Completed
Branch master (d65695)
by
unknown
04:25
created
core/db_models/EEM_Price.model.php 1 patch
Indentation   +337 added lines, -337 removed lines patch added patch discarded remove patch
@@ -12,368 +12,368 @@
 block discarded – undo
12 12
  */
13 13
 class EEM_Price extends EEM_Soft_Delete_Base
14 14
 {
15
-    // private instance of the EEM_Price object
16
-    protected static $_instance;
15
+	// private instance of the EEM_Price object
16
+	protected static $_instance;
17 17
 
18 18
 
19
-    /**
20
-     * private constructor to prevent direct creation
21
-     *
22
-     * @Constructor
23
-     * @param string $timezone string representing the timezone we want to set for returned Date Time Strings
24
-     *                         (and any incoming timezone data that gets saved).
25
-     *                         Note this just sends the timezone info to the date time model field objects.
26
-     *                         Default is NULL
27
-     *                         (and will be assumed using the set timezone in the 'timezone_string' wp option)
28
-     */
29
-    protected function __construct($timezone)
30
-    {
31
-        $this->singular_item = __('Price', 'event_espresso');
32
-        $this->plural_item   = __('Prices', 'event_espresso');
19
+	/**
20
+	 * private constructor to prevent direct creation
21
+	 *
22
+	 * @Constructor
23
+	 * @param string $timezone string representing the timezone we want to set for returned Date Time Strings
24
+	 *                         (and any incoming timezone data that gets saved).
25
+	 *                         Note this just sends the timezone info to the date time model field objects.
26
+	 *                         Default is NULL
27
+	 *                         (and will be assumed using the set timezone in the 'timezone_string' wp option)
28
+	 */
29
+	protected function __construct($timezone)
30
+	{
31
+		$this->singular_item = __('Price', 'event_espresso');
32
+		$this->plural_item   = __('Prices', 'event_espresso');
33 33
 
34
-        $this->_tables          = [
35
-            'Price' => new EE_Primary_Table('esp_price', 'PRC_ID'),
36
-        ];
37
-        $this->_fields          = [
38
-            'Price' => [
39
-                'PRC_ID'         => new EE_Primary_Key_Int_Field(
40
-                    'PRC_ID',
41
-                    'Price ID'
42
-                ),
43
-                'PRT_ID'         => new EE_Foreign_Key_Int_Field(
44
-                    'PRT_ID',
45
-                    esc_html__('Price type Id', 'event_espresso'),
46
-                    false,
47
-                    null,
48
-                    'Price_Type'
49
-                ),
50
-                'PRC_amount'     => new EE_Money_Field(
51
-                    'PRC_amount',
52
-                    esc_html__('Price Amount', 'event_espresso'),
53
-                    false,
54
-                    0
55
-                ),
56
-                'PRC_name'       => new EE_Plain_Text_Field(
57
-                    'PRC_name',
58
-                    esc_html__('Name of Price', 'event_espresso'),
59
-                    false,
60
-                    ''
61
-                ),
62
-                'PRC_desc'       => new EE_Post_Content_Field(
63
-                    'PRC_desc',
64
-                    esc_html__('Price Description', 'event_espresso'),
65
-                    false,
66
-                    ''
67
-                ),
68
-                'PRC_is_default' => new EE_Boolean_Field(
69
-                    'PRC_is_default',
70
-                    esc_html__('Flag indicating whether price is a default price', 'event_espresso'),
71
-                    false,
72
-                    false
73
-                ),
74
-                'PRC_overrides'  => new EE_Integer_Field(
75
-                    'PRC_overrides',
76
-                    esc_html__(
77
-                        'Price ID for a global Price that will be overridden by this Price  ( for replacing default prices )',
78
-                        'event_espresso'
79
-                    ),
80
-                    true,
81
-                    0
82
-                ),
83
-                'PRC_order'      => new EE_Integer_Field(
84
-                    'PRC_order',
85
-                    esc_html__(
86
-                        'Order of Application of Price (lower numbers apply first?)',
87
-                        'event_espresso'
88
-                    ),
89
-                    false,
90
-                    1
91
-                ),
92
-                'PRC_deleted'    => new EE_Trashed_Flag_Field(
93
-                    'PRC_deleted',
94
-                    esc_html__('Flag Indicating if this has been deleted or not', 'event_espresso'),
95
-                    false,
96
-                    false
97
-                ),
98
-                'PRC_parent'     => new EE_Integer_Field(
99
-                    'PRC_parent',
100
-                    esc_html__('Indicates what PRC_ID is the parent of this PRC_ID', 'event_espresso'),
101
-                    true,
102
-                    0
103
-                ),
104
-                'PRC_wp_user'    => new EE_WP_User_Field(
105
-                    'PRC_wp_user',
106
-                    esc_html__('Price Creator ID', 'event_espresso'),
107
-                    false
108
-                ),
109
-            ],
110
-        ];
111
-        $this->_model_relations = [
112
-            'Ticket'     => new EE_HABTM_Relation('Ticket_Price'),
113
-            'Price_Type' => new EE_Belongs_To_Relation(),
114
-            'WP_User'    => new EE_Belongs_To_Relation(),
115
-        ];
116
-        // this model is generally available for reading
117
-        $this->_cap_restriction_generators[ EEM_Base::caps_read ] =
118
-            new EE_Restriction_Generator_Default_Public(
119
-                'PRC_is_default',
120
-                'Ticket.Datetime.Event'
121
-            );
122
-        // account for default tickets in the caps
123
-        $this->_cap_restriction_generators[ EEM_Base::caps_read_admin ] =
124
-            new EE_Restriction_Generator_Default_Protected(
125
-                'PRC_is_default',
126
-                'Ticket.Datetime.Event'
127
-            );
128
-        $this->_cap_restriction_generators[ EEM_Base::caps_edit ]       =
129
-            new EE_Restriction_Generator_Default_Protected(
130
-                'PRC_is_default',
131
-                'Ticket.Datetime.Event'
132
-            );
133
-        $this->_cap_restriction_generators[ EEM_Base::caps_delete ]     =
134
-            new EE_Restriction_Generator_Default_Protected(
135
-                'PRC_is_default',
136
-                'Ticket.Datetime.Event'
137
-            );
138
-        parent::__construct($timezone);
139
-    }
34
+		$this->_tables          = [
35
+			'Price' => new EE_Primary_Table('esp_price', 'PRC_ID'),
36
+		];
37
+		$this->_fields          = [
38
+			'Price' => [
39
+				'PRC_ID'         => new EE_Primary_Key_Int_Field(
40
+					'PRC_ID',
41
+					'Price ID'
42
+				),
43
+				'PRT_ID'         => new EE_Foreign_Key_Int_Field(
44
+					'PRT_ID',
45
+					esc_html__('Price type Id', 'event_espresso'),
46
+					false,
47
+					null,
48
+					'Price_Type'
49
+				),
50
+				'PRC_amount'     => new EE_Money_Field(
51
+					'PRC_amount',
52
+					esc_html__('Price Amount', 'event_espresso'),
53
+					false,
54
+					0
55
+				),
56
+				'PRC_name'       => new EE_Plain_Text_Field(
57
+					'PRC_name',
58
+					esc_html__('Name of Price', 'event_espresso'),
59
+					false,
60
+					''
61
+				),
62
+				'PRC_desc'       => new EE_Post_Content_Field(
63
+					'PRC_desc',
64
+					esc_html__('Price Description', 'event_espresso'),
65
+					false,
66
+					''
67
+				),
68
+				'PRC_is_default' => new EE_Boolean_Field(
69
+					'PRC_is_default',
70
+					esc_html__('Flag indicating whether price is a default price', 'event_espresso'),
71
+					false,
72
+					false
73
+				),
74
+				'PRC_overrides'  => new EE_Integer_Field(
75
+					'PRC_overrides',
76
+					esc_html__(
77
+						'Price ID for a global Price that will be overridden by this Price  ( for replacing default prices )',
78
+						'event_espresso'
79
+					),
80
+					true,
81
+					0
82
+				),
83
+				'PRC_order'      => new EE_Integer_Field(
84
+					'PRC_order',
85
+					esc_html__(
86
+						'Order of Application of Price (lower numbers apply first?)',
87
+						'event_espresso'
88
+					),
89
+					false,
90
+					1
91
+				),
92
+				'PRC_deleted'    => new EE_Trashed_Flag_Field(
93
+					'PRC_deleted',
94
+					esc_html__('Flag Indicating if this has been deleted or not', 'event_espresso'),
95
+					false,
96
+					false
97
+				),
98
+				'PRC_parent'     => new EE_Integer_Field(
99
+					'PRC_parent',
100
+					esc_html__('Indicates what PRC_ID is the parent of this PRC_ID', 'event_espresso'),
101
+					true,
102
+					0
103
+				),
104
+				'PRC_wp_user'    => new EE_WP_User_Field(
105
+					'PRC_wp_user',
106
+					esc_html__('Price Creator ID', 'event_espresso'),
107
+					false
108
+				),
109
+			],
110
+		];
111
+		$this->_model_relations = [
112
+			'Ticket'     => new EE_HABTM_Relation('Ticket_Price'),
113
+			'Price_Type' => new EE_Belongs_To_Relation(),
114
+			'WP_User'    => new EE_Belongs_To_Relation(),
115
+		];
116
+		// this model is generally available for reading
117
+		$this->_cap_restriction_generators[ EEM_Base::caps_read ] =
118
+			new EE_Restriction_Generator_Default_Public(
119
+				'PRC_is_default',
120
+				'Ticket.Datetime.Event'
121
+			);
122
+		// account for default tickets in the caps
123
+		$this->_cap_restriction_generators[ EEM_Base::caps_read_admin ] =
124
+			new EE_Restriction_Generator_Default_Protected(
125
+				'PRC_is_default',
126
+				'Ticket.Datetime.Event'
127
+			);
128
+		$this->_cap_restriction_generators[ EEM_Base::caps_edit ]       =
129
+			new EE_Restriction_Generator_Default_Protected(
130
+				'PRC_is_default',
131
+				'Ticket.Datetime.Event'
132
+			);
133
+		$this->_cap_restriction_generators[ EEM_Base::caps_delete ]     =
134
+			new EE_Restriction_Generator_Default_Protected(
135
+				'PRC_is_default',
136
+				'Ticket.Datetime.Event'
137
+			);
138
+		parent::__construct($timezone);
139
+	}
140 140
 
141 141
 
142
-    /**
143
-     * instantiate a new price object with blank/empty properties
144
-     *
145
-     * @return mixed array on success, FALSE on fail
146
-     */
147
-    public function get_new_price()
148
-    {
149
-        return $this->create_default_object();
150
-    }
142
+	/**
143
+	 * instantiate a new price object with blank/empty properties
144
+	 *
145
+	 * @return mixed array on success, FALSE on fail
146
+	 */
147
+	public function get_new_price()
148
+	{
149
+		return $this->create_default_object();
150
+	}
151 151
 
152 152
 
153
-    /**
154
-     * retrieve  ALL prices from db
155
-     *
156
-     * @return EE_Base_Class[]|EE_PRice[]
157
-     * @throws EE_Error
158
-     */
159
-    public function get_all_prices()
160
-    {
161
-        // retrieve all prices
162
-        return $this->get_all(['order_by' => ['PRC_amount' => 'ASC']]);
163
-    }
153
+	/**
154
+	 * retrieve  ALL prices from db
155
+	 *
156
+	 * @return EE_Base_Class[]|EE_PRice[]
157
+	 * @throws EE_Error
158
+	 */
159
+	public function get_all_prices()
160
+	{
161
+		// retrieve all prices
162
+		return $this->get_all(['order_by' => ['PRC_amount' => 'ASC']]);
163
+	}
164 164
 
165 165
 
166
-    /**
167
-     * retrieve all active prices for a particular event
168
-     *
169
-     * @param int $EVT_ID
170
-     * @return array on success
171
-     * @throws EE_Error
172
-     */
173
-    public function get_all_event_prices($EVT_ID = 0)
174
-    {
175
-        return $this->get_all(
176
-            [
177
-                [
178
-                    'EVT_ID'            => $EVT_ID,
179
-                    'Price_Type.PBT_ID' => ['!=', EEM_Price_Type::base_type_tax],
180
-                ],
181
-                'order_by' => $this->_order_by_array_for_get_all_method(),
182
-            ]
183
-        );
184
-    }
166
+	/**
167
+	 * retrieve all active prices for a particular event
168
+	 *
169
+	 * @param int $EVT_ID
170
+	 * @return array on success
171
+	 * @throws EE_Error
172
+	 */
173
+	public function get_all_event_prices($EVT_ID = 0)
174
+	{
175
+		return $this->get_all(
176
+			[
177
+				[
178
+					'EVT_ID'            => $EVT_ID,
179
+					'Price_Type.PBT_ID' => ['!=', EEM_Price_Type::base_type_tax],
180
+				],
181
+				'order_by' => $this->_order_by_array_for_get_all_method(),
182
+			]
183
+		);
184
+	}
185 185
 
186 186
 
187
-    /**
188
-     * retrieve all active global prices (that are not taxes (PBT_ID=4)) for a particular event
189
-     *
190
-     * @param boolean $count return count
191
-     * @param bool    $include_taxes
192
-     * @return bool|EE_Base_Class[]|EE_PRice[]
193
-     * @throws EE_Error
194
-     */
195
-    public function get_all_default_prices($count = false, $include_taxes = false)
196
-    {
197
-        $_where = [
198
-            'PRC_deleted'    => 0,
199
-            'PRC_is_default' => 1,
200
-        ];
201
-        if (! $include_taxes) {
202
-            $_where['Price_Type.PBT_ID'] = ['!=', 4];
203
-        }
204
-        $_query_params = [
205
-            $_where,
206
-            'order_by' => $this->_order_by_array_for_get_all_method(),
207
-        ];
208
-        return $count ? $this->count([$_where]) : $this->get_all($_query_params);
209
-    }
187
+	/**
188
+	 * retrieve all active global prices (that are not taxes (PBT_ID=4)) for a particular event
189
+	 *
190
+	 * @param boolean $count return count
191
+	 * @param bool    $include_taxes
192
+	 * @return bool|EE_Base_Class[]|EE_PRice[]
193
+	 * @throws EE_Error
194
+	 */
195
+	public function get_all_default_prices($count = false, $include_taxes = false)
196
+	{
197
+		$_where = [
198
+			'PRC_deleted'    => 0,
199
+			'PRC_is_default' => 1,
200
+		];
201
+		if (! $include_taxes) {
202
+			$_where['Price_Type.PBT_ID'] = ['!=', 4];
203
+		}
204
+		$_query_params = [
205
+			$_where,
206
+			'order_by' => $this->_order_by_array_for_get_all_method(),
207
+		];
208
+		return $count ? $this->count([$_where]) : $this->get_all($_query_params);
209
+	}
210 210
 
211 211
 
212
-    /**
213
-     * retrieve all active global prices that are taxes
214
-     *
215
-     * @return bool|EE_Base_Class[]|EE_PRice[]
216
-     * @throws EE_Error
217
-     * @since   5.0.0.p
218
-     */
219
-    public function getAllDefaultTaxes()
220
-    {
221
-        return $this->get_all(
222
-            [
223
-                [
224
-                    'PRC_deleted'    => 0,
225
-                    'PRC_is_default' => 1,
226
-                    'Price_Type.PBT_ID' => EEM_Price_Type::base_type_tax
227
-                ],
228
-                'order_by' => [
229
-                    'Price_Type.PRT_order' => 'ASC',
230
-                    'PRC_order' => 'ASC'
231
-                ],
232
-            ]
233
-        );
234
-    }
212
+	/**
213
+	 * retrieve all active global prices that are taxes
214
+	 *
215
+	 * @return bool|EE_Base_Class[]|EE_PRice[]
216
+	 * @throws EE_Error
217
+	 * @since   5.0.0.p
218
+	 */
219
+	public function getAllDefaultTaxes()
220
+	{
221
+		return $this->get_all(
222
+			[
223
+				[
224
+					'PRC_deleted'    => 0,
225
+					'PRC_is_default' => 1,
226
+					'Price_Type.PBT_ID' => EEM_Price_Type::base_type_tax
227
+				],
228
+				'order_by' => [
229
+					'Price_Type.PRT_order' => 'ASC',
230
+					'PRC_order' => 'ASC'
231
+				],
232
+			]
233
+		);
234
+	}
235 235
 
236 236
 
237
-    /**
238
-     * retrieve all prices that are taxes
239
-     *
240
-     * @return EE_Base_Class[]|EE_PRice[]
241
-     * @throws EE_Error
242
-     * @throws InvalidArgumentException
243
-     * @throws ReflectionException
244
-     * @throws InvalidDataTypeException
245
-     * @throws InvalidInterfaceException
246
-     */
247
-    public function get_all_prices_that_are_taxes()
248
-    {
249
-        $taxes     = [];
250
-        $all_taxes = $this->get_all(
251
-            [
252
-                ['Price_Type.PBT_ID' => EEM_Price_Type::base_type_tax, 'PRC_is_default' => 1],
253
-                'order_by' => ['Price_Type.PRT_order' => 'ASC', 'PRC_order' => 'ASC'],
254
-            ]
255
-        );
256
-        foreach ($all_taxes as $tax) {
257
-            if ($tax instanceof EE_Price) {
258
-                $taxes[ $tax->order() ][ $tax->ID() ] = $tax;
259
-            }
260
-        }
261
-        return $taxes;
262
-    }
237
+	/**
238
+	 * retrieve all prices that are taxes
239
+	 *
240
+	 * @return EE_Base_Class[]|EE_PRice[]
241
+	 * @throws EE_Error
242
+	 * @throws InvalidArgumentException
243
+	 * @throws ReflectionException
244
+	 * @throws InvalidDataTypeException
245
+	 * @throws InvalidInterfaceException
246
+	 */
247
+	public function get_all_prices_that_are_taxes()
248
+	{
249
+		$taxes     = [];
250
+		$all_taxes = $this->get_all(
251
+			[
252
+				['Price_Type.PBT_ID' => EEM_Price_Type::base_type_tax, 'PRC_is_default' => 1],
253
+				'order_by' => ['Price_Type.PRT_order' => 'ASC', 'PRC_order' => 'ASC'],
254
+			]
255
+		);
256
+		foreach ($all_taxes as $tax) {
257
+			if ($tax instanceof EE_Price) {
258
+				$taxes[ $tax->order() ][ $tax->ID() ] = $tax;
259
+			}
260
+		}
261
+		return $taxes;
262
+	}
263 263
 
264 264
 
265
-    /**
266
-     * retrieve all prices for an ticket plus default global prices, but not taxes
267
-     *
268
-     * @param int $TKT_ID the id of the event.  If not included then we assume that this is a new ticket.
269
-     * @return EE_Base_Class[]|EE_PRice[]|boolean
270
-     * @throws EE_Error
271
-     */
272
-    public function get_all_ticket_prices_for_admin($TKT_ID = 0)
273
-    {
274
-        $array_of_price_objects = [];
275
-        if (empty($TKT_ID)) {
276
-            // if there is no tkt, get prices with no tkt ID, are global, are not a tax, and are active
277
-            // return that list
278
-            $default_prices = $this->get_all_default_prices();
265
+	/**
266
+	 * retrieve all prices for an ticket plus default global prices, but not taxes
267
+	 *
268
+	 * @param int $TKT_ID the id of the event.  If not included then we assume that this is a new ticket.
269
+	 * @return EE_Base_Class[]|EE_PRice[]|boolean
270
+	 * @throws EE_Error
271
+	 */
272
+	public function get_all_ticket_prices_for_admin($TKT_ID = 0)
273
+	{
274
+		$array_of_price_objects = [];
275
+		if (empty($TKT_ID)) {
276
+			// if there is no tkt, get prices with no tkt ID, are global, are not a tax, and are active
277
+			// return that list
278
+			$default_prices = $this->get_all_default_prices();
279 279
 
280
-            if ($default_prices) {
281
-                foreach ($default_prices as $price) {
282
-                    if ($price instanceof EE_Price) {
283
-                        $array_of_price_objects[ $price->type() ][] = $price;
284
-                    }
285
-                }
286
-                return $array_of_price_objects;
287
-            }
288
-            return [];
289
-        }
290
-        $ticket_prices = $this->get_all(
291
-            [
292
-                [
293
-                    'TKT_ID'      => $TKT_ID,
294
-                    'PRC_deleted' => 0,
295
-                ],
296
-                'order_by' => ['PRC_order' => 'ASC'],
297
-            ]
298
-        );
280
+			if ($default_prices) {
281
+				foreach ($default_prices as $price) {
282
+					if ($price instanceof EE_Price) {
283
+						$array_of_price_objects[ $price->type() ][] = $price;
284
+					}
285
+				}
286
+				return $array_of_price_objects;
287
+			}
288
+			return [];
289
+		}
290
+		$ticket_prices = $this->get_all(
291
+			[
292
+				[
293
+					'TKT_ID'      => $TKT_ID,
294
+					'PRC_deleted' => 0,
295
+				],
296
+				'order_by' => ['PRC_order' => 'ASC'],
297
+			]
298
+		);
299 299
 
300
-        if (! empty($ticket_prices)) {
301
-            foreach ($ticket_prices as $price) {
302
-                if ($price instanceof EE_Price) {
303
-                    $array_of_price_objects[ $price->type() ][] = $price;
304
-                }
305
-            }
306
-            return $array_of_price_objects;
307
-        }
308
-        return false;
309
-    }
300
+		if (! empty($ticket_prices)) {
301
+			foreach ($ticket_prices as $price) {
302
+				if ($price instanceof EE_Price) {
303
+					$array_of_price_objects[ $price->type() ][] = $price;
304
+				}
305
+			}
306
+			return $array_of_price_objects;
307
+		}
308
+		return false;
309
+	}
310 310
 
311 311
 
312
-    /**
313
-     * _sort_event_prices_by_type
314
-     *
315
-     * @param EE_Price $price_a
316
-     * @param EE_Price $price_b
317
-     * @return bool false on fail
318
-     */
319
-    public function _sort_event_prices_by_type(EE_Price $price_a, EE_Price $price_b)
320
-    {
321
-        if ($price_a->type_obj()->order() === $price_b->type_obj()->order()) {
322
-            return $this->_sort_event_prices_by_order($price_a, $price_b);
323
-        }
324
-        return $price_a->type_obj()->order() < $price_b->type_obj()->order() ? -1 : 1;
325
-    }
312
+	/**
313
+	 * _sort_event_prices_by_type
314
+	 *
315
+	 * @param EE_Price $price_a
316
+	 * @param EE_Price $price_b
317
+	 * @return bool false on fail
318
+	 */
319
+	public function _sort_event_prices_by_type(EE_Price $price_a, EE_Price $price_b)
320
+	{
321
+		if ($price_a->type_obj()->order() === $price_b->type_obj()->order()) {
322
+			return $this->_sort_event_prices_by_order($price_a, $price_b);
323
+		}
324
+		return $price_a->type_obj()->order() < $price_b->type_obj()->order() ? -1 : 1;
325
+	}
326 326
 
327 327
 
328
-    /**
329
-     *        _sort_event_prices_by_order
330
-     *
331
-     * @param EE_Price $price_a
332
-     * @param EE_Price $price_b
333
-     * @return bool false on fail
334
-     */
335
-    public function _sort_event_prices_by_order(EE_Price $price_a, EE_Price $price_b)
336
-    {
337
-        if ($price_a->order() === $price_b->order()) {
338
-            return 0;
339
-        }
340
-        return $price_a->order() < $price_b->order() ? -1 : 1;
341
-    }
328
+	/**
329
+	 *        _sort_event_prices_by_order
330
+	 *
331
+	 * @param EE_Price $price_a
332
+	 * @param EE_Price $price_b
333
+	 * @return bool false on fail
334
+	 */
335
+	public function _sort_event_prices_by_order(EE_Price $price_a, EE_Price $price_b)
336
+	{
337
+		if ($price_a->order() === $price_b->order()) {
338
+			return 0;
339
+		}
340
+		return $price_a->order() < $price_b->order() ? -1 : 1;
341
+	}
342 342
 
343 343
 
344
-    /**
345
-     * get all prices of a specific type
346
-     *
347
-     * @param int $type - PRT_ID
348
-     * @return EE_Base_Class[]|EE_PRice[]
349
-     * @throws EE_Error
350
-     */
351
-    public function get_all_prices_that_are_type($type = 0)
352
-    {
353
-        return $this->get_all(
354
-            [
355
-                [
356
-                    'PRT_ID' => $type,
357
-                ],
358
-                'order_by' => $this->_order_by_array_for_get_all_method(),
359
-            ]
360
-        );
361
-    }
344
+	/**
345
+	 * get all prices of a specific type
346
+	 *
347
+	 * @param int $type - PRT_ID
348
+	 * @return EE_Base_Class[]|EE_PRice[]
349
+	 * @throws EE_Error
350
+	 */
351
+	public function get_all_prices_that_are_type($type = 0)
352
+	{
353
+		return $this->get_all(
354
+			[
355
+				[
356
+					'PRT_ID' => $type,
357
+				],
358
+				'order_by' => $this->_order_by_array_for_get_all_method(),
359
+			]
360
+		);
361
+	}
362 362
 
363 363
 
364
-    /**
365
-     * Returns an array of the normal 'order_by' query parameter provided to the get_all query.
366
-     * Of course you don't have to use it, but this is the order we usually want to sort prices by
367
-     *
368
-     * @return array which can be used like so: $this->get_all(array(array(...where
369
-     *               stuff...),'order_by'=>$this->_order_by_array_for_get_all_method()));
370
-     */
371
-    public function _order_by_array_for_get_all_method()
372
-    {
373
-        return [
374
-            'PRC_order'            => 'ASC',
375
-            'Price_Type.PRT_order' => 'ASC',
376
-            'PRC_ID'               => 'ASC',
377
-        ];
378
-    }
364
+	/**
365
+	 * Returns an array of the normal 'order_by' query parameter provided to the get_all query.
366
+	 * Of course you don't have to use it, but this is the order we usually want to sort prices by
367
+	 *
368
+	 * @return array which can be used like so: $this->get_all(array(array(...where
369
+	 *               stuff...),'order_by'=>$this->_order_by_array_for_get_all_method()));
370
+	 */
371
+	public function _order_by_array_for_get_all_method()
372
+	{
373
+		return [
374
+			'PRC_order'            => 'ASC',
375
+			'Price_Type.PRT_order' => 'ASC',
376
+			'PRC_ID'               => 'ASC',
377
+		];
378
+	}
379 379
 }
Please login to merge, or discard this patch.
strategies/EE_Restriction_Generator_Default_Protected.strategy.php 1 patch
Indentation   +160 added lines, -160 removed lines patch added patch discarded remove patch
@@ -14,164 +14,164 @@
 block discarded – undo
14 14
  */
15 15
 class EE_Restriction_Generator_Default_Protected extends EE_Restriction_Generator_Base
16 16
 {
17
-    /**
18
-     * Name of the field on this model (or a related model, including the model chain to it)
19
-     * that is a boolean indicating whether or not a model object is considered "Default" or not
20
-     *
21
-     * @var string
22
-     */
23
-    protected $_default_field_name;
24
-
25
-    /**
26
-     * The model chain to follow to get to the event model, including the event model itself.
27
-     * Eg 'Ticket.Datetime.Event'
28
-     *
29
-     * @var string
30
-     */
31
-    protected $_path_to_event_model;
32
-
33
-
34
-    /**
35
-     * @param string $default_field_name  the name of the field Name of the field on this model
36
-     *                                    (or a related model, including the model chain to it)
37
-     *                                    that is a boolean indicating whether or not a model object
38
-     *                                    is considered "Default" or not
39
-     * @param string $path_to_event_model The model chain to follow to get to the event model,
40
-     *                                    including the event model itself. Eg 'Ticket.Datetime.Event'
41
-     */
42
-    public function __construct(string $default_field_name, string $path_to_event_model)
43
-    {
44
-        $this->_default_field_name  = $default_field_name;
45
-        $this->_path_to_event_model = rtrim($path_to_event_model, '.') . '.';
46
-    }
47
-
48
-
49
-    /**
50
-     * @return EE_Default_Where_Conditions[]|EE_Return_None_Where_Conditions[]
51
-     * @throws EE_Error
52
-     */
53
-    protected function _generate_restrictions(): array
54
-    {
55
-        // if there are no standard caps for this model, then for now
56
-        // all we know is if they need the default cap to access this
57
-        if (! $this->model()->cap_slug()) {
58
-            return [
59
-                self::get_default_restrictions_cap() => new EE_Return_None_Where_Conditions(),
60
-            ];
61
-        }
62
-
63
-        $action         = $this->action();
64
-        $others         = "{$action}_others";
65
-        $private        = "{$action}_private";
66
-        $default        = "{$action}_default";
67
-        $others_default = "{$action}_others_default";
68
-        $event_model    = EEM_Event::instance();
69
-
70
-        $restrictions = [
71
-            // first: access to non-defaults is essentially controlled by which events are accessible
72
-            // if they don't have the basic event cap, they can't access ANY non-default items
73
-            $this->getCapKey($event_model, $action)    => $this->nonDefaultRestrictions(true),
74
-            // if they don't have the others event cap, they can't access others' non-default items
75
-            $this->getCapKey($event_model, $others)    => $this->othersNonDefaultRestrictions($event_model, $others),
76
-            // if they have basic and others, but not private, they can't access others' private non-default items
77
-            $this->getCapKey($event_model, $private)   => $this->privateRestrictions($event_model, $private),
78
-            // second: access to defaults is controlled by the default capabilities
79
-            // if they don't have the default capability, restrict access to only non-default items
80
-            $this->getCapKey($this->model(), $default) => $this->nonDefaultRestrictions(false),
81
-        ];
82
-        // if they don't have the "others" default capability,
83
-        // restrict access to only their default ones, and non-default ones
84
-        if (EE_Restriction_Generator_Base::is_cap($this->model(), $others_default)) {
85
-            $restrictions[ $this->getCapKey($this->model(), $others_default) ] = $this->othersDefaultRestrictions(
86
-                $others_default
87
-            );
88
-        }
89
-        return $restrictions;
90
-    }
91
-
92
-
93
-    /**
94
-     * @param EEM_Base $model
95
-     * @param string   $action
96
-     * @return string
97
-     * @since   5.0.0.p
98
-     */
99
-    private function getCapKey(EEM_Base $model, string $action): string
100
-    {
101
-        return EE_Restriction_Generator_Base::get_cap_name($model, $action);
102
-    }
103
-
104
-
105
-    /**
106
-     * @param bool $use_default_field_name
107
-     * @return EE_Default_Where_Conditions
108
-     * @since   5.0.0.p
109
-     */
110
-    private function nonDefaultRestrictions(bool $use_default_field_name): EE_Default_Where_Conditions
111
-    {
112
-        return new EE_Default_Where_Conditions([$this->_default_field_name => $use_default_field_name]);
113
-    }
114
-
115
-
116
-    /**
117
-     * @param string $action
118
-     * @return EE_Default_Where_Conditions
119
-     * @throws EE_Error
120
-     * @since   5.0.0.p
121
-     */
122
-    private function othersDefaultRestrictions(string $action): EE_Default_Where_Conditions
123
-    {
124
-        return new EE_Default_Where_Conditions(
125
-            [
126
-                // if they don't have the others default cap, they can't access others default items
127
-                // (but they can access their own default items, and non-default items)
128
-                'OR*no_' . $this->getCapKey($this->model(), $action) => [
129
-                    'AND'                      => [
130
-                        $this->_path_to_event_model . 'EVT_wp_user' => EE_QUERY_PLACEHOLDER_CURRENT_USER,
131
-                        $this->_default_field_name                  => true,
132
-                    ],
133
-                    $this->_default_field_name => false,
134
-                ],
135
-            ]
136
-        );
137
-    }
138
-
139
-
140
-    /**
141
-     * @param EEM_Event $event_model
142
-     * @param string    $action
143
-     * @return EE_Default_Where_Conditions
144
-     * @since   5.0.0.p
145
-     */
146
-    private function othersNonDefaultRestrictions(EEM_Event $event_model, string $action): EE_Default_Where_Conditions
147
-    {
148
-        return new EE_Default_Where_Conditions(
149
-            [
150
-                'OR*no_' . $this->getCapKey($event_model, $action) => [
151
-                    $this->_path_to_event_model . 'EVT_wp_user' => EE_QUERY_PLACEHOLDER_CURRENT_USER,
152
-                ],
153
-                $this->_default_field_name                         => true,
154
-            ]
155
-        );
156
-    }
157
-
158
-
159
-    /**
160
-     * @param EEM_Event $event_model
161
-     * @param string    $action
162
-     * @return EE_Default_Where_Conditions
163
-     * @since   5.0.0.p
164
-     */
165
-    private function privateRestrictions(EEM_Event $event_model, string $action): EE_Default_Where_Conditions
166
-    {
167
-        return new EE_Default_Where_Conditions(
168
-            [
169
-                'OR*no_' . $this->getCapKey($event_model, $action) => [
170
-                    $this->_path_to_event_model . 'EVT_wp_user' => EE_QUERY_PLACEHOLDER_CURRENT_USER,
171
-                    $this->_path_to_event_model . 'status'      => ['!=', 'private'],
172
-                    $this->_default_field_name                  => true,
173
-                ],
174
-            ]
175
-        );
176
-    }
17
+	/**
18
+	 * Name of the field on this model (or a related model, including the model chain to it)
19
+	 * that is a boolean indicating whether or not a model object is considered "Default" or not
20
+	 *
21
+	 * @var string
22
+	 */
23
+	protected $_default_field_name;
24
+
25
+	/**
26
+	 * The model chain to follow to get to the event model, including the event model itself.
27
+	 * Eg 'Ticket.Datetime.Event'
28
+	 *
29
+	 * @var string
30
+	 */
31
+	protected $_path_to_event_model;
32
+
33
+
34
+	/**
35
+	 * @param string $default_field_name  the name of the field Name of the field on this model
36
+	 *                                    (or a related model, including the model chain to it)
37
+	 *                                    that is a boolean indicating whether or not a model object
38
+	 *                                    is considered "Default" or not
39
+	 * @param string $path_to_event_model The model chain to follow to get to the event model,
40
+	 *                                    including the event model itself. Eg 'Ticket.Datetime.Event'
41
+	 */
42
+	public function __construct(string $default_field_name, string $path_to_event_model)
43
+	{
44
+		$this->_default_field_name  = $default_field_name;
45
+		$this->_path_to_event_model = rtrim($path_to_event_model, '.') . '.';
46
+	}
47
+
48
+
49
+	/**
50
+	 * @return EE_Default_Where_Conditions[]|EE_Return_None_Where_Conditions[]
51
+	 * @throws EE_Error
52
+	 */
53
+	protected function _generate_restrictions(): array
54
+	{
55
+		// if there are no standard caps for this model, then for now
56
+		// all we know is if they need the default cap to access this
57
+		if (! $this->model()->cap_slug()) {
58
+			return [
59
+				self::get_default_restrictions_cap() => new EE_Return_None_Where_Conditions(),
60
+			];
61
+		}
62
+
63
+		$action         = $this->action();
64
+		$others         = "{$action}_others";
65
+		$private        = "{$action}_private";
66
+		$default        = "{$action}_default";
67
+		$others_default = "{$action}_others_default";
68
+		$event_model    = EEM_Event::instance();
69
+
70
+		$restrictions = [
71
+			// first: access to non-defaults is essentially controlled by which events are accessible
72
+			// if they don't have the basic event cap, they can't access ANY non-default items
73
+			$this->getCapKey($event_model, $action)    => $this->nonDefaultRestrictions(true),
74
+			// if they don't have the others event cap, they can't access others' non-default items
75
+			$this->getCapKey($event_model, $others)    => $this->othersNonDefaultRestrictions($event_model, $others),
76
+			// if they have basic and others, but not private, they can't access others' private non-default items
77
+			$this->getCapKey($event_model, $private)   => $this->privateRestrictions($event_model, $private),
78
+			// second: access to defaults is controlled by the default capabilities
79
+			// if they don't have the default capability, restrict access to only non-default items
80
+			$this->getCapKey($this->model(), $default) => $this->nonDefaultRestrictions(false),
81
+		];
82
+		// if they don't have the "others" default capability,
83
+		// restrict access to only their default ones, and non-default ones
84
+		if (EE_Restriction_Generator_Base::is_cap($this->model(), $others_default)) {
85
+			$restrictions[ $this->getCapKey($this->model(), $others_default) ] = $this->othersDefaultRestrictions(
86
+				$others_default
87
+			);
88
+		}
89
+		return $restrictions;
90
+	}
91
+
92
+
93
+	/**
94
+	 * @param EEM_Base $model
95
+	 * @param string   $action
96
+	 * @return string
97
+	 * @since   5.0.0.p
98
+	 */
99
+	private function getCapKey(EEM_Base $model, string $action): string
100
+	{
101
+		return EE_Restriction_Generator_Base::get_cap_name($model, $action);
102
+	}
103
+
104
+
105
+	/**
106
+	 * @param bool $use_default_field_name
107
+	 * @return EE_Default_Where_Conditions
108
+	 * @since   5.0.0.p
109
+	 */
110
+	private function nonDefaultRestrictions(bool $use_default_field_name): EE_Default_Where_Conditions
111
+	{
112
+		return new EE_Default_Where_Conditions([$this->_default_field_name => $use_default_field_name]);
113
+	}
114
+
115
+
116
+	/**
117
+	 * @param string $action
118
+	 * @return EE_Default_Where_Conditions
119
+	 * @throws EE_Error
120
+	 * @since   5.0.0.p
121
+	 */
122
+	private function othersDefaultRestrictions(string $action): EE_Default_Where_Conditions
123
+	{
124
+		return new EE_Default_Where_Conditions(
125
+			[
126
+				// if they don't have the others default cap, they can't access others default items
127
+				// (but they can access their own default items, and non-default items)
128
+				'OR*no_' . $this->getCapKey($this->model(), $action) => [
129
+					'AND'                      => [
130
+						$this->_path_to_event_model . 'EVT_wp_user' => EE_QUERY_PLACEHOLDER_CURRENT_USER,
131
+						$this->_default_field_name                  => true,
132
+					],
133
+					$this->_default_field_name => false,
134
+				],
135
+			]
136
+		);
137
+	}
138
+
139
+
140
+	/**
141
+	 * @param EEM_Event $event_model
142
+	 * @param string    $action
143
+	 * @return EE_Default_Where_Conditions
144
+	 * @since   5.0.0.p
145
+	 */
146
+	private function othersNonDefaultRestrictions(EEM_Event $event_model, string $action): EE_Default_Where_Conditions
147
+	{
148
+		return new EE_Default_Where_Conditions(
149
+			[
150
+				'OR*no_' . $this->getCapKey($event_model, $action) => [
151
+					$this->_path_to_event_model . 'EVT_wp_user' => EE_QUERY_PLACEHOLDER_CURRENT_USER,
152
+				],
153
+				$this->_default_field_name                         => true,
154
+			]
155
+		);
156
+	}
157
+
158
+
159
+	/**
160
+	 * @param EEM_Event $event_model
161
+	 * @param string    $action
162
+	 * @return EE_Default_Where_Conditions
163
+	 * @since   5.0.0.p
164
+	 */
165
+	private function privateRestrictions(EEM_Event $event_model, string $action): EE_Default_Where_Conditions
166
+	{
167
+		return new EE_Default_Where_Conditions(
168
+			[
169
+				'OR*no_' . $this->getCapKey($event_model, $action) => [
170
+					$this->_path_to_event_model . 'EVT_wp_user' => EE_QUERY_PLACEHOLDER_CURRENT_USER,
171
+					$this->_path_to_event_model . 'status'      => ['!=', 'private'],
172
+					$this->_default_field_name                  => true,
173
+				],
174
+			]
175
+		);
176
+	}
177 177
 }
Please login to merge, or discard this patch.
core/admin/EE_Admin.core.php 1 patch
Indentation   +998 added lines, -998 removed lines patch added patch discarded remove patch
@@ -20,1002 +20,1002 @@
 block discarded – undo
20 20
  */
21 21
 final class EE_Admin implements InterminableInterface
22 22
 {
23
-    /**
24
-     * @var EE_Admin $_instance
25
-     */
26
-    private static $_instance;
27
-
28
-    /**
29
-     * @var PersistentAdminNoticeManager $persistent_admin_notice_manager
30
-     */
31
-    private $persistent_admin_notice_manager;
32
-
33
-    /**
34
-     * @var LoaderInterface $loader
35
-     */
36
-    protected $loader;
37
-
38
-    /**
39
-     * @var RequestInterface
40
-     */
41
-    protected $request;
42
-
43
-
44
-    /**
45
-     * @singleton method used to instantiate class object
46
-     * @param LoaderInterface  $loader
47
-     * @param RequestInterface $request
48
-     * @return EE_Admin
49
-     * @throws EE_Error
50
-     */
51
-    public static function instance(LoaderInterface $loader = null, RequestInterface $request = null)
52
-    {
53
-        // check if class object is instantiated
54
-        if (! EE_Admin::$_instance instanceof EE_Admin) {
55
-            EE_Admin::$_instance = new EE_Admin($loader, $request);
56
-        }
57
-        return EE_Admin::$_instance;
58
-    }
59
-
60
-
61
-    /**
62
-     * @return EE_Admin
63
-     * @throws EE_Error
64
-     */
65
-    public static function reset()
66
-    {
67
-        EE_Admin::$_instance = null;
68
-        $loader = LoaderFactory::getLoader();
69
-        $request = $loader->getShared('EventEspresso\core\services\request\Request');
70
-        return EE_Admin::instance($loader, $request);
71
-    }
72
-
73
-
74
-    /**
75
-     * @param LoaderInterface  $loader
76
-     * @param RequestInterface $request
77
-     * @throws EE_Error
78
-     * @throws InvalidDataTypeException
79
-     * @throws InvalidInterfaceException
80
-     * @throws InvalidArgumentException
81
-     */
82
-    protected function __construct(LoaderInterface $loader, RequestInterface $request)
83
-    {
84
-        $this->loader = $loader;
85
-        $this->request = $request;
86
-        // define global EE_Admin constants
87
-        $this->_define_all_constants();
88
-        // set autoloaders for our admin page classes based on included path information
89
-        EEH_Autoloader::register_autoloaders_for_each_file_in_folder(EE_ADMIN);
90
-        // reset Environment config (we only do this on admin page loads);
91
-        EE_Registry::instance()->CFG->environment->recheck_values();
92
-        // load EE_Request_Handler early
93
-        add_action('AHEE__EE_System__initialize_last', [$this, 'init']);
94
-        add_action('admin_init', [$this, 'admin_init'], 100);
95
-        if (! $this->request->isAjax()) {
96
-            // admin hooks
97
-            add_action('admin_notices', [$this, 'display_admin_notices'], 10);
98
-            add_action('network_admin_notices', [$this, 'display_admin_notices'], 10);
99
-            add_filter('pre_update_option', [$this, 'check_for_invalid_datetime_formats'], 100, 2);
100
-            add_filter('plugin_action_links', [$this, 'filter_plugin_actions'], 10, 2);
101
-            add_filter('admin_footer_text', [$this, 'espresso_admin_footer']);
102
-            add_action('display_post_states', [$this, 'displayStateForCriticalPages'], 10, 2);
103
-            add_filter('plugin_row_meta', [$this, 'addLinksToPluginRowMeta'], 10, 2);
104
-        }
105
-        do_action('AHEE__EE_Admin__loaded');
106
-    }
107
-
108
-
109
-    /**
110
-     * _define_all_constants
111
-     * define constants that are set globally for all admin pages
112
-     *
113
-     * @return void
114
-     */
115
-    private function _define_all_constants()
116
-    {
117
-        if (! defined('EE_ADMIN_URL')) {
118
-            define('EE_ADMIN_URL', EE_PLUGIN_DIR_URL . 'core/admin/');
119
-            define('EE_ADMIN_PAGES_URL', EE_PLUGIN_DIR_URL . 'admin_pages/');
120
-            define('EE_ADMIN_TEMPLATE', EE_ADMIN . 'templates/');
121
-            define('WP_ADMIN_PATH', ABSPATH . 'wp-admin/');
122
-            define('WP_AJAX_URL', admin_url('admin-ajax.php'));
123
-        }
124
-    }
125
-
126
-
127
-    /**
128
-     * filter_plugin_actions - adds links to the Plugins page listing
129
-     *
130
-     * @param array  $links
131
-     * @param string $plugin
132
-     * @return    array
133
-     */
134
-    public function filter_plugin_actions($links, $plugin)
135
-    {
136
-        // set $main_file in stone
137
-        static $main_file;
138
-        // if $main_file is not set yet
139
-        if (! $main_file) {
140
-            $main_file = EE_PLUGIN_BASENAME;
141
-        }
142
-        if ($plugin === $main_file) {
143
-            // compare current plugin to this one
144
-            if (EE_Maintenance_Mode::instance()->level() === EE_Maintenance_Mode::level_2_complete_maintenance) {
145
-                $maintenance_link = '<a href="admin.php?page=espresso_maintenance_settings"'
146
-                                    . ' title="Event Espresso is in maintenance mode.  Click this link to learn why.">'
147
-                                    . esc_html__('Maintenance Mode Active', 'event_espresso')
148
-                                    . '</a>';
149
-                array_unshift($links, $maintenance_link);
150
-            } else {
151
-                $org_settings_link = '<a href="admin.php?page=espresso_general_settings">'
152
-                                     . esc_html__('Settings', 'event_espresso')
153
-                                     . '</a>';
154
-                $events_link       = '<a href="admin.php?page=espresso_events">'
155
-                                     . esc_html__('Events', 'event_espresso')
156
-                                     . '</a>';
157
-                // add before other links
158
-                array_unshift($links, $org_settings_link, $events_link);
159
-            }
160
-        }
161
-        return $links;
162
-    }
163
-
164
-
165
-    /**
166
-     * hide_admin_pages_except_maintenance_mode
167
-     *
168
-     * @param array $admin_page_folder_names
169
-     * @return array
170
-     */
171
-    public function hide_admin_pages_except_maintenance_mode($admin_page_folder_names = [])
172
-    {
173
-        return [
174
-            'maintenance' => EE_ADMIN_PAGES . 'maintenance/',
175
-            'about'       => EE_ADMIN_PAGES . 'about/',
176
-            'support'     => EE_ADMIN_PAGES . 'support/',
177
-        ];
178
-    }
179
-
180
-
181
-    /**
182
-     * init- should fire after shortcode, module,  addon, other plugin (default priority), and even
183
-     * EE_Front_Controller's init phases have run
184
-     *
185
-     * @return void
186
-     * @throws EE_Error
187
-     * @throws InvalidArgumentException
188
-     * @throws InvalidDataTypeException
189
-     * @throws InvalidInterfaceException
190
-     * @throws ReflectionException
191
-     * @throws ServiceNotFoundException
192
-     */
193
-    public function init()
194
-    {
195
-        // only enable most of the EE_Admin IF we're not in full maintenance mode
196
-        if (EE_Maintenance_Mode::instance()->models_can_query()) {
197
-            $this->initModelsReady();
198
-        }
199
-        // run the admin page factory but ONLY if:
200
-        // - it is a regular non ajax admin request
201
-        // - we are doing an ee admin ajax request
202
-        if ($this->request->isAdmin() || $this->request->isAdminAjax() || $this->request->isActivation()) {
203
-            try {
204
-                // this loads the controller for the admin pages which will setup routing etc
205
-                $admin_page_loader = $this->loader->getShared('EE_Admin_Page_Loader', [$this->loader]);
206
-                /** @var EE_Admin_Page_Loader $admin_page_loader */
207
-                $admin_page_loader->init();
208
-            } catch (EE_Error $e) {
209
-                $e->get_error();
210
-            }
211
-        }
212
-        if ($this->request->isAjax()) {
213
-            return;
214
-        }
215
-        add_filter('content_save_pre', [$this, 'its_eSpresso'], 10, 1);
216
-        // make sure our CPTs and custom taxonomy metaboxes get shown for first time users
217
-        add_action('admin_head', [$this, 'enable_hidden_ee_nav_menu_metaboxes'], 10);
218
-        add_action('admin_head', [$this, 'register_custom_nav_menu_boxes'], 10);
219
-        // exclude EE critical pages from all nav menus and wp_list_pages
220
-        add_filter('nav_menu_meta_box_object', [$this, 'remove_pages_from_nav_menu'], 10);
221
-    }
222
-
223
-
224
-    /**
225
-     * Gets the loader (and if it wasn't previously set, sets it)
226
-     *
227
-     * @return LoaderInterface
228
-     * @throws InvalidArgumentException
229
-     * @throws InvalidDataTypeException
230
-     * @throws InvalidInterfaceException
231
-     */
232
-    protected function getLoader()
233
-    {
234
-        return $this->loader;
235
-    }
236
-
237
-
238
-    /**
239
-     * Method that's fired on admin requests (including admin ajax) but only when the models are usable
240
-     * (ie, the site isn't in maintenance mode)
241
-     *
242
-     * @return void
243
-     * @throws EE_Error
244
-     * @since 4.9.63.p
245
-     */
246
-    protected function initModelsReady()
247
-    {
248
-        // ok so we want to enable the entire admin
249
-        $this->persistent_admin_notice_manager = $this->loader->getShared(
250
-            'EventEspresso\core\services\notifications\PersistentAdminNoticeManager'
251
-        );
252
-        $this->persistent_admin_notice_manager->setReturnUrl(
253
-            EE_Admin_Page::add_query_args_and_nonce(
254
-                [
255
-                    'page'   => $this->request->getRequestParam('page', ''),
256
-                    'action' => $this->request->getRequestParam('action', ''),
257
-                ],
258
-                EE_ADMIN_URL
259
-            )
260
-        );
261
-        $this->maybeSetDatetimeWarningNotice();
262
-        // at a glance dashboard widget
263
-        add_filter('dashboard_glance_items', [$this, 'dashboard_glance_items'], 10);
264
-        // filter for get_edit_post_link used on comments for custom post types
265
-        add_filter('get_edit_post_link', [$this, 'modify_edit_post_link'], 10, 2);
266
-    }
267
-
268
-
269
-    /**
270
-     *    get_persistent_admin_notices
271
-     *
272
-     * @access    public
273
-     * @return void
274
-     * @throws EE_Error
275
-     * @throws InvalidArgumentException
276
-     * @throws InvalidDataTypeException
277
-     * @throws InvalidInterfaceException
278
-     */
279
-    public function maybeSetDatetimeWarningNotice()
280
-    {
281
-        // add dismissible notice for datetime changes.  Only valid if site does not have a timezone_string set.
282
-        // @todo This needs to stay in core for a bit to catch anyone upgrading from a version without this to a version
283
-        // with this.  But after enough time (indeterminate at this point) we can just remove this notice.
284
-        // this was added with https://events.codebasehq.com/projects/event-espresso/tickets/10626
285
-        if (
286
-            apply_filters('FHEE__EE_Admin__maybeSetDatetimeWarningNotice', true)
287
-            && ! get_option('timezone_string')
288
-            && EEM_Event::instance()->count() > 0
289
-        ) {
290
-            new PersistentAdminNotice(
291
-                'datetime_fix_notice',
292
-                sprintf(
293
-                    esc_html__(
294
-                        '%1$sImportant announcement related to your install of Event Espresso%2$s: There are some changes made to your site that could affect how dates display for your events and other related items with dates and times.  Read more about it %3$shere%4$s. If your dates and times are displaying incorrectly (incorrect offset), you can fix it using the tool on %5$sthis page%4$s.',
295
-                        'event_espresso'
296
-                    ),
297
-                    '<strong>',
298
-                    '</strong>',
299
-                    '<a href="https://eventespresso.com/2017/08/important-upcoming-changes-dates-times">',
300
-                    '</a>',
301
-                    '<a href="' . EE_Admin_Page::add_query_args_and_nonce(
302
-                        [
303
-                            'page'   => 'espresso_maintenance_settings',
304
-                            'action' => 'datetime_tools',
305
-                        ],
306
-                        admin_url('admin.php')
307
-                    ) . '">'
308
-                ),
309
-                false,
310
-                'manage_options',
311
-                'datetime_fix_persistent_notice'
312
-            );
313
-        }
314
-    }
315
-
316
-
317
-    /**
318
-     * this simply hooks into the nav menu setup of pages metabox and makes sure that we remove EE critical pages from
319
-     * the list of options. the wp function "wp_nav_menu_item_post_type_meta_box" found in
320
-     * wp-admin/includes/nav-menu.php looks for the "_default_query" property on the post_type object and it uses that
321
-     * to override any queries found in the existing query for the given post type.  Note that _default_query is not a
322
-     * normal property on the post_type object.  It's found ONLY in this particular context.
323
-     *
324
-     * @param WP_Post $post_type WP post type object
325
-     * @return WP_Post
326
-     * @throws InvalidArgumentException
327
-     * @throws InvalidDataTypeException
328
-     * @throws InvalidInterfaceException
329
-     */
330
-    public function remove_pages_from_nav_menu($post_type)
331
-    {
332
-        // if this isn't the "pages" post type let's get out
333
-        if ($post_type->name !== 'page') {
334
-            return $post_type;
335
-        }
336
-        $critical_pages            = EE_Registry::instance()->CFG->core->get_critical_pages_array();
337
-        $post_type->_default_query = [
338
-            'post__not_in' => $critical_pages,
339
-        ];
340
-        return $post_type;
341
-    }
342
-
343
-
344
-    /**
345
-     * WP by default only shows three metaboxes in "nav-menus.php" for first times users.
346
-     * We want to make sure our metaboxes get shown as well
347
-     *
348
-     * @return void
349
-     */
350
-    public function enable_hidden_ee_nav_menu_metaboxes()
351
-    {
352
-        global $wp_meta_boxes, $pagenow;
353
-        if (! is_array($wp_meta_boxes) || $pagenow !== 'nav-menus.php') {
354
-            return;
355
-        }
356
-        $user = wp_get_current_user();
357
-        // has this been done yet?
358
-        if (get_user_option('ee_nav_menu_initialized', $user->ID)) {
359
-            return;
360
-        }
361
-
362
-        $hidden_meta_boxes  = get_user_option('metaboxhidden_nav-menus', $user->ID);
363
-        $initial_meta_boxes = apply_filters(
364
-            'FHEE__EE_Admin__enable_hidden_ee_nav_menu_boxes__initial_meta_boxes',
365
-            [
366
-                'nav-menu-theme-locations',
367
-                'add-page',
368
-                'add-custom-links',
369
-                'add-category',
370
-                'add-espresso_events',
371
-                'add-espresso_venues',
372
-                'add-espresso_event_categories',
373
-                'add-espresso_venue_categories',
374
-                'add-post-type-post',
375
-                'add-post-type-page',
376
-            ]
377
-        );
378
-
379
-        if (is_array($hidden_meta_boxes)) {
380
-            foreach ($hidden_meta_boxes as $key => $meta_box_id) {
381
-                if (in_array($meta_box_id, $initial_meta_boxes, true)) {
382
-                    unset($hidden_meta_boxes[ $key ]);
383
-                }
384
-            }
385
-        }
386
-        update_user_option($user->ID, 'metaboxhidden_nav-menus', $hidden_meta_boxes, true);
387
-        update_user_option($user->ID, 'ee_nav_menu_initialized', 1, true);
388
-    }
389
-
390
-
391
-    /**
392
-     * This method simply registers custom nav menu boxes for "nav_menus.php route"
393
-     * Currently EE is using this to make sure there are menu options for our CPT archive page routes.
394
-     *
395
-     * @return void
396
-     * @todo   modify this so its more dynamic and automatic for all ee CPTs and setups and can also be hooked into by
397
-     *         addons etc.
398
-     */
399
-    public function register_custom_nav_menu_boxes()
400
-    {
401
-        add_meta_box(
402
-            'add-extra-nav-menu-pages',
403
-            esc_html__('Event Espresso Pages', 'event_espresso'),
404
-            [$this, 'ee_cpt_archive_pages'],
405
-            'nav-menus',
406
-            'side',
407
-            'core'
408
-        );
409
-        add_filter(
410
-            "postbox_classes_nav-menus_add-extra-nav-menu-pages",
411
-            function ($classes) {
412
-                array_push($classes, 'ee-admin-container');
413
-                return $classes;
414
-            }
415
-        );
416
-    }
417
-
418
-
419
-    /**
420
-     * Use this to edit the post link for our cpts so that the edit link points to the correct page.
421
-     *
422
-     * @param string $link the original link generated by wp
423
-     * @param int    $id   post id
424
-     * @return string  the (maybe) modified link
425
-     * @since   4.3.0
426
-     */
427
-    public function modify_edit_post_link($link, $id)
428
-    {
429
-        if (! $post = get_post($id)) {
430
-            return $link;
431
-        }
432
-        if ($post->post_type === 'espresso_attendees') {
433
-            $query_args = [
434
-                'action' => 'edit_attendee',
435
-                'post'   => $id,
436
-            ];
437
-            return EEH_URL::add_query_args_and_nonce(
438
-                $query_args,
439
-                admin_url('admin.php?page=espresso_registrations')
440
-            );
441
-        }
442
-        return $link;
443
-    }
444
-
445
-
446
-    public function ee_cpt_archive_pages()
447
-    {
448
-        global $nav_menu_selected_id;
449
-        $removed_args = [
450
-            'action',
451
-            'customlink-tab',
452
-            'edit-menu-item',
453
-            'menu-item',
454
-            'page-tab',
455
-            '_wpnonce',
456
-        ];
457
-        $nav_tab_link = $nav_menu_selected_id
458
-            ? esc_url(
459
-                add_query_arg(
460
-                    'extra-nav-menu-pages-tab',
461
-                    'event-archives',
462
-                    remove_query_arg($removed_args)
463
-                )
464
-            )
465
-            : '';
466
-        $select_all_link = esc_url(
467
-            add_query_arg(
468
-                [
469
-                    'extra-nav-menu-pages-tab' => 'event-archives',
470
-                    'selectall'                => 1,
471
-                ],
472
-                remove_query_arg($removed_args)
473
-            )
474
-        );
475
-        $pages = $this->_get_extra_nav_menu_pages_items();
476
-        $args['walker'] = new Walker_Nav_Menu_Checklist(false);
477
-        ;
478
-        $nav_menu_pages_items = walk_nav_menu_tree(
479
-            array_map(
480
-                [$this, '_setup_extra_nav_menu_pages_items'],
481
-                $pages
482
-            ),
483
-            0,
484
-            (object) $args
485
-        );
486
-        EEH_Template::display_template(
487
-            EE_ADMIN_TEMPLATE . 'cpt_archive_page.template.php',
488
-            [
489
-                'nav_menu_selected_id' => $nav_menu_selected_id,
490
-                'nav_menu_pages_items' => $nav_menu_pages_items,
491
-                'nav_tab_link'         => $nav_tab_link,
492
-                'select_all_link'      => $select_all_link,
493
-            ]
494
-        );
495
-    }
496
-
497
-
498
-    /**
499
-     * Returns an array of event archive nav items.
500
-     *
501
-     * @return array
502
-     * @todo  for now this method is just in place so when it gets abstracted further we can substitute in whatever
503
-     *        method we use for getting the extra nav menu items
504
-     */
505
-    private function _get_extra_nav_menu_pages_items()
506
-    {
507
-        $menuitems[] = [
508
-            'title'       => esc_html__('Event List', 'event_espresso'),
509
-            'url'         => get_post_type_archive_link('espresso_events'),
510
-            'description' => esc_html__('Archive page for all events.', 'event_espresso'),
511
-        ];
512
-        return apply_filters('FHEE__EE_Admin__get_extra_nav_menu_pages_items', $menuitems);
513
-    }
514
-
515
-
516
-    /**
517
-     * Setup nav menu walker item for usage in the event archive nav menu metabox.  It receives a menu_item array with
518
-     * the properties and converts it to the menu item object.
519
-     *
520
-     * @param $menu_item_values
521
-     * @return stdClass
522
-     * @see wp_setup_nav_menu_item() in wp-includes/nav-menu.php
523
-     */
524
-    private function _setup_extra_nav_menu_pages_items($menu_item_values)
525
-    {
526
-        $menu_item = new stdClass();
527
-        $keys      = [
528
-            'ID'               => 0,
529
-            'db_id'            => 0,
530
-            'menu_item_parent' => 0,
531
-            'object_id'        => -1,
532
-            'post_parent'      => 0,
533
-            'type'             => 'custom',
534
-            'object'           => '',
535
-            'type_label'       => esc_html__('Extra Nav Menu Item', 'event_espresso'),
536
-            'title'            => '',
537
-            'url'              => '',
538
-            'target'           => '',
539
-            'attr_title'       => '',
540
-            'description'      => '',
541
-            'classes'          => [],
542
-            'xfn'              => '',
543
-        ];
544
-        foreach ($keys as $key => $value) {
545
-            $menu_item->{$key} = $menu_item_values[ $key ] ?? $value;
546
-        }
547
-        return $menu_item;
548
-    }
549
-
550
-
551
-    /**
552
-     * admin_init
553
-     *
554
-     * @return void
555
-     * @throws InvalidArgumentException
556
-     * @throws InvalidDataTypeException
557
-     * @throws InvalidInterfaceException
558
-     */
559
-    public function admin_init()
560
-    {
561
-        /**
562
-         * our cpt models must be instantiated on WordPress post processing routes (wp-admin/post.php),
563
-         * so any hooking into core WP routes is taken care of.  So in this next few lines of code:
564
-         * - check if doing post processing.
565
-         * - check if doing post processing of one of EE CPTs
566
-         * - instantiate the corresponding EE CPT model for the post_type being processed.
567
-         */
568
-        $action    = $this->request->getRequestParam('action');
569
-        $post_type = $this->request->getRequestParam('post_type');
570
-        if ($post_type && $action === 'editpost') {
571
-            /** @var CustomPostTypeDefinitions $custom_post_types */
572
-            $custom_post_types = $this->loader->getShared(CustomPostTypeDefinitions::class);
573
-            $custom_post_types->getCustomPostTypeModels($post_type);
574
-        }
575
-
576
-
577
-        if (! $this->request->isAjax()) {
578
-            /**
579
-             * This code excludes EE critical pages anywhere `wp_dropdown_pages` is used to create a dropdown for selecting
580
-             * critical pages.  The only place critical pages need included in a generated dropdown is on the "Critical
581
-             * Pages" tab in the EE General Settings Admin page.
582
-             * This is for user-proofing.
583
-             */
584
-            add_filter('wp_dropdown_pages', [$this, 'modify_dropdown_pages']);
585
-            if (EE_Maintenance_Mode::instance()->models_can_query()) {
586
-                $this->adminInitModelsReady();
587
-            }
588
-        }
589
-    }
590
-
591
-
592
-    /**
593
-     * Runs on admin_init but only if models are usable (ie, we're not in maintenance mode)
594
-     */
595
-    protected function adminInitModelsReady()
596
-    {
597
-        if (function_exists('wp_add_privacy_policy_content')) {
598
-            $this->loader->getShared('EventEspresso\core\services\privacy\policy\PrivacyPolicyManager');
599
-        }
600
-    }
601
-
602
-
603
-    /**
604
-     * Callback for wp_dropdown_pages hook to remove ee critical pages from the dropdown selection.
605
-     *
606
-     * @param string $output Current output.
607
-     * @return string
608
-     * @throws InvalidArgumentException
609
-     * @throws InvalidDataTypeException
610
-     * @throws InvalidInterfaceException
611
-     */
612
-    public function modify_dropdown_pages($output)
613
-    {
614
-        // get critical pages
615
-        $critical_pages = EE_Registry::instance()->CFG->core->get_critical_pages_array();
616
-
617
-        // split current output by line break for easier parsing.
618
-        $split_output = explode("\n", $output);
619
-
620
-        // loop through to remove any critical pages from the array.
621
-        foreach ($critical_pages as $page_id) {
622
-            $needle = 'value="' . $page_id . '"';
623
-            foreach ($split_output as $key => $haystack) {
624
-                if (strpos($haystack, $needle) !== false) {
625
-                    unset($split_output[ $key ]);
626
-                }
627
-            }
628
-        }
629
-        // replace output with the new contents
630
-        return implode("\n", $split_output);
631
-    }
632
-
633
-
634
-    /**
635
-     * display_admin_notices
636
-     *
637
-     * @return void
638
-     */
639
-    public function display_admin_notices()
640
-    {
641
-        echo EE_Error::get_notices(); // already escaped
642
-    }
643
-
644
-
645
-    /**
646
-     * @param array $elements
647
-     * @return array
648
-     * @throws EE_Error
649
-     * @throws InvalidArgumentException
650
-     * @throws InvalidDataTypeException
651
-     * @throws InvalidInterfaceException
652
-     */
653
-    public function dashboard_glance_items($elements)
654
-    {
655
-        $elements                        = is_array($elements) ? $elements : [$elements];
656
-        $events                          = EEM_Event::instance()->count();
657
-        $items['events']['url']          = EE_Admin_Page::add_query_args_and_nonce(
658
-            ['page' => 'espresso_events'],
659
-            admin_url('admin.php')
660
-        );
661
-        $items['events']['text']         = sprintf(
662
-            esc_html(
663
-                _n('%s Event', '%s Events', $events, 'event_espresso')
664
-            ),
665
-            number_format_i18n($events)
666
-        );
667
-        $items['events']['title']        = esc_html__('Click to view all Events', 'event_espresso');
668
-        $registrations                   = EEM_Registration::instance()->count(
669
-            [
670
-                [
671
-                    'STS_ID' => ['!=', EEM_Registration::status_id_incomplete],
672
-                ],
673
-            ]
674
-        );
675
-        $items['registrations']['url']   = EE_Admin_Page::add_query_args_and_nonce(
676
-            ['page' => 'espresso_registrations'],
677
-            admin_url('admin.php')
678
-        );
679
-        $items['registrations']['text']  = sprintf(
680
-            esc_html(
681
-                _n('%s Registration', '%s Registrations', $registrations, 'event_espresso')
682
-            ),
683
-            number_format_i18n($registrations)
684
-        );
685
-        $items['registrations']['title'] = esc_html__('Click to view all registrations', 'event_espresso');
686
-
687
-        $items = (array) apply_filters('FHEE__EE_Admin__dashboard_glance_items__items', $items);
688
-
689
-        foreach ($items as $type => $item_properties) {
690
-            $elements[] = sprintf(
691
-                '<a class="ee-dashboard-link-' . $type . '" href="%s" title="%s">%s</a>',
692
-                $item_properties['url'],
693
-                $item_properties['title'],
694
-                $item_properties['text']
695
-            );
696
-        }
697
-        return $elements;
698
-    }
699
-
700
-
701
-    /**
702
-     * check_for_invalid_datetime_formats
703
-     * if an admin changes their date or time format settings on the WP General Settings admin page, verify that
704
-     * their selected format can be parsed by PHP
705
-     *
706
-     * @param    $value
707
-     * @param    $option
708
-     * @return    string
709
-     */
710
-    public function check_for_invalid_datetime_formats($value, $option)
711
-    {
712
-        // check for date_format or time_format
713
-        switch ($option) {
714
-            case 'date_format':
715
-                $date_time_format = $value . ' ' . get_option('time_format');
716
-                break;
717
-            case 'time_format':
718
-                $date_time_format = get_option('date_format') . ' ' . $value;
719
-                break;
720
-            default:
721
-                $date_time_format = false;
722
-        }
723
-        // do we have a date_time format to check ?
724
-        if ($date_time_format) {
725
-            $error_msg = EEH_DTT_Helper::validate_format_string($date_time_format);
726
-
727
-            if (is_array($error_msg)) {
728
-                $msg = '<p>'
729
-                       . sprintf(
730
-                           esc_html__(
731
-                               'The following date time "%s" ( %s ) is difficult to be properly parsed by PHP for the following reasons:',
732
-                               'event_espresso'
733
-                           ),
734
-                           date($date_time_format),
735
-                           $date_time_format
736
-                       )
737
-                       . '</p><p><ul>';
738
-
739
-
740
-                foreach ($error_msg as $error) {
741
-                    $msg .= '<li>' . $error . '</li>';
742
-                }
743
-
744
-                $msg .= '</ul></p><p>'
745
-                        . sprintf(
746
-                            esc_html__(
747
-                                '%sPlease note that your date and time formats have been reset to "F j, Y" and "g:i a" respectively.%s',
748
-                                'event_espresso'
749
-                            ),
750
-                            '<span style="color:#D54E21;">',
751
-                            '</span>'
752
-                        )
753
-                        . '</p>';
754
-
755
-                // trigger WP settings error
756
-                add_settings_error(
757
-                    'date_format',
758
-                    'date_format',
759
-                    $msg
760
-                );
761
-
762
-                // set format to something valid
763
-                switch ($option) {
764
-                    case 'date_format':
765
-                        $value = 'F j, Y';
766
-                        break;
767
-                    case 'time_format':
768
-                        $value = 'g:i a';
769
-                        break;
770
-                }
771
-            }
772
-        }
773
-        return $value;
774
-    }
775
-
776
-
777
-    /**
778
-     * its_eSpresso - converts the less commonly used spelling of "Expresso" to "Espresso"
779
-     *
780
-     * @param $content
781
-     * @return    string
782
-     */
783
-    public function its_eSpresso($content)
784
-    {
785
-        return str_replace('[EXPRESSO_', '[ESPRESSO_', $content);
786
-    }
787
-
788
-
789
-    /**
790
-     * espresso_admin_footer
791
-     *
792
-     * @return    string
793
-     */
794
-    public function espresso_admin_footer()
795
-    {
796
-        return EEH_Template::powered_by_event_espresso('aln-cntr', '', ['utm_content' => 'admin_footer']);
797
-    }
798
-
799
-
800
-    /**
801
-     * Hooks into the "post states" filter in a wp post type list table.
802
-     *
803
-     * @param array   $post_states
804
-     * @param WP_Post $post
805
-     * @return array
806
-     * @throws InvalidArgumentException
807
-     * @throws InvalidDataTypeException
808
-     * @throws InvalidInterfaceException
809
-     */
810
-    public function displayStateForCriticalPages($post_states, $post)
811
-    {
812
-        $post_states = (array) $post_states;
813
-        if (! $post instanceof WP_Post || $post->post_type !== 'page') {
814
-            return $post_states;
815
-        }
816
-        /** @var EE_Core_Config $config */
817
-        $config = $this->loader->getShared('EE_Config')->core;
818
-        if (in_array($post->ID, $config->get_critical_pages_array(), true)) {
819
-            $post_states[] = sprintf(
820
-            /* Translators: Using company name - Event Espresso Critical Page */
821
-                esc_html__('%s Critical Page', 'event_espresso'),
822
-                'Event Espresso'
823
-            );
824
-        }
825
-        return $post_states;
826
-    }
827
-
828
-
829
-    /**
830
-     * Show documentation links on the plugins page
831
-     *
832
-     * @param mixed $meta Plugin Row Meta
833
-     * @param mixed $file Plugin Base file
834
-     * @return array
835
-     */
836
-    public function addLinksToPluginRowMeta($meta, $file)
837
-    {
838
-        if (EE_PLUGIN_BASENAME === $file) {
839
-            $row_meta = [
840
-                'docs' => '<a href="https://eventespresso.com/support/documentation/versioned-docs/?doc_ver=ee4"'
841
-                          . ' aria-label="'
842
-                          . esc_attr__('View Event Espresso documentation', 'event_espresso')
843
-                          . '">'
844
-                          . esc_html__('Docs', 'event_espresso')
845
-                          . '</a>',
846
-                'api'  => '<a href="https://github.com/eventespresso/event-espresso-core/tree/master/docs/C--REST-API"'
847
-                          . ' aria-label="'
848
-                          . esc_attr__('View Event Espresso API docs', 'event_espresso')
849
-                          . '">'
850
-                          . esc_html__('API docs', 'event_espresso')
851
-                          . '</a>',
852
-            ];
853
-            return array_merge($meta, $row_meta);
854
-        }
855
-        return (array) $meta;
856
-    }
857
-
858
-     /**************************************************************************************/
859
-     /************************************* DEPRECATED *************************************/
860
-     /**************************************************************************************/
861
-
862
-
863
-    /**
864
-     * This is the action hook for the AHEE__EE_Admin_Page__route_admin_request hook that fires off right before an
865
-     * EE_Admin_Page route is called.
866
-     *
867
-     * @return void
868
-     */
869
-    public function route_admin_request()
870
-    {
871
-    }
872
-
873
-
874
-    /**
875
-     * wp_loaded should fire on the WordPress wp_loaded hook.  This fires on a VERY late priority.
876
-     *
877
-     * @return void
878
-     */
879
-    public function wp_loaded()
880
-    {
881
-    }
882
-
883
-
884
-    /**
885
-     * static method for registering ee admin page.
886
-     * This method is deprecated in favor of the new location in EE_Register_Admin_Page::register.
887
-     *
888
-     * @param       $page_basename
889
-     * @param       $page_path
890
-     * @param array $config
891
-     * @return void
892
-     * @throws EE_Error
893
-     * @see        EE_Register_Admin_Page::register()
894
-     * @since      4.3.0
895
-     * @deprecated 4.3.0    Use EE_Register_Admin_Page::register() instead
896
-     */
897
-    public static function register_ee_admin_page($page_basename, $page_path, $config = [])
898
-    {
899
-        EE_Error::doing_it_wrong(
900
-            __METHOD__,
901
-            sprintf(
902
-                esc_html__(
903
-                    'Usage is deprecated.  Use EE_Register_Admin_Page::register() for registering the %s admin page.',
904
-                    'event_espresso'
905
-                ),
906
-                $page_basename
907
-            ),
908
-            '4.3'
909
-        );
910
-        if (class_exists('EE_Register_Admin_Page')) {
911
-            $config['page_path'] = $page_path;
912
-        }
913
-        EE_Register_Admin_Page::register($page_basename, $config);
914
-    }
915
-
916
-
917
-    /**
918
-     * @param int      $post_ID
919
-     * @param \WP_Post $post
920
-     * @return void
921
-     * @deprecated 4.8.41
922
-     */
923
-    public static function parse_post_content_on_save($post_ID, $post)
924
-    {
925
-        EE_Error::doing_it_wrong(
926
-            __METHOD__,
927
-            esc_html__('Usage is deprecated', 'event_espresso'),
928
-            '4.8.41'
929
-        );
930
-    }
931
-
932
-
933
-    /**
934
-     * @param  $option
935
-     * @param  $old_value
936
-     * @param  $value
937
-     * @return void
938
-     * @deprecated 4.8.41
939
-     */
940
-    public function reset_page_for_posts_on_change($option, $old_value, $value)
941
-    {
942
-        EE_Error::doing_it_wrong(
943
-            __METHOD__,
944
-            esc_html__('Usage is deprecated', 'event_espresso'),
945
-            '4.8.41'
946
-        );
947
-    }
948
-
949
-
950
-    /**
951
-     * @return void
952
-     * @deprecated 4.9.27
953
-     */
954
-    public function get_persistent_admin_notices()
955
-    {
956
-        EE_Error::doing_it_wrong(
957
-            __METHOD__,
958
-            sprintf(
959
-                esc_html__('Usage is deprecated. Use "%1$s" instead.', 'event_espresso'),
960
-                '\EventEspresso\core\services\notifications\PersistentAdminNoticeManager'
961
-            ),
962
-            '4.9.27'
963
-        );
964
-    }
965
-
966
-
967
-    /**
968
-     * @throws InvalidInterfaceException
969
-     * @throws InvalidDataTypeException
970
-     * @throws DomainException
971
-     * @deprecated 4.9.27
972
-     */
973
-    public function dismiss_ee_nag_notice_callback()
974
-    {
975
-        EE_Error::doing_it_wrong(
976
-            __METHOD__,
977
-            sprintf(
978
-                esc_html__('Usage is deprecated. Use "%1$s" instead.', 'event_espresso'),
979
-                '\EventEspresso\core\services\notifications\PersistentAdminNoticeManager'
980
-            ),
981
-            '4.9.27'
982
-        );
983
-        $this->persistent_admin_notice_manager->dismissNotice();
984
-    }
985
-
986
-
987
-    /**
988
-     * @return void
989
-     * @deprecated 5.0.0.p
990
-     */
991
-    public function enqueue_admin_scripts()
992
-    {
993
-    }
994
-
995
-
996
-
997
-    /**
998
-     * @return RequestInterface
999
-     * @deprecated 5.0.0.p
1000
-     */
1001
-    public function get_request()
1002
-    {
1003
-        EE_Error::doing_it_wrong(
1004
-            __METHOD__,
1005
-            sprintf(
1006
-                esc_html__('Usage is deprecated. Use "%1$s" instead.', 'event_espresso'),
1007
-                'EventEspresso\core\services\request\Request'
1008
-            ),
1009
-            '5.0.0.p'
1010
-        );
1011
-        return $this->request;
1012
-    }
1013
-
1014
-
1015
-    /**
1016
-     * @deprecated 5.0.0.p
1017
-     */
1018
-    public function hookIntoWpPluginsPage()
1019
-    {
1020
-    }
23
+	/**
24
+	 * @var EE_Admin $_instance
25
+	 */
26
+	private static $_instance;
27
+
28
+	/**
29
+	 * @var PersistentAdminNoticeManager $persistent_admin_notice_manager
30
+	 */
31
+	private $persistent_admin_notice_manager;
32
+
33
+	/**
34
+	 * @var LoaderInterface $loader
35
+	 */
36
+	protected $loader;
37
+
38
+	/**
39
+	 * @var RequestInterface
40
+	 */
41
+	protected $request;
42
+
43
+
44
+	/**
45
+	 * @singleton method used to instantiate class object
46
+	 * @param LoaderInterface  $loader
47
+	 * @param RequestInterface $request
48
+	 * @return EE_Admin
49
+	 * @throws EE_Error
50
+	 */
51
+	public static function instance(LoaderInterface $loader = null, RequestInterface $request = null)
52
+	{
53
+		// check if class object is instantiated
54
+		if (! EE_Admin::$_instance instanceof EE_Admin) {
55
+			EE_Admin::$_instance = new EE_Admin($loader, $request);
56
+		}
57
+		return EE_Admin::$_instance;
58
+	}
59
+
60
+
61
+	/**
62
+	 * @return EE_Admin
63
+	 * @throws EE_Error
64
+	 */
65
+	public static function reset()
66
+	{
67
+		EE_Admin::$_instance = null;
68
+		$loader = LoaderFactory::getLoader();
69
+		$request = $loader->getShared('EventEspresso\core\services\request\Request');
70
+		return EE_Admin::instance($loader, $request);
71
+	}
72
+
73
+
74
+	/**
75
+	 * @param LoaderInterface  $loader
76
+	 * @param RequestInterface $request
77
+	 * @throws EE_Error
78
+	 * @throws InvalidDataTypeException
79
+	 * @throws InvalidInterfaceException
80
+	 * @throws InvalidArgumentException
81
+	 */
82
+	protected function __construct(LoaderInterface $loader, RequestInterface $request)
83
+	{
84
+		$this->loader = $loader;
85
+		$this->request = $request;
86
+		// define global EE_Admin constants
87
+		$this->_define_all_constants();
88
+		// set autoloaders for our admin page classes based on included path information
89
+		EEH_Autoloader::register_autoloaders_for_each_file_in_folder(EE_ADMIN);
90
+		// reset Environment config (we only do this on admin page loads);
91
+		EE_Registry::instance()->CFG->environment->recheck_values();
92
+		// load EE_Request_Handler early
93
+		add_action('AHEE__EE_System__initialize_last', [$this, 'init']);
94
+		add_action('admin_init', [$this, 'admin_init'], 100);
95
+		if (! $this->request->isAjax()) {
96
+			// admin hooks
97
+			add_action('admin_notices', [$this, 'display_admin_notices'], 10);
98
+			add_action('network_admin_notices', [$this, 'display_admin_notices'], 10);
99
+			add_filter('pre_update_option', [$this, 'check_for_invalid_datetime_formats'], 100, 2);
100
+			add_filter('plugin_action_links', [$this, 'filter_plugin_actions'], 10, 2);
101
+			add_filter('admin_footer_text', [$this, 'espresso_admin_footer']);
102
+			add_action('display_post_states', [$this, 'displayStateForCriticalPages'], 10, 2);
103
+			add_filter('plugin_row_meta', [$this, 'addLinksToPluginRowMeta'], 10, 2);
104
+		}
105
+		do_action('AHEE__EE_Admin__loaded');
106
+	}
107
+
108
+
109
+	/**
110
+	 * _define_all_constants
111
+	 * define constants that are set globally for all admin pages
112
+	 *
113
+	 * @return void
114
+	 */
115
+	private function _define_all_constants()
116
+	{
117
+		if (! defined('EE_ADMIN_URL')) {
118
+			define('EE_ADMIN_URL', EE_PLUGIN_DIR_URL . 'core/admin/');
119
+			define('EE_ADMIN_PAGES_URL', EE_PLUGIN_DIR_URL . 'admin_pages/');
120
+			define('EE_ADMIN_TEMPLATE', EE_ADMIN . 'templates/');
121
+			define('WP_ADMIN_PATH', ABSPATH . 'wp-admin/');
122
+			define('WP_AJAX_URL', admin_url('admin-ajax.php'));
123
+		}
124
+	}
125
+
126
+
127
+	/**
128
+	 * filter_plugin_actions - adds links to the Plugins page listing
129
+	 *
130
+	 * @param array  $links
131
+	 * @param string $plugin
132
+	 * @return    array
133
+	 */
134
+	public function filter_plugin_actions($links, $plugin)
135
+	{
136
+		// set $main_file in stone
137
+		static $main_file;
138
+		// if $main_file is not set yet
139
+		if (! $main_file) {
140
+			$main_file = EE_PLUGIN_BASENAME;
141
+		}
142
+		if ($plugin === $main_file) {
143
+			// compare current plugin to this one
144
+			if (EE_Maintenance_Mode::instance()->level() === EE_Maintenance_Mode::level_2_complete_maintenance) {
145
+				$maintenance_link = '<a href="admin.php?page=espresso_maintenance_settings"'
146
+									. ' title="Event Espresso is in maintenance mode.  Click this link to learn why.">'
147
+									. esc_html__('Maintenance Mode Active', 'event_espresso')
148
+									. '</a>';
149
+				array_unshift($links, $maintenance_link);
150
+			} else {
151
+				$org_settings_link = '<a href="admin.php?page=espresso_general_settings">'
152
+									 . esc_html__('Settings', 'event_espresso')
153
+									 . '</a>';
154
+				$events_link       = '<a href="admin.php?page=espresso_events">'
155
+									 . esc_html__('Events', 'event_espresso')
156
+									 . '</a>';
157
+				// add before other links
158
+				array_unshift($links, $org_settings_link, $events_link);
159
+			}
160
+		}
161
+		return $links;
162
+	}
163
+
164
+
165
+	/**
166
+	 * hide_admin_pages_except_maintenance_mode
167
+	 *
168
+	 * @param array $admin_page_folder_names
169
+	 * @return array
170
+	 */
171
+	public function hide_admin_pages_except_maintenance_mode($admin_page_folder_names = [])
172
+	{
173
+		return [
174
+			'maintenance' => EE_ADMIN_PAGES . 'maintenance/',
175
+			'about'       => EE_ADMIN_PAGES . 'about/',
176
+			'support'     => EE_ADMIN_PAGES . 'support/',
177
+		];
178
+	}
179
+
180
+
181
+	/**
182
+	 * init- should fire after shortcode, module,  addon, other plugin (default priority), and even
183
+	 * EE_Front_Controller's init phases have run
184
+	 *
185
+	 * @return void
186
+	 * @throws EE_Error
187
+	 * @throws InvalidArgumentException
188
+	 * @throws InvalidDataTypeException
189
+	 * @throws InvalidInterfaceException
190
+	 * @throws ReflectionException
191
+	 * @throws ServiceNotFoundException
192
+	 */
193
+	public function init()
194
+	{
195
+		// only enable most of the EE_Admin IF we're not in full maintenance mode
196
+		if (EE_Maintenance_Mode::instance()->models_can_query()) {
197
+			$this->initModelsReady();
198
+		}
199
+		// run the admin page factory but ONLY if:
200
+		// - it is a regular non ajax admin request
201
+		// - we are doing an ee admin ajax request
202
+		if ($this->request->isAdmin() || $this->request->isAdminAjax() || $this->request->isActivation()) {
203
+			try {
204
+				// this loads the controller for the admin pages which will setup routing etc
205
+				$admin_page_loader = $this->loader->getShared('EE_Admin_Page_Loader', [$this->loader]);
206
+				/** @var EE_Admin_Page_Loader $admin_page_loader */
207
+				$admin_page_loader->init();
208
+			} catch (EE_Error $e) {
209
+				$e->get_error();
210
+			}
211
+		}
212
+		if ($this->request->isAjax()) {
213
+			return;
214
+		}
215
+		add_filter('content_save_pre', [$this, 'its_eSpresso'], 10, 1);
216
+		// make sure our CPTs and custom taxonomy metaboxes get shown for first time users
217
+		add_action('admin_head', [$this, 'enable_hidden_ee_nav_menu_metaboxes'], 10);
218
+		add_action('admin_head', [$this, 'register_custom_nav_menu_boxes'], 10);
219
+		// exclude EE critical pages from all nav menus and wp_list_pages
220
+		add_filter('nav_menu_meta_box_object', [$this, 'remove_pages_from_nav_menu'], 10);
221
+	}
222
+
223
+
224
+	/**
225
+	 * Gets the loader (and if it wasn't previously set, sets it)
226
+	 *
227
+	 * @return LoaderInterface
228
+	 * @throws InvalidArgumentException
229
+	 * @throws InvalidDataTypeException
230
+	 * @throws InvalidInterfaceException
231
+	 */
232
+	protected function getLoader()
233
+	{
234
+		return $this->loader;
235
+	}
236
+
237
+
238
+	/**
239
+	 * Method that's fired on admin requests (including admin ajax) but only when the models are usable
240
+	 * (ie, the site isn't in maintenance mode)
241
+	 *
242
+	 * @return void
243
+	 * @throws EE_Error
244
+	 * @since 4.9.63.p
245
+	 */
246
+	protected function initModelsReady()
247
+	{
248
+		// ok so we want to enable the entire admin
249
+		$this->persistent_admin_notice_manager = $this->loader->getShared(
250
+			'EventEspresso\core\services\notifications\PersistentAdminNoticeManager'
251
+		);
252
+		$this->persistent_admin_notice_manager->setReturnUrl(
253
+			EE_Admin_Page::add_query_args_and_nonce(
254
+				[
255
+					'page'   => $this->request->getRequestParam('page', ''),
256
+					'action' => $this->request->getRequestParam('action', ''),
257
+				],
258
+				EE_ADMIN_URL
259
+			)
260
+		);
261
+		$this->maybeSetDatetimeWarningNotice();
262
+		// at a glance dashboard widget
263
+		add_filter('dashboard_glance_items', [$this, 'dashboard_glance_items'], 10);
264
+		// filter for get_edit_post_link used on comments for custom post types
265
+		add_filter('get_edit_post_link', [$this, 'modify_edit_post_link'], 10, 2);
266
+	}
267
+
268
+
269
+	/**
270
+	 *    get_persistent_admin_notices
271
+	 *
272
+	 * @access    public
273
+	 * @return void
274
+	 * @throws EE_Error
275
+	 * @throws InvalidArgumentException
276
+	 * @throws InvalidDataTypeException
277
+	 * @throws InvalidInterfaceException
278
+	 */
279
+	public function maybeSetDatetimeWarningNotice()
280
+	{
281
+		// add dismissible notice for datetime changes.  Only valid if site does not have a timezone_string set.
282
+		// @todo This needs to stay in core for a bit to catch anyone upgrading from a version without this to a version
283
+		// with this.  But after enough time (indeterminate at this point) we can just remove this notice.
284
+		// this was added with https://events.codebasehq.com/projects/event-espresso/tickets/10626
285
+		if (
286
+			apply_filters('FHEE__EE_Admin__maybeSetDatetimeWarningNotice', true)
287
+			&& ! get_option('timezone_string')
288
+			&& EEM_Event::instance()->count() > 0
289
+		) {
290
+			new PersistentAdminNotice(
291
+				'datetime_fix_notice',
292
+				sprintf(
293
+					esc_html__(
294
+						'%1$sImportant announcement related to your install of Event Espresso%2$s: There are some changes made to your site that could affect how dates display for your events and other related items with dates and times.  Read more about it %3$shere%4$s. If your dates and times are displaying incorrectly (incorrect offset), you can fix it using the tool on %5$sthis page%4$s.',
295
+						'event_espresso'
296
+					),
297
+					'<strong>',
298
+					'</strong>',
299
+					'<a href="https://eventespresso.com/2017/08/important-upcoming-changes-dates-times">',
300
+					'</a>',
301
+					'<a href="' . EE_Admin_Page::add_query_args_and_nonce(
302
+						[
303
+							'page'   => 'espresso_maintenance_settings',
304
+							'action' => 'datetime_tools',
305
+						],
306
+						admin_url('admin.php')
307
+					) . '">'
308
+				),
309
+				false,
310
+				'manage_options',
311
+				'datetime_fix_persistent_notice'
312
+			);
313
+		}
314
+	}
315
+
316
+
317
+	/**
318
+	 * this simply hooks into the nav menu setup of pages metabox and makes sure that we remove EE critical pages from
319
+	 * the list of options. the wp function "wp_nav_menu_item_post_type_meta_box" found in
320
+	 * wp-admin/includes/nav-menu.php looks for the "_default_query" property on the post_type object and it uses that
321
+	 * to override any queries found in the existing query for the given post type.  Note that _default_query is not a
322
+	 * normal property on the post_type object.  It's found ONLY in this particular context.
323
+	 *
324
+	 * @param WP_Post $post_type WP post type object
325
+	 * @return WP_Post
326
+	 * @throws InvalidArgumentException
327
+	 * @throws InvalidDataTypeException
328
+	 * @throws InvalidInterfaceException
329
+	 */
330
+	public function remove_pages_from_nav_menu($post_type)
331
+	{
332
+		// if this isn't the "pages" post type let's get out
333
+		if ($post_type->name !== 'page') {
334
+			return $post_type;
335
+		}
336
+		$critical_pages            = EE_Registry::instance()->CFG->core->get_critical_pages_array();
337
+		$post_type->_default_query = [
338
+			'post__not_in' => $critical_pages,
339
+		];
340
+		return $post_type;
341
+	}
342
+
343
+
344
+	/**
345
+	 * WP by default only shows three metaboxes in "nav-menus.php" for first times users.
346
+	 * We want to make sure our metaboxes get shown as well
347
+	 *
348
+	 * @return void
349
+	 */
350
+	public function enable_hidden_ee_nav_menu_metaboxes()
351
+	{
352
+		global $wp_meta_boxes, $pagenow;
353
+		if (! is_array($wp_meta_boxes) || $pagenow !== 'nav-menus.php') {
354
+			return;
355
+		}
356
+		$user = wp_get_current_user();
357
+		// has this been done yet?
358
+		if (get_user_option('ee_nav_menu_initialized', $user->ID)) {
359
+			return;
360
+		}
361
+
362
+		$hidden_meta_boxes  = get_user_option('metaboxhidden_nav-menus', $user->ID);
363
+		$initial_meta_boxes = apply_filters(
364
+			'FHEE__EE_Admin__enable_hidden_ee_nav_menu_boxes__initial_meta_boxes',
365
+			[
366
+				'nav-menu-theme-locations',
367
+				'add-page',
368
+				'add-custom-links',
369
+				'add-category',
370
+				'add-espresso_events',
371
+				'add-espresso_venues',
372
+				'add-espresso_event_categories',
373
+				'add-espresso_venue_categories',
374
+				'add-post-type-post',
375
+				'add-post-type-page',
376
+			]
377
+		);
378
+
379
+		if (is_array($hidden_meta_boxes)) {
380
+			foreach ($hidden_meta_boxes as $key => $meta_box_id) {
381
+				if (in_array($meta_box_id, $initial_meta_boxes, true)) {
382
+					unset($hidden_meta_boxes[ $key ]);
383
+				}
384
+			}
385
+		}
386
+		update_user_option($user->ID, 'metaboxhidden_nav-menus', $hidden_meta_boxes, true);
387
+		update_user_option($user->ID, 'ee_nav_menu_initialized', 1, true);
388
+	}
389
+
390
+
391
+	/**
392
+	 * This method simply registers custom nav menu boxes for "nav_menus.php route"
393
+	 * Currently EE is using this to make sure there are menu options for our CPT archive page routes.
394
+	 *
395
+	 * @return void
396
+	 * @todo   modify this so its more dynamic and automatic for all ee CPTs and setups and can also be hooked into by
397
+	 *         addons etc.
398
+	 */
399
+	public function register_custom_nav_menu_boxes()
400
+	{
401
+		add_meta_box(
402
+			'add-extra-nav-menu-pages',
403
+			esc_html__('Event Espresso Pages', 'event_espresso'),
404
+			[$this, 'ee_cpt_archive_pages'],
405
+			'nav-menus',
406
+			'side',
407
+			'core'
408
+		);
409
+		add_filter(
410
+			"postbox_classes_nav-menus_add-extra-nav-menu-pages",
411
+			function ($classes) {
412
+				array_push($classes, 'ee-admin-container');
413
+				return $classes;
414
+			}
415
+		);
416
+	}
417
+
418
+
419
+	/**
420
+	 * Use this to edit the post link for our cpts so that the edit link points to the correct page.
421
+	 *
422
+	 * @param string $link the original link generated by wp
423
+	 * @param int    $id   post id
424
+	 * @return string  the (maybe) modified link
425
+	 * @since   4.3.0
426
+	 */
427
+	public function modify_edit_post_link($link, $id)
428
+	{
429
+		if (! $post = get_post($id)) {
430
+			return $link;
431
+		}
432
+		if ($post->post_type === 'espresso_attendees') {
433
+			$query_args = [
434
+				'action' => 'edit_attendee',
435
+				'post'   => $id,
436
+			];
437
+			return EEH_URL::add_query_args_and_nonce(
438
+				$query_args,
439
+				admin_url('admin.php?page=espresso_registrations')
440
+			);
441
+		}
442
+		return $link;
443
+	}
444
+
445
+
446
+	public function ee_cpt_archive_pages()
447
+	{
448
+		global $nav_menu_selected_id;
449
+		$removed_args = [
450
+			'action',
451
+			'customlink-tab',
452
+			'edit-menu-item',
453
+			'menu-item',
454
+			'page-tab',
455
+			'_wpnonce',
456
+		];
457
+		$nav_tab_link = $nav_menu_selected_id
458
+			? esc_url(
459
+				add_query_arg(
460
+					'extra-nav-menu-pages-tab',
461
+					'event-archives',
462
+					remove_query_arg($removed_args)
463
+				)
464
+			)
465
+			: '';
466
+		$select_all_link = esc_url(
467
+			add_query_arg(
468
+				[
469
+					'extra-nav-menu-pages-tab' => 'event-archives',
470
+					'selectall'                => 1,
471
+				],
472
+				remove_query_arg($removed_args)
473
+			)
474
+		);
475
+		$pages = $this->_get_extra_nav_menu_pages_items();
476
+		$args['walker'] = new Walker_Nav_Menu_Checklist(false);
477
+		;
478
+		$nav_menu_pages_items = walk_nav_menu_tree(
479
+			array_map(
480
+				[$this, '_setup_extra_nav_menu_pages_items'],
481
+				$pages
482
+			),
483
+			0,
484
+			(object) $args
485
+		);
486
+		EEH_Template::display_template(
487
+			EE_ADMIN_TEMPLATE . 'cpt_archive_page.template.php',
488
+			[
489
+				'nav_menu_selected_id' => $nav_menu_selected_id,
490
+				'nav_menu_pages_items' => $nav_menu_pages_items,
491
+				'nav_tab_link'         => $nav_tab_link,
492
+				'select_all_link'      => $select_all_link,
493
+			]
494
+		);
495
+	}
496
+
497
+
498
+	/**
499
+	 * Returns an array of event archive nav items.
500
+	 *
501
+	 * @return array
502
+	 * @todo  for now this method is just in place so when it gets abstracted further we can substitute in whatever
503
+	 *        method we use for getting the extra nav menu items
504
+	 */
505
+	private function _get_extra_nav_menu_pages_items()
506
+	{
507
+		$menuitems[] = [
508
+			'title'       => esc_html__('Event List', 'event_espresso'),
509
+			'url'         => get_post_type_archive_link('espresso_events'),
510
+			'description' => esc_html__('Archive page for all events.', 'event_espresso'),
511
+		];
512
+		return apply_filters('FHEE__EE_Admin__get_extra_nav_menu_pages_items', $menuitems);
513
+	}
514
+
515
+
516
+	/**
517
+	 * Setup nav menu walker item for usage in the event archive nav menu metabox.  It receives a menu_item array with
518
+	 * the properties and converts it to the menu item object.
519
+	 *
520
+	 * @param $menu_item_values
521
+	 * @return stdClass
522
+	 * @see wp_setup_nav_menu_item() in wp-includes/nav-menu.php
523
+	 */
524
+	private function _setup_extra_nav_menu_pages_items($menu_item_values)
525
+	{
526
+		$menu_item = new stdClass();
527
+		$keys      = [
528
+			'ID'               => 0,
529
+			'db_id'            => 0,
530
+			'menu_item_parent' => 0,
531
+			'object_id'        => -1,
532
+			'post_parent'      => 0,
533
+			'type'             => 'custom',
534
+			'object'           => '',
535
+			'type_label'       => esc_html__('Extra Nav Menu Item', 'event_espresso'),
536
+			'title'            => '',
537
+			'url'              => '',
538
+			'target'           => '',
539
+			'attr_title'       => '',
540
+			'description'      => '',
541
+			'classes'          => [],
542
+			'xfn'              => '',
543
+		];
544
+		foreach ($keys as $key => $value) {
545
+			$menu_item->{$key} = $menu_item_values[ $key ] ?? $value;
546
+		}
547
+		return $menu_item;
548
+	}
549
+
550
+
551
+	/**
552
+	 * admin_init
553
+	 *
554
+	 * @return void
555
+	 * @throws InvalidArgumentException
556
+	 * @throws InvalidDataTypeException
557
+	 * @throws InvalidInterfaceException
558
+	 */
559
+	public function admin_init()
560
+	{
561
+		/**
562
+		 * our cpt models must be instantiated on WordPress post processing routes (wp-admin/post.php),
563
+		 * so any hooking into core WP routes is taken care of.  So in this next few lines of code:
564
+		 * - check if doing post processing.
565
+		 * - check if doing post processing of one of EE CPTs
566
+		 * - instantiate the corresponding EE CPT model for the post_type being processed.
567
+		 */
568
+		$action    = $this->request->getRequestParam('action');
569
+		$post_type = $this->request->getRequestParam('post_type');
570
+		if ($post_type && $action === 'editpost') {
571
+			/** @var CustomPostTypeDefinitions $custom_post_types */
572
+			$custom_post_types = $this->loader->getShared(CustomPostTypeDefinitions::class);
573
+			$custom_post_types->getCustomPostTypeModels($post_type);
574
+		}
575
+
576
+
577
+		if (! $this->request->isAjax()) {
578
+			/**
579
+			 * This code excludes EE critical pages anywhere `wp_dropdown_pages` is used to create a dropdown for selecting
580
+			 * critical pages.  The only place critical pages need included in a generated dropdown is on the "Critical
581
+			 * Pages" tab in the EE General Settings Admin page.
582
+			 * This is for user-proofing.
583
+			 */
584
+			add_filter('wp_dropdown_pages', [$this, 'modify_dropdown_pages']);
585
+			if (EE_Maintenance_Mode::instance()->models_can_query()) {
586
+				$this->adminInitModelsReady();
587
+			}
588
+		}
589
+	}
590
+
591
+
592
+	/**
593
+	 * Runs on admin_init but only if models are usable (ie, we're not in maintenance mode)
594
+	 */
595
+	protected function adminInitModelsReady()
596
+	{
597
+		if (function_exists('wp_add_privacy_policy_content')) {
598
+			$this->loader->getShared('EventEspresso\core\services\privacy\policy\PrivacyPolicyManager');
599
+		}
600
+	}
601
+
602
+
603
+	/**
604
+	 * Callback for wp_dropdown_pages hook to remove ee critical pages from the dropdown selection.
605
+	 *
606
+	 * @param string $output Current output.
607
+	 * @return string
608
+	 * @throws InvalidArgumentException
609
+	 * @throws InvalidDataTypeException
610
+	 * @throws InvalidInterfaceException
611
+	 */
612
+	public function modify_dropdown_pages($output)
613
+	{
614
+		// get critical pages
615
+		$critical_pages = EE_Registry::instance()->CFG->core->get_critical_pages_array();
616
+
617
+		// split current output by line break for easier parsing.
618
+		$split_output = explode("\n", $output);
619
+
620
+		// loop through to remove any critical pages from the array.
621
+		foreach ($critical_pages as $page_id) {
622
+			$needle = 'value="' . $page_id . '"';
623
+			foreach ($split_output as $key => $haystack) {
624
+				if (strpos($haystack, $needle) !== false) {
625
+					unset($split_output[ $key ]);
626
+				}
627
+			}
628
+		}
629
+		// replace output with the new contents
630
+		return implode("\n", $split_output);
631
+	}
632
+
633
+
634
+	/**
635
+	 * display_admin_notices
636
+	 *
637
+	 * @return void
638
+	 */
639
+	public function display_admin_notices()
640
+	{
641
+		echo EE_Error::get_notices(); // already escaped
642
+	}
643
+
644
+
645
+	/**
646
+	 * @param array $elements
647
+	 * @return array
648
+	 * @throws EE_Error
649
+	 * @throws InvalidArgumentException
650
+	 * @throws InvalidDataTypeException
651
+	 * @throws InvalidInterfaceException
652
+	 */
653
+	public function dashboard_glance_items($elements)
654
+	{
655
+		$elements                        = is_array($elements) ? $elements : [$elements];
656
+		$events                          = EEM_Event::instance()->count();
657
+		$items['events']['url']          = EE_Admin_Page::add_query_args_and_nonce(
658
+			['page' => 'espresso_events'],
659
+			admin_url('admin.php')
660
+		);
661
+		$items['events']['text']         = sprintf(
662
+			esc_html(
663
+				_n('%s Event', '%s Events', $events, 'event_espresso')
664
+			),
665
+			number_format_i18n($events)
666
+		);
667
+		$items['events']['title']        = esc_html__('Click to view all Events', 'event_espresso');
668
+		$registrations                   = EEM_Registration::instance()->count(
669
+			[
670
+				[
671
+					'STS_ID' => ['!=', EEM_Registration::status_id_incomplete],
672
+				],
673
+			]
674
+		);
675
+		$items['registrations']['url']   = EE_Admin_Page::add_query_args_and_nonce(
676
+			['page' => 'espresso_registrations'],
677
+			admin_url('admin.php')
678
+		);
679
+		$items['registrations']['text']  = sprintf(
680
+			esc_html(
681
+				_n('%s Registration', '%s Registrations', $registrations, 'event_espresso')
682
+			),
683
+			number_format_i18n($registrations)
684
+		);
685
+		$items['registrations']['title'] = esc_html__('Click to view all registrations', 'event_espresso');
686
+
687
+		$items = (array) apply_filters('FHEE__EE_Admin__dashboard_glance_items__items', $items);
688
+
689
+		foreach ($items as $type => $item_properties) {
690
+			$elements[] = sprintf(
691
+				'<a class="ee-dashboard-link-' . $type . '" href="%s" title="%s">%s</a>',
692
+				$item_properties['url'],
693
+				$item_properties['title'],
694
+				$item_properties['text']
695
+			);
696
+		}
697
+		return $elements;
698
+	}
699
+
700
+
701
+	/**
702
+	 * check_for_invalid_datetime_formats
703
+	 * if an admin changes their date or time format settings on the WP General Settings admin page, verify that
704
+	 * their selected format can be parsed by PHP
705
+	 *
706
+	 * @param    $value
707
+	 * @param    $option
708
+	 * @return    string
709
+	 */
710
+	public function check_for_invalid_datetime_formats($value, $option)
711
+	{
712
+		// check for date_format or time_format
713
+		switch ($option) {
714
+			case 'date_format':
715
+				$date_time_format = $value . ' ' . get_option('time_format');
716
+				break;
717
+			case 'time_format':
718
+				$date_time_format = get_option('date_format') . ' ' . $value;
719
+				break;
720
+			default:
721
+				$date_time_format = false;
722
+		}
723
+		// do we have a date_time format to check ?
724
+		if ($date_time_format) {
725
+			$error_msg = EEH_DTT_Helper::validate_format_string($date_time_format);
726
+
727
+			if (is_array($error_msg)) {
728
+				$msg = '<p>'
729
+					   . sprintf(
730
+						   esc_html__(
731
+							   'The following date time "%s" ( %s ) is difficult to be properly parsed by PHP for the following reasons:',
732
+							   'event_espresso'
733
+						   ),
734
+						   date($date_time_format),
735
+						   $date_time_format
736
+					   )
737
+					   . '</p><p><ul>';
738
+
739
+
740
+				foreach ($error_msg as $error) {
741
+					$msg .= '<li>' . $error . '</li>';
742
+				}
743
+
744
+				$msg .= '</ul></p><p>'
745
+						. sprintf(
746
+							esc_html__(
747
+								'%sPlease note that your date and time formats have been reset to "F j, Y" and "g:i a" respectively.%s',
748
+								'event_espresso'
749
+							),
750
+							'<span style="color:#D54E21;">',
751
+							'</span>'
752
+						)
753
+						. '</p>';
754
+
755
+				// trigger WP settings error
756
+				add_settings_error(
757
+					'date_format',
758
+					'date_format',
759
+					$msg
760
+				);
761
+
762
+				// set format to something valid
763
+				switch ($option) {
764
+					case 'date_format':
765
+						$value = 'F j, Y';
766
+						break;
767
+					case 'time_format':
768
+						$value = 'g:i a';
769
+						break;
770
+				}
771
+			}
772
+		}
773
+		return $value;
774
+	}
775
+
776
+
777
+	/**
778
+	 * its_eSpresso - converts the less commonly used spelling of "Expresso" to "Espresso"
779
+	 *
780
+	 * @param $content
781
+	 * @return    string
782
+	 */
783
+	public function its_eSpresso($content)
784
+	{
785
+		return str_replace('[EXPRESSO_', '[ESPRESSO_', $content);
786
+	}
787
+
788
+
789
+	/**
790
+	 * espresso_admin_footer
791
+	 *
792
+	 * @return    string
793
+	 */
794
+	public function espresso_admin_footer()
795
+	{
796
+		return EEH_Template::powered_by_event_espresso('aln-cntr', '', ['utm_content' => 'admin_footer']);
797
+	}
798
+
799
+
800
+	/**
801
+	 * Hooks into the "post states" filter in a wp post type list table.
802
+	 *
803
+	 * @param array   $post_states
804
+	 * @param WP_Post $post
805
+	 * @return array
806
+	 * @throws InvalidArgumentException
807
+	 * @throws InvalidDataTypeException
808
+	 * @throws InvalidInterfaceException
809
+	 */
810
+	public function displayStateForCriticalPages($post_states, $post)
811
+	{
812
+		$post_states = (array) $post_states;
813
+		if (! $post instanceof WP_Post || $post->post_type !== 'page') {
814
+			return $post_states;
815
+		}
816
+		/** @var EE_Core_Config $config */
817
+		$config = $this->loader->getShared('EE_Config')->core;
818
+		if (in_array($post->ID, $config->get_critical_pages_array(), true)) {
819
+			$post_states[] = sprintf(
820
+			/* Translators: Using company name - Event Espresso Critical Page */
821
+				esc_html__('%s Critical Page', 'event_espresso'),
822
+				'Event Espresso'
823
+			);
824
+		}
825
+		return $post_states;
826
+	}
827
+
828
+
829
+	/**
830
+	 * Show documentation links on the plugins page
831
+	 *
832
+	 * @param mixed $meta Plugin Row Meta
833
+	 * @param mixed $file Plugin Base file
834
+	 * @return array
835
+	 */
836
+	public function addLinksToPluginRowMeta($meta, $file)
837
+	{
838
+		if (EE_PLUGIN_BASENAME === $file) {
839
+			$row_meta = [
840
+				'docs' => '<a href="https://eventespresso.com/support/documentation/versioned-docs/?doc_ver=ee4"'
841
+						  . ' aria-label="'
842
+						  . esc_attr__('View Event Espresso documentation', 'event_espresso')
843
+						  . '">'
844
+						  . esc_html__('Docs', 'event_espresso')
845
+						  . '</a>',
846
+				'api'  => '<a href="https://github.com/eventespresso/event-espresso-core/tree/master/docs/C--REST-API"'
847
+						  . ' aria-label="'
848
+						  . esc_attr__('View Event Espresso API docs', 'event_espresso')
849
+						  . '">'
850
+						  . esc_html__('API docs', 'event_espresso')
851
+						  . '</a>',
852
+			];
853
+			return array_merge($meta, $row_meta);
854
+		}
855
+		return (array) $meta;
856
+	}
857
+
858
+	 /**************************************************************************************/
859
+	 /************************************* DEPRECATED *************************************/
860
+	 /**************************************************************************************/
861
+
862
+
863
+	/**
864
+	 * This is the action hook for the AHEE__EE_Admin_Page__route_admin_request hook that fires off right before an
865
+	 * EE_Admin_Page route is called.
866
+	 *
867
+	 * @return void
868
+	 */
869
+	public function route_admin_request()
870
+	{
871
+	}
872
+
873
+
874
+	/**
875
+	 * wp_loaded should fire on the WordPress wp_loaded hook.  This fires on a VERY late priority.
876
+	 *
877
+	 * @return void
878
+	 */
879
+	public function wp_loaded()
880
+	{
881
+	}
882
+
883
+
884
+	/**
885
+	 * static method for registering ee admin page.
886
+	 * This method is deprecated in favor of the new location in EE_Register_Admin_Page::register.
887
+	 *
888
+	 * @param       $page_basename
889
+	 * @param       $page_path
890
+	 * @param array $config
891
+	 * @return void
892
+	 * @throws EE_Error
893
+	 * @see        EE_Register_Admin_Page::register()
894
+	 * @since      4.3.0
895
+	 * @deprecated 4.3.0    Use EE_Register_Admin_Page::register() instead
896
+	 */
897
+	public static function register_ee_admin_page($page_basename, $page_path, $config = [])
898
+	{
899
+		EE_Error::doing_it_wrong(
900
+			__METHOD__,
901
+			sprintf(
902
+				esc_html__(
903
+					'Usage is deprecated.  Use EE_Register_Admin_Page::register() for registering the %s admin page.',
904
+					'event_espresso'
905
+				),
906
+				$page_basename
907
+			),
908
+			'4.3'
909
+		);
910
+		if (class_exists('EE_Register_Admin_Page')) {
911
+			$config['page_path'] = $page_path;
912
+		}
913
+		EE_Register_Admin_Page::register($page_basename, $config);
914
+	}
915
+
916
+
917
+	/**
918
+	 * @param int      $post_ID
919
+	 * @param \WP_Post $post
920
+	 * @return void
921
+	 * @deprecated 4.8.41
922
+	 */
923
+	public static function parse_post_content_on_save($post_ID, $post)
924
+	{
925
+		EE_Error::doing_it_wrong(
926
+			__METHOD__,
927
+			esc_html__('Usage is deprecated', 'event_espresso'),
928
+			'4.8.41'
929
+		);
930
+	}
931
+
932
+
933
+	/**
934
+	 * @param  $option
935
+	 * @param  $old_value
936
+	 * @param  $value
937
+	 * @return void
938
+	 * @deprecated 4.8.41
939
+	 */
940
+	public function reset_page_for_posts_on_change($option, $old_value, $value)
941
+	{
942
+		EE_Error::doing_it_wrong(
943
+			__METHOD__,
944
+			esc_html__('Usage is deprecated', 'event_espresso'),
945
+			'4.8.41'
946
+		);
947
+	}
948
+
949
+
950
+	/**
951
+	 * @return void
952
+	 * @deprecated 4.9.27
953
+	 */
954
+	public function get_persistent_admin_notices()
955
+	{
956
+		EE_Error::doing_it_wrong(
957
+			__METHOD__,
958
+			sprintf(
959
+				esc_html__('Usage is deprecated. Use "%1$s" instead.', 'event_espresso'),
960
+				'\EventEspresso\core\services\notifications\PersistentAdminNoticeManager'
961
+			),
962
+			'4.9.27'
963
+		);
964
+	}
965
+
966
+
967
+	/**
968
+	 * @throws InvalidInterfaceException
969
+	 * @throws InvalidDataTypeException
970
+	 * @throws DomainException
971
+	 * @deprecated 4.9.27
972
+	 */
973
+	public function dismiss_ee_nag_notice_callback()
974
+	{
975
+		EE_Error::doing_it_wrong(
976
+			__METHOD__,
977
+			sprintf(
978
+				esc_html__('Usage is deprecated. Use "%1$s" instead.', 'event_espresso'),
979
+				'\EventEspresso\core\services\notifications\PersistentAdminNoticeManager'
980
+			),
981
+			'4.9.27'
982
+		);
983
+		$this->persistent_admin_notice_manager->dismissNotice();
984
+	}
985
+
986
+
987
+	/**
988
+	 * @return void
989
+	 * @deprecated 5.0.0.p
990
+	 */
991
+	public function enqueue_admin_scripts()
992
+	{
993
+	}
994
+
995
+
996
+
997
+	/**
998
+	 * @return RequestInterface
999
+	 * @deprecated 5.0.0.p
1000
+	 */
1001
+	public function get_request()
1002
+	{
1003
+		EE_Error::doing_it_wrong(
1004
+			__METHOD__,
1005
+			sprintf(
1006
+				esc_html__('Usage is deprecated. Use "%1$s" instead.', 'event_espresso'),
1007
+				'EventEspresso\core\services\request\Request'
1008
+			),
1009
+			'5.0.0.p'
1010
+		);
1011
+		return $this->request;
1012
+	}
1013
+
1014
+
1015
+	/**
1016
+	 * @deprecated 5.0.0.p
1017
+	 */
1018
+	public function hookIntoWpPluginsPage()
1019
+	{
1020
+	}
1021 1021
 }
Please login to merge, or discard this patch.
core/admin/EE_Admin_List_Table.core.php 1 patch
Indentation   +946 added lines, -946 removed lines patch added patch discarded remove patch
@@ -5,7 +5,7 @@  discard block
 block discarded – undo
5 5
 use EventEspresso\core\services\request\sanitizers\AllowedTags;
6 6
 
7 7
 if (! class_exists('WP_List_Table')) {
8
-    require_once ABSPATH . 'wp-admin/includes/class-wp-list-table.php';
8
+	require_once ABSPATH . 'wp-admin/includes/class-wp-list-table.php';
9 9
 }
10 10
 
11 11
 
@@ -23,928 +23,928 @@  discard block
 block discarded – undo
23 23
  */
24 24
 abstract class EE_Admin_List_Table extends WP_List_Table
25 25
 {
26
-    const ACTION_COPY    = 'duplicate';
27
-
28
-    const ACTION_DELETE  = 'delete';
29
-
30
-    const ACTION_EDIT    = 'edit';
31
-
32
-    const ACTION_RESTORE = 'restore';
33
-
34
-    const ACTION_TRASH   = 'trash';
35
-
36
-    protected static $actions = [
37
-        self::ACTION_COPY,
38
-        self::ACTION_DELETE,
39
-        self::ACTION_EDIT,
40
-        self::ACTION_RESTORE,
41
-        self::ACTION_TRASH,
42
-    ];
43
-
44
-    /**
45
-     * holds the data that will be processed for the table
46
-     *
47
-     * @var array $_data
48
-     */
49
-    protected $_data;
50
-
51
-
52
-    /**
53
-     * This holds the value of all the data available for the given view (for all pages).
54
-     *
55
-     * @var int $_all_data_count
56
-     */
57
-    protected $_all_data_count;
58
-
59
-
60
-    /**
61
-     * Will contain the count of trashed items for the view label.
62
-     *
63
-     * @var int $_trashed_count
64
-     */
65
-    protected $_trashed_count;
66
-
67
-
68
-    /**
69
-     * This is what will be referenced as the slug for the current screen
70
-     *
71
-     * @var string $_screen
72
-     */
73
-    protected $_screen;
74
-
75
-
76
-    /**
77
-     * this is the EE_Admin_Page object
78
-     *
79
-     * @var EE_Admin_Page $_admin_page
80
-     */
81
-    protected $_admin_page;
82
-
83
-
84
-    /**
85
-     * The current view
86
-     *
87
-     * @var string $_view
88
-     */
89
-    protected $_view;
90
-
91
-
92
-    /**
93
-     * array of possible views for this table
94
-     *
95
-     * @var array $_views
96
-     */
97
-    protected $_views;
98
-
99
-
100
-    /**
101
-     * An array of key => value pairs containing information about the current table
102
-     * array(
103
-     *        'plural' => 'plural label',
104
-     *        'singular' => 'singular label',
105
-     *        'ajax' => false, //whether to use ajax or not
106
-     *        'screen' => null, //string used to reference what screen this is
107
-     *        (WP_List_table converts to screen object)
108
-     * )
109
-     *
110
-     * @var array $_wp_list_args
111
-     */
112
-    protected $_wp_list_args;
113
-
114
-    /**
115
-     * an array of column names
116
-     * array(
117
-     *    'internal-name' => 'Title'
118
-     * )
119
-     *
120
-     * @var array $_columns
121
-     */
122
-    protected $_columns;
123
-
124
-    /**
125
-     * An array of sortable columns
126
-     * array(
127
-     *    'internal-name' => 'orderby' //or
128
-     *    'internal-name' => array( 'orderby', true )
129
-     * )
130
-     *
131
-     * @var array $_sortable_columns
132
-     */
133
-    protected $_sortable_columns;
134
-
135
-    /**
136
-     * callback method used to perform AJAX row reordering
137
-     *
138
-     * @var string $_ajax_sorting_callback
139
-     */
140
-    protected $_ajax_sorting_callback;
141
-
142
-    /**
143
-     * An array of hidden columns (if needed)
144
-     * array('internal-name', 'internal-name')
145
-     *
146
-     * @var array $_hidden_columns
147
-     */
148
-    protected $_hidden_columns;
149
-
150
-    /**
151
-     * holds the per_page value
152
-     *
153
-     * @var int $_per_page
154
-     */
155
-    protected $_per_page;
156
-
157
-    /**
158
-     * holds what page number is currently being viewed
159
-     *
160
-     * @var int $_current_page
161
-     */
162
-    protected $_current_page;
163
-
164
-    /**
165
-     * the reference string for the nonce_action
166
-     *
167
-     * @var string $_nonce_action_ref
168
-     */
169
-    protected $_nonce_action_ref;
170
-
171
-    /**
172
-     * property to hold incoming request data (as set by the admin_page_core)
173
-     *
174
-     * @var array $_req_data
175
-     */
176
-    protected $_req_data;
177
-
178
-
179
-    /**
180
-     * yes / no array for admin form fields
181
-     *
182
-     * @var array $_yes_no
183
-     */
184
-    protected $_yes_no = [];
185
-
186
-    /**
187
-     * Array describing buttons that should appear at the bottom of the page
188
-     * Keys are strings that represent the button's function (specifically a key in _labels['buttons']),
189
-     * and the values are another array with the following keys
190
-     * array(
191
-     *    'route' => 'page_route',
192
-     *    'extra_request' => array('evt_id' => 1 ); //extra request vars that need to be included in the button.
193
-     * )
194
-     *
195
-     * @var array $_bottom_buttons
196
-     */
197
-    protected $_bottom_buttons = [];
198
-
199
-
200
-    /**
201
-     * Used to indicate what should be the primary column for the list table.
202
-     * If not present then falls back to what WP calculates
203
-     * as the primary column.
204
-     *
205
-     * @type string $_primary_column
206
-     */
207
-    protected $_primary_column = '';
208
-
209
-
210
-    /**
211
-     * Used to indicate whether the table has a checkbox column or not.
212
-     *
213
-     * @type bool $_has_checkbox_column
214
-     */
215
-    protected $_has_checkbox_column = false;
216
-
217
-    /**
218
-     * @var AdminListTableFilters|null
219
-     */
220
-    protected ?AdminListTableFilters $admin_list_table_filters = null;
221
-
222
-
223
-    /**
224
-     * @param EE_Admin_Page              $admin_page we use this for obtaining everything we need in the list table
225
-     * @param AdminListTableFilters|null $filters    to display list table filters
226
-     */
227
-    public function __construct(EE_Admin_Page $admin_page, ?AdminListTableFilters $filters = null)
228
-    {
229
-        $this->_admin_page   = $admin_page;
230
-        $this->_req_data     = $this->_admin_page->get_request_data();
231
-        $this->_view         = $this->_admin_page->get_view();
232
-        $this->_views        = empty($this->_views) ? $this->_admin_page->get_list_table_view_RLs() : $this->_views;
233
-        $this->_current_page = $this->get_pagenum();
234
-        $this->_screen       = $this->_admin_page->get_current_page() . '_' . $this->_admin_page->get_current_view();
235
-        $this->_yes_no       = [
236
-            esc_html__('No', 'event_espresso'),
237
-            esc_html__('Yes', 'event_espresso')
238
-        ];
239
-
240
-        $this->_per_page = $this->get_items_per_page($this->_screen . '_per_page');
241
-
242
-        $this->admin_list_table_filters = $filters instanceof AdminListTableFilters
243
-            ? $filters
244
-            : LoaderFactory::getShared(AdminListTableFilters::class);
245
-
246
-        $this->_setup_data();
247
-        $this->_add_view_counts();
248
-
249
-        $this->_nonce_action_ref = $this->_view;
250
-
251
-        $this->_set_properties();
252
-
253
-        // set primary column
254
-        add_filter('list_table_primary_column', [$this, 'set_primary_column']);
255
-
256
-        // set parent defaults
257
-        parent::__construct($this->_wp_list_args);
258
-
259
-        $this->prepare_items();
260
-    }
261
-
262
-
263
-    /**
264
-     * _setup_data
265
-     * this method is used to setup the $_data, $_all_data_count, and _per_page properties
266
-     *
267
-     * @return void
268
-     * @uses $this->_admin_page
269
-     */
270
-    abstract protected function _setup_data();
271
-
272
-
273
-    /**
274
-     * set the properties that this class needs to be able to execute wp_list_table properly
275
-     * properties set:
276
-     * _wp_list_args = what the arguments required for the parent _wp_list_table.
277
-     * _columns = set the columns in an array.
278
-     * _sortable_columns = columns that are sortable (array).
279
-     * _hidden_columns = columns that are hidden (array)
280
-     * _default_orderby = the default orderby for sorting.
281
-     *
282
-     * @abstract
283
-     * @access protected
284
-     * @return void
285
-     */
286
-    abstract protected function _set_properties();
287
-
288
-
289
-    /**
290
-     * _get_table_filters
291
-     * We use this to assemble and return any filters that are associated with this table that help further refine what
292
-     * gets shown in the table.
293
-     *
294
-     * @abstract
295
-     * @access protected
296
-     * @return string[]
297
-     */
298
-    abstract protected function _get_table_filters();
299
-
300
-
301
-    /**
302
-     * this is a method that child class will do to add counts to the views array so when views are displayed the
303
-     * counts of the views is accurate.
304
-     *
305
-     * @abstract
306
-     * @access protected
307
-     * @return void
308
-     */
309
-    abstract protected function _add_view_counts();
310
-
311
-
312
-    /**
313
-     * _get_hidden_fields
314
-     * returns a html string of hidden fields so if any table filters are used the current view will be respected.
315
-     *
316
-     * @return string
317
-     */
318
-    protected function _get_hidden_fields()
319
-    {
320
-        $action = isset($this->_req_data['route']) ? $this->_req_data['route'] : '';
321
-        $action = empty($action) && isset($this->_req_data['action']) ? $this->_req_data['action'] : $action;
322
-        // if action is STILL empty, then we set it to default
323
-        $action = empty($action) ? 'default' : $action;
324
-        $field  = '<input type="hidden" name="page" value="' . esc_attr($this->_req_data['page']) . '" />' . "\n";
325
-        $field  .= '<input type="hidden" name="route" value="' . esc_attr($action) . '" />' . "\n";
326
-        $field  .= '<input type="hidden" name="perpage" value="' . esc_attr($this->_per_page) . '" />' . "\n";
327
-
328
-        $bulk_actions = $this->_get_bulk_actions();
329
-        foreach ($bulk_actions as $bulk_action => $label) {
330
-            $field .= '<input type="hidden" name="' . $bulk_action . '_nonce"'
331
-                      . ' value="' . wp_create_nonce($bulk_action . '_nonce') . '" />' . "\n";
332
-        }
333
-
334
-        return $field;
335
-    }
336
-
337
-
338
-    /**
339
-     * _set_column_info
340
-     * we're using this to set the column headers property.
341
-     *
342
-     * @access protected
343
-     * @return void
344
-     */
345
-    protected function _set_column_info()
346
-    {
347
-        $columns   = $this->get_columns();
348
-        $hidden    = $this->get_hidden_columns();
349
-        $_sortable = $this->get_sortable_columns();
350
-
351
-        /**
352
-         * Dynamic hook allowing for adding sortable columns in this list table.
353
-         * Note that $this->screen->id is in the format
354
-         * {sanitize_title($top_level_menu_label)}_page_{$espresso_admin_page_slug}.  So for the messages list
355
-         * table it is: event-espresso_page_espresso_messages.
356
-         * However, take note that if the top level menu label has been translated (i.e. "Event Espresso"). then the
357
-         * hook prefix ("event-espresso") will be different.
358
-         *
359
-         * @var array
360
-         */
361
-        $_sortable = apply_filters(
362
-            "FHEE_manage_{$this->screen->id}_sortable_columns",
363
-            $_sortable,
364
-            $this->_screen,
365
-            $this
366
-        );
367
-
368
-        $sortable = [];
369
-        foreach ($_sortable as $id => $data) {
370
-            if (empty($data)) {
371
-                continue;
372
-            }
373
-            // fix for offset errors with WP_List_Table default get_columninfo()
374
-            if (is_array($data)) {
375
-                $_data[0] = key($data);
376
-                $_data[1] = isset($data[1]) ? $data[1] : false;
377
-            } else {
378
-                $_data[0] = $data;
379
-            }
380
-
381
-            $data = (array) $data;
382
-
383
-            if (! isset($data[1])) {
384
-                $_data[1] = false;
385
-            }
386
-
387
-            $sortable[ $id ] = $_data;
388
-        }
389
-        $primary               = $this->get_primary_column_name();
390
-        $this->_column_headers = [$columns, $hidden, $sortable, $primary];
391
-    }
392
-
393
-
394
-    /**
395
-     * Added for WP4.1 backward compat (@see https://events.codebasehq.com/projects/event-espresso/tickets/8814)
396
-     *
397
-     * @return string
398
-     */
399
-    protected function get_primary_column_name()
400
-    {
401
-        foreach (class_parents($this) as $parent) {
402
-            if ($parent === 'WP_List_Table' && method_exists($parent, 'get_primary_column_name')) {
403
-                return parent::get_primary_column_name();
404
-            }
405
-        }
406
-        return $this->_primary_column;
407
-    }
408
-
409
-
410
-    /**
411
-     * Added for WP4.1 backward compat (@see https://events.codebasehq.com/projects/event-espresso/tickets/8814)
412
-     *
413
-     * @param EE_Base_Class $item
414
-     * @param string        $column_name
415
-     * @param string        $primary
416
-     * @return string
417
-     */
418
-    protected function handle_row_actions($item, $column_name, $primary)
419
-    {
420
-        foreach (class_parents($this) as $parent) {
421
-            if ($parent === 'WP_List_Table' && method_exists($parent, 'handle_row_actions')) {
422
-                return parent::handle_row_actions($item, $column_name, $primary);
423
-            }
424
-        }
425
-        return '';
426
-    }
427
-
428
-
429
-    /**
430
-     * _get_bulk_actions
431
-     * This is a wrapper called by WP_List_Table::get_bulk_actions()
432
-     *
433
-     * @access protected
434
-     * @return array bulk_actions
435
-     */
436
-    protected function _get_bulk_actions(): array
437
-    {
438
-        $actions = [];
439
-        // the _views property should have the bulk_actions, so let's go through and extract them into a properly
440
-        // formatted array for the wp_list_table();
441
-        foreach ($this->_views as $view => $args) {
442
-            if ($this->_view === $view && isset($args['bulk_action']) && is_array($args['bulk_action'])) {
443
-                // each bulk action will correspond with a admin page route, so we can check whatever the capability is
444
-                // for that page route and skip adding the bulk action if no access for the current logged in user.
445
-                foreach ($args['bulk_action'] as $route => $label) {
446
-                    if ($this->_admin_page->check_user_access($route, true)) {
447
-                        $actions[ $route ] = $label;
448
-                    }
449
-                }
450
-            }
451
-        }
452
-        return $actions;
453
-    }
454
-
455
-
456
-    /**
457
-     * Generate the table navigation above or below the table.
458
-     * Overrides the parent table nav in WP_List_Table so we can hide the bulk action div if there are no bulk actions.
459
-     *
460
-     * @throws EE_Error
461
-     * @since 4.9.44.rc.001
462
-     */
463
-    public function display_tablenav($which)
464
-    {
465
-        if ('top' === $which) {
466
-            wp_nonce_field('bulk-' . $this->_args['plural']);
467
-        }
468
-        ?>
26
+	const ACTION_COPY    = 'duplicate';
27
+
28
+	const ACTION_DELETE  = 'delete';
29
+
30
+	const ACTION_EDIT    = 'edit';
31
+
32
+	const ACTION_RESTORE = 'restore';
33
+
34
+	const ACTION_TRASH   = 'trash';
35
+
36
+	protected static $actions = [
37
+		self::ACTION_COPY,
38
+		self::ACTION_DELETE,
39
+		self::ACTION_EDIT,
40
+		self::ACTION_RESTORE,
41
+		self::ACTION_TRASH,
42
+	];
43
+
44
+	/**
45
+	 * holds the data that will be processed for the table
46
+	 *
47
+	 * @var array $_data
48
+	 */
49
+	protected $_data;
50
+
51
+
52
+	/**
53
+	 * This holds the value of all the data available for the given view (for all pages).
54
+	 *
55
+	 * @var int $_all_data_count
56
+	 */
57
+	protected $_all_data_count;
58
+
59
+
60
+	/**
61
+	 * Will contain the count of trashed items for the view label.
62
+	 *
63
+	 * @var int $_trashed_count
64
+	 */
65
+	protected $_trashed_count;
66
+
67
+
68
+	/**
69
+	 * This is what will be referenced as the slug for the current screen
70
+	 *
71
+	 * @var string $_screen
72
+	 */
73
+	protected $_screen;
74
+
75
+
76
+	/**
77
+	 * this is the EE_Admin_Page object
78
+	 *
79
+	 * @var EE_Admin_Page $_admin_page
80
+	 */
81
+	protected $_admin_page;
82
+
83
+
84
+	/**
85
+	 * The current view
86
+	 *
87
+	 * @var string $_view
88
+	 */
89
+	protected $_view;
90
+
91
+
92
+	/**
93
+	 * array of possible views for this table
94
+	 *
95
+	 * @var array $_views
96
+	 */
97
+	protected $_views;
98
+
99
+
100
+	/**
101
+	 * An array of key => value pairs containing information about the current table
102
+	 * array(
103
+	 *        'plural' => 'plural label',
104
+	 *        'singular' => 'singular label',
105
+	 *        'ajax' => false, //whether to use ajax or not
106
+	 *        'screen' => null, //string used to reference what screen this is
107
+	 *        (WP_List_table converts to screen object)
108
+	 * )
109
+	 *
110
+	 * @var array $_wp_list_args
111
+	 */
112
+	protected $_wp_list_args;
113
+
114
+	/**
115
+	 * an array of column names
116
+	 * array(
117
+	 *    'internal-name' => 'Title'
118
+	 * )
119
+	 *
120
+	 * @var array $_columns
121
+	 */
122
+	protected $_columns;
123
+
124
+	/**
125
+	 * An array of sortable columns
126
+	 * array(
127
+	 *    'internal-name' => 'orderby' //or
128
+	 *    'internal-name' => array( 'orderby', true )
129
+	 * )
130
+	 *
131
+	 * @var array $_sortable_columns
132
+	 */
133
+	protected $_sortable_columns;
134
+
135
+	/**
136
+	 * callback method used to perform AJAX row reordering
137
+	 *
138
+	 * @var string $_ajax_sorting_callback
139
+	 */
140
+	protected $_ajax_sorting_callback;
141
+
142
+	/**
143
+	 * An array of hidden columns (if needed)
144
+	 * array('internal-name', 'internal-name')
145
+	 *
146
+	 * @var array $_hidden_columns
147
+	 */
148
+	protected $_hidden_columns;
149
+
150
+	/**
151
+	 * holds the per_page value
152
+	 *
153
+	 * @var int $_per_page
154
+	 */
155
+	protected $_per_page;
156
+
157
+	/**
158
+	 * holds what page number is currently being viewed
159
+	 *
160
+	 * @var int $_current_page
161
+	 */
162
+	protected $_current_page;
163
+
164
+	/**
165
+	 * the reference string for the nonce_action
166
+	 *
167
+	 * @var string $_nonce_action_ref
168
+	 */
169
+	protected $_nonce_action_ref;
170
+
171
+	/**
172
+	 * property to hold incoming request data (as set by the admin_page_core)
173
+	 *
174
+	 * @var array $_req_data
175
+	 */
176
+	protected $_req_data;
177
+
178
+
179
+	/**
180
+	 * yes / no array for admin form fields
181
+	 *
182
+	 * @var array $_yes_no
183
+	 */
184
+	protected $_yes_no = [];
185
+
186
+	/**
187
+	 * Array describing buttons that should appear at the bottom of the page
188
+	 * Keys are strings that represent the button's function (specifically a key in _labels['buttons']),
189
+	 * and the values are another array with the following keys
190
+	 * array(
191
+	 *    'route' => 'page_route',
192
+	 *    'extra_request' => array('evt_id' => 1 ); //extra request vars that need to be included in the button.
193
+	 * )
194
+	 *
195
+	 * @var array $_bottom_buttons
196
+	 */
197
+	protected $_bottom_buttons = [];
198
+
199
+
200
+	/**
201
+	 * Used to indicate what should be the primary column for the list table.
202
+	 * If not present then falls back to what WP calculates
203
+	 * as the primary column.
204
+	 *
205
+	 * @type string $_primary_column
206
+	 */
207
+	protected $_primary_column = '';
208
+
209
+
210
+	/**
211
+	 * Used to indicate whether the table has a checkbox column or not.
212
+	 *
213
+	 * @type bool $_has_checkbox_column
214
+	 */
215
+	protected $_has_checkbox_column = false;
216
+
217
+	/**
218
+	 * @var AdminListTableFilters|null
219
+	 */
220
+	protected ?AdminListTableFilters $admin_list_table_filters = null;
221
+
222
+
223
+	/**
224
+	 * @param EE_Admin_Page              $admin_page we use this for obtaining everything we need in the list table
225
+	 * @param AdminListTableFilters|null $filters    to display list table filters
226
+	 */
227
+	public function __construct(EE_Admin_Page $admin_page, ?AdminListTableFilters $filters = null)
228
+	{
229
+		$this->_admin_page   = $admin_page;
230
+		$this->_req_data     = $this->_admin_page->get_request_data();
231
+		$this->_view         = $this->_admin_page->get_view();
232
+		$this->_views        = empty($this->_views) ? $this->_admin_page->get_list_table_view_RLs() : $this->_views;
233
+		$this->_current_page = $this->get_pagenum();
234
+		$this->_screen       = $this->_admin_page->get_current_page() . '_' . $this->_admin_page->get_current_view();
235
+		$this->_yes_no       = [
236
+			esc_html__('No', 'event_espresso'),
237
+			esc_html__('Yes', 'event_espresso')
238
+		];
239
+
240
+		$this->_per_page = $this->get_items_per_page($this->_screen . '_per_page');
241
+
242
+		$this->admin_list_table_filters = $filters instanceof AdminListTableFilters
243
+			? $filters
244
+			: LoaderFactory::getShared(AdminListTableFilters::class);
245
+
246
+		$this->_setup_data();
247
+		$this->_add_view_counts();
248
+
249
+		$this->_nonce_action_ref = $this->_view;
250
+
251
+		$this->_set_properties();
252
+
253
+		// set primary column
254
+		add_filter('list_table_primary_column', [$this, 'set_primary_column']);
255
+
256
+		// set parent defaults
257
+		parent::__construct($this->_wp_list_args);
258
+
259
+		$this->prepare_items();
260
+	}
261
+
262
+
263
+	/**
264
+	 * _setup_data
265
+	 * this method is used to setup the $_data, $_all_data_count, and _per_page properties
266
+	 *
267
+	 * @return void
268
+	 * @uses $this->_admin_page
269
+	 */
270
+	abstract protected function _setup_data();
271
+
272
+
273
+	/**
274
+	 * set the properties that this class needs to be able to execute wp_list_table properly
275
+	 * properties set:
276
+	 * _wp_list_args = what the arguments required for the parent _wp_list_table.
277
+	 * _columns = set the columns in an array.
278
+	 * _sortable_columns = columns that are sortable (array).
279
+	 * _hidden_columns = columns that are hidden (array)
280
+	 * _default_orderby = the default orderby for sorting.
281
+	 *
282
+	 * @abstract
283
+	 * @access protected
284
+	 * @return void
285
+	 */
286
+	abstract protected function _set_properties();
287
+
288
+
289
+	/**
290
+	 * _get_table_filters
291
+	 * We use this to assemble and return any filters that are associated with this table that help further refine what
292
+	 * gets shown in the table.
293
+	 *
294
+	 * @abstract
295
+	 * @access protected
296
+	 * @return string[]
297
+	 */
298
+	abstract protected function _get_table_filters();
299
+
300
+
301
+	/**
302
+	 * this is a method that child class will do to add counts to the views array so when views are displayed the
303
+	 * counts of the views is accurate.
304
+	 *
305
+	 * @abstract
306
+	 * @access protected
307
+	 * @return void
308
+	 */
309
+	abstract protected function _add_view_counts();
310
+
311
+
312
+	/**
313
+	 * _get_hidden_fields
314
+	 * returns a html string of hidden fields so if any table filters are used the current view will be respected.
315
+	 *
316
+	 * @return string
317
+	 */
318
+	protected function _get_hidden_fields()
319
+	{
320
+		$action = isset($this->_req_data['route']) ? $this->_req_data['route'] : '';
321
+		$action = empty($action) && isset($this->_req_data['action']) ? $this->_req_data['action'] : $action;
322
+		// if action is STILL empty, then we set it to default
323
+		$action = empty($action) ? 'default' : $action;
324
+		$field  = '<input type="hidden" name="page" value="' . esc_attr($this->_req_data['page']) . '" />' . "\n";
325
+		$field  .= '<input type="hidden" name="route" value="' . esc_attr($action) . '" />' . "\n";
326
+		$field  .= '<input type="hidden" name="perpage" value="' . esc_attr($this->_per_page) . '" />' . "\n";
327
+
328
+		$bulk_actions = $this->_get_bulk_actions();
329
+		foreach ($bulk_actions as $bulk_action => $label) {
330
+			$field .= '<input type="hidden" name="' . $bulk_action . '_nonce"'
331
+					  . ' value="' . wp_create_nonce($bulk_action . '_nonce') . '" />' . "\n";
332
+		}
333
+
334
+		return $field;
335
+	}
336
+
337
+
338
+	/**
339
+	 * _set_column_info
340
+	 * we're using this to set the column headers property.
341
+	 *
342
+	 * @access protected
343
+	 * @return void
344
+	 */
345
+	protected function _set_column_info()
346
+	{
347
+		$columns   = $this->get_columns();
348
+		$hidden    = $this->get_hidden_columns();
349
+		$_sortable = $this->get_sortable_columns();
350
+
351
+		/**
352
+		 * Dynamic hook allowing for adding sortable columns in this list table.
353
+		 * Note that $this->screen->id is in the format
354
+		 * {sanitize_title($top_level_menu_label)}_page_{$espresso_admin_page_slug}.  So for the messages list
355
+		 * table it is: event-espresso_page_espresso_messages.
356
+		 * However, take note that if the top level menu label has been translated (i.e. "Event Espresso"). then the
357
+		 * hook prefix ("event-espresso") will be different.
358
+		 *
359
+		 * @var array
360
+		 */
361
+		$_sortable = apply_filters(
362
+			"FHEE_manage_{$this->screen->id}_sortable_columns",
363
+			$_sortable,
364
+			$this->_screen,
365
+			$this
366
+		);
367
+
368
+		$sortable = [];
369
+		foreach ($_sortable as $id => $data) {
370
+			if (empty($data)) {
371
+				continue;
372
+			}
373
+			// fix for offset errors with WP_List_Table default get_columninfo()
374
+			if (is_array($data)) {
375
+				$_data[0] = key($data);
376
+				$_data[1] = isset($data[1]) ? $data[1] : false;
377
+			} else {
378
+				$_data[0] = $data;
379
+			}
380
+
381
+			$data = (array) $data;
382
+
383
+			if (! isset($data[1])) {
384
+				$_data[1] = false;
385
+			}
386
+
387
+			$sortable[ $id ] = $_data;
388
+		}
389
+		$primary               = $this->get_primary_column_name();
390
+		$this->_column_headers = [$columns, $hidden, $sortable, $primary];
391
+	}
392
+
393
+
394
+	/**
395
+	 * Added for WP4.1 backward compat (@see https://events.codebasehq.com/projects/event-espresso/tickets/8814)
396
+	 *
397
+	 * @return string
398
+	 */
399
+	protected function get_primary_column_name()
400
+	{
401
+		foreach (class_parents($this) as $parent) {
402
+			if ($parent === 'WP_List_Table' && method_exists($parent, 'get_primary_column_name')) {
403
+				return parent::get_primary_column_name();
404
+			}
405
+		}
406
+		return $this->_primary_column;
407
+	}
408
+
409
+
410
+	/**
411
+	 * Added for WP4.1 backward compat (@see https://events.codebasehq.com/projects/event-espresso/tickets/8814)
412
+	 *
413
+	 * @param EE_Base_Class $item
414
+	 * @param string        $column_name
415
+	 * @param string        $primary
416
+	 * @return string
417
+	 */
418
+	protected function handle_row_actions($item, $column_name, $primary)
419
+	{
420
+		foreach (class_parents($this) as $parent) {
421
+			if ($parent === 'WP_List_Table' && method_exists($parent, 'handle_row_actions')) {
422
+				return parent::handle_row_actions($item, $column_name, $primary);
423
+			}
424
+		}
425
+		return '';
426
+	}
427
+
428
+
429
+	/**
430
+	 * _get_bulk_actions
431
+	 * This is a wrapper called by WP_List_Table::get_bulk_actions()
432
+	 *
433
+	 * @access protected
434
+	 * @return array bulk_actions
435
+	 */
436
+	protected function _get_bulk_actions(): array
437
+	{
438
+		$actions = [];
439
+		// the _views property should have the bulk_actions, so let's go through and extract them into a properly
440
+		// formatted array for the wp_list_table();
441
+		foreach ($this->_views as $view => $args) {
442
+			if ($this->_view === $view && isset($args['bulk_action']) && is_array($args['bulk_action'])) {
443
+				// each bulk action will correspond with a admin page route, so we can check whatever the capability is
444
+				// for that page route and skip adding the bulk action if no access for the current logged in user.
445
+				foreach ($args['bulk_action'] as $route => $label) {
446
+					if ($this->_admin_page->check_user_access($route, true)) {
447
+						$actions[ $route ] = $label;
448
+					}
449
+				}
450
+			}
451
+		}
452
+		return $actions;
453
+	}
454
+
455
+
456
+	/**
457
+	 * Generate the table navigation above or below the table.
458
+	 * Overrides the parent table nav in WP_List_Table so we can hide the bulk action div if there are no bulk actions.
459
+	 *
460
+	 * @throws EE_Error
461
+	 * @since 4.9.44.rc.001
462
+	 */
463
+	public function display_tablenav($which)
464
+	{
465
+		if ('top' === $which) {
466
+			wp_nonce_field('bulk-' . $this->_args['plural']);
467
+		}
468
+		?>
469 469
         <div class="tablenav <?php echo esc_attr($which); ?>">
470 470
             <?php if ($this->_get_bulk_actions()) { ?>
471 471
                 <div class="alignleft actions bulkactions">
472 472
                     <?php $this->bulk_actions(); ?>
473 473
                 </div>
474 474
             <?php }
475
-            $this->extra_tablenav($which);
476
-            $this->pagination($which);
477
-            ?>
475
+			$this->extra_tablenav($which);
476
+			$this->pagination($which);
477
+			?>
478 478
 
479 479
             <br class="clear" />
480 480
         </div>
481 481
         <?php
482
-    }
483
-
484
-
485
-    /**
486
-     * _filters
487
-     * This receives the filters array from children _get_table_filters() and assembles the string including the filter
488
-     * button.
489
-     *
490
-     * @access private
491
-     * @return void  echos html showing filters
492
-     */
493
-    private function _filters(): void
494
-    {
495
-        $classname = get_class($this);
496
-        $filters   = apply_filters(
497
-            "FHEE__{$classname}__filters",
498
-            $this->_get_table_filters(),
499
-            $this,
500
-            $this->_screen
501
-        );
502
-
503
-        if (empty($filters)) {
504
-            return;
505
-        }
506
-
507
-        $this->admin_list_table_filters->filters(
508
-            $filters,
509
-            $this->get_admin_page()->get_current_page_view_url()
510
-        );
511
-    }
512
-
513
-
514
-    /**
515
-     * Callback for 'list_table_primary_column' WordPress filter
516
-     * If child EE_Admin_List_Table classes set the _primary_column property then that will be set as the primary
517
-     * column when class is instantiated.
518
-     *
519
-     * @param string $column_name
520
-     * @return string
521
-     * @see WP_List_Table::get_primary_column_name
522
-     */
523
-    public function set_primary_column($column_name)
524
-    {
525
-        return ! empty($this->_primary_column) ? $this->_primary_column : $column_name;
526
-    }
527
-
528
-
529
-    /**
530
-     *
531
-     */
532
-    public function prepare_items()
533
-    {
534
-        $this->_set_column_info();
535
-        $this->process_bulk_action();
536
-
537
-        $this->items = $this->_data;
538
-        $this->set_pagination_args(
539
-            [
540
-                'total_items' => $this->_all_data_count,
541
-                'per_page'    => $this->_per_page,
542
-                'total_pages' => (int) ceil($this->_all_data_count / $this->_per_page),
543
-            ]
544
-        );
545
-    }
546
-
547
-
548
-    /**
549
-     * @param object|array $item
550
-     * @return string html content for the column
551
-     */
552
-    protected function column_cb($item)
553
-    {
554
-        return '';
555
-    }
556
-
557
-
558
-    /**
559
-     * This column is the default for when there is no defined column method for a registered column.
560
-     * This can be overridden by child classes, but allows for hooking in for custom columns.
561
-     *
562
-     * @param EE_Base_Class $item
563
-     * @param string        $column_name The column being called.
564
-     * @return string html content for the column
565
-     */
566
-    public function column_default($item, $column_name)
567
-    {
568
-        /**
569
-         * Dynamic hook allowing for adding additional column content in this list table.
570
-         * Note that $this->screen->id is in the format
571
-         * {sanitize_title($top_level_menu_label)}_page_{$espresso_admin_page_slug}.  So for the messages list
572
-         * table it is: event-espresso_page_espresso_messages.
573
-         * However, take note that if the top level menu label has been translated (i.e. "Event Espresso"). then the
574
-         * hook prefix ("event-espresso") will be different.
575
-         */
576
-        ob_start();
577
-        do_action(
578
-            'AHEE__EE_Admin_List_Table__column_' . $column_name . '__' . $this->screen->id,
579
-            $item,
580
-            $this->_screen
581
-        );
582
-        $content = ob_get_clean();
583
-        return $column_name === 'actions' ? $this->actionsModalMenu($content) : $content;
584
-    }
585
-
586
-
587
-    /**
588
-     * Get a list of columns. The format is:
589
-     * 'internal-name' => 'Title'
590
-     *
591
-     * @return array
592
-     * @since  3.1.0
593
-     * @access public
594
-     * @abstract
595
-     */
596
-    public function get_columns()
597
-    {
598
-        /**
599
-         * Dynamic hook allowing for adding additional columns in this list table.
600
-         * Note that $this->screen->id is in the format
601
-         * {sanitize_title($top_level_menu_label)}_page_{$espresso_admin_page_slug}.  So for the messages list
602
-         * table it is: event-espresso_page_espresso_messages.
603
-         * However, take note that if the top level menu label has been translated (i.e. "Event Espresso"). then the
604
-         * hook prefix ("event-espresso") will be different.
605
-         *
606
-         * @var array
607
-         */
608
-        return apply_filters("FHEE_manage_{$this->screen->id}_columns", $this->_columns, $this->_screen, $this);
609
-    }
610
-
611
-
612
-    /**
613
-     * Get an associative array ( id => link ) with the list
614
-     * of views available on this table.
615
-     *
616
-     * @return array
617
-     * @since  3.1.0
618
-     * @access protected
619
-     */
620
-    public function get_views()
621
-    {
622
-        return $this->_views;
623
-    }
624
-
625
-
626
-    /**
627
-     * Generate the views html.
628
-     */
629
-    public function display_views()
630
-    {
631
-        $views           = $this->get_views();
632
-        $assembled_views = [];
633
-
634
-        if (empty($views)) {
635
-            return;
636
-        }
637
-        echo "<ul class='subsubsub'>\n";
638
-        foreach ($views as $view) {
639
-            $count = isset($view['count']) && ! empty($view['count']) ? absint($view['count']) : 0;
640
-            if (isset($view['slug'], $view['class'], $view['url'], $view['label'])) {
641
-                $filter = "<li";
642
-                $filter .= $view['class'] ? " class='" . esc_attr($view['class']) . "'" : '';
643
-                $filter .= ">";
644
-                $filter .= '<a href="' . esc_url_raw($view['url']) . '">' . esc_html($view['label']) . '</a>';
645
-                $filter .= '<span class="count">(' . $count . ')</span>';
646
-                $filter .= '</li>';
647
-                $assembled_views[ $view['slug'] ] = $filter;
648
-            }
649
-        }
650
-
651
-        echo ! empty($assembled_views)
652
-            ? implode("<li style='margin:0 .5rem;'>|</li>", $assembled_views)
653
-            : '';
654
-        echo "</ul>";
655
-    }
656
-
657
-
658
-    /**
659
-     * Generates content for a single row of the table
660
-     *
661
-     * @param EE_Base_Class $item The current item
662
-     * @since  4.1
663
-     * @access public
664
-     */
665
-    public function single_row($item)
666
-    {
667
-        $row_class = $this->_get_row_class($item);
668
-        echo '<tr class="' . esc_attr($row_class) . '">';
669
-        $this->single_row_columns($item); // already escaped
670
-        echo '</tr>';
671
-    }
672
-
673
-
674
-    /**
675
-     * This simply sets up the row class for the table rows.
676
-     * Allows for easier overriding of child methods for setting up sorting.
677
-     *
678
-     * @param EE_Base_Class $item the current item
679
-     * @return string
680
-     */
681
-    protected function _get_row_class($item)
682
-    {
683
-        static $row_class = '';
684
-        $row_class = ($row_class === '' ? 'alternate' : '');
685
-
686
-        $new_row_class = $row_class;
687
-
688
-        if (! empty($this->_ajax_sorting_callback)) {
689
-            $new_row_class .= ' rowsortable';
690
-        }
691
-
692
-        return $new_row_class;
693
-    }
694
-
695
-
696
-    /**
697
-     * @return array
698
-     */
699
-    public function get_sortable_columns()
700
-    {
701
-        return (array) $this->_sortable_columns;
702
-    }
703
-
704
-
705
-    /**
706
-     * @return string
707
-     */
708
-    public function get_ajax_sorting_callback()
709
-    {
710
-        return $this->_ajax_sorting_callback;
711
-    }
712
-
713
-
714
-    /**
715
-     * @return array
716
-     */
717
-    public function get_hidden_columns()
718
-    {
719
-        $user_id     = get_current_user_id();
720
-        $has_default = get_user_option('default' . $this->screen->id . 'columnshidden', $user_id);
721
-        if (empty($has_default) && ! empty($this->_hidden_columns)) {
722
-            update_user_option($user_id, 'default' . $this->screen->id . 'columnshidden', true);
723
-            update_user_option($user_id, 'manage' . $this->screen->id . 'columnshidden', $this->_hidden_columns, true);
724
-        }
725
-        $ref = 'manage' . $this->screen->id . 'columnshidden';
726
-        return (array) get_user_option($ref, $user_id);
727
-    }
728
-
729
-
730
-    /**
731
-     * Generates the columns for a single row of the table.
732
-     * Overridden from wp_list_table so as to allow us to filter the column content for a given
733
-     * column.
734
-     *
735
-     * @param EE_Base_Class $item The current item
736
-     * @since 3.1.0
737
-     */
738
-    public function single_row_columns($item)
739
-    {
740
-        [$columns, $hidden, $sortable, $primary] = $this->get_column_info();
741
-
742
-        foreach ($columns as $column_name => $column_display_name) {
743
-
744
-            /**
745
-             * With WordPress version 4.3.RC+ WordPress started using the hidden css class to control whether columns
746
-             * are hidden or not instead of using "display:none;".  This bit of code provides backward compat.
747
-             */
748
-            $hidden_class = in_array($column_name, $hidden) ? ' hidden' : '';
749
-
750
-            $classes = $column_name . ' column-' . $column_name . $hidden_class;
751
-            if ($primary === $column_name) {
752
-                $classes .= ' has-row-actions column-primary';
753
-            }
754
-
755
-            $data = ' data-colname="' . wp_strip_all_tags($column_display_name) . '"';
756
-
757
-            $class = 'class="' . esc_attr($classes) . '"';
758
-
759
-            $attributes = "{$class}{$data}";
760
-
761
-            if ($column_name === 'cb') {
762
-                echo '<th scope="row" class="check-column">';
763
-                echo apply_filters(
764
-                    'FHEE__EE_Admin_List_Table__single_row_columns__column_cb_content',
765
-                    $this->column_cb($item), // already escaped
766
-                    $item,
767
-                    $this
768
-                );
769
-                echo '</th>';
770
-            } elseif (method_exists($this, "column_$column_name")) {
771
-                echo "<td $attributes>"; // already escaped
772
-                echo apply_filters(
773
-                    'FHEE__EE_Admin_List_Table__single_row_columns__column_' . $column_name . '__column_content',
774
-                    call_user_func([$this, "column_$column_name"], $item),
775
-                    $item,
776
-                    $this
777
-                );
778
-                echo wp_kses($this->handle_row_actions($item, $column_name, $primary), AllowedTags::getWithFormTags());
779
-                echo "</td>";
780
-            } else {
781
-                echo "<td $attributes>"; // already escaped
782
-                echo apply_filters(
783
-                    'FHEE__EE_Admin_List_Table__single_row_columns__column_default__column_content',
784
-                    $this->column_default($item, $column_name),
785
-                    $item,
786
-                    $column_name,
787
-                    $this
788
-                );
789
-                echo wp_kses($this->handle_row_actions($item, $column_name, $primary), AllowedTags::getWithFormTags());
790
-                echo "</td>";
791
-            }
792
-        }
793
-    }
794
-
795
-
796
-    /**
797
-     * Extra controls to be displayed between bulk actions and pagination
798
-     *
799
-     * @access public
800
-     * @param string $which
801
-     * @throws EE_Error
802
-     */
803
-    public function extra_tablenav($which)
804
-    {
805
-        if ($which === 'top') {
806
-            $this->_filters();
807
-            echo wp_kses($this->_get_hidden_fields(), AllowedTags::getWithFormTags());
808
-        } else {
809
-            echo '<div class="list-table-bottom-buttons alignleft actions">';
810
-            foreach ($this->_bottom_buttons as $type => $action) {
811
-                $route         = $action['route'] ?? '';
812
-                $extra_request = $action['extra_request'] ?? '';
813
-                $btn_class     = $action['btn_class'] ?? 'button button--secondary';
814
-                // already escaped
815
-                echo wp_kses($this->_admin_page->get_action_link_or_button(
816
-                    $route,
817
-                    $type,
818
-                    $extra_request,
819
-                    $btn_class
820
-                ), AllowedTags::getWithFormTags());
821
-            }
822
-            do_action('AHEE__EE_Admin_List_Table__extra_tablenav__after_bottom_buttons', $this, $this->_screen);
823
-            echo '</div>';
824
-        }
825
-    }
826
-
827
-
828
-    /**
829
-     * Get an associative array ( option_name => option_title ) with the list
830
-     * of bulk actions available on this table.
831
-     *
832
-     * @return array
833
-     * @since  3.1.0
834
-     * @access protected
835
-     */
836
-    public function get_bulk_actions()
837
-    {
838
-        return (array) $this->_get_bulk_actions();
839
-    }
840
-
841
-
842
-    /**
843
-     * Processing bulk actions.
844
-     */
845
-    public function process_bulk_action()
846
-    {
847
-        // this is not used it is handled by the child EE_Admin_Page class (routes).  However, including here for
848
-        // reference in case there is a case where it gets used.
849
-    }
850
-
851
-
852
-    /**
853
-     * returns the EE admin page this list table is associated with
854
-     *
855
-     * @return EE_Admin_Page
856
-     */
857
-    public function get_admin_page()
858
-    {
859
-        return $this->_admin_page;
860
-    }
861
-
862
-
863
-    /**
864
-     * A "helper" function for all children to provide an html string of
865
-     * actions to output in their content.  It is preferable for child classes
866
-     * to use this method for generating their actions content so that it's
867
-     * filterable by plugins
868
-     *
869
-     * @param string        $action_container           what are the html container
870
-     *                                                  elements for this actions string?
871
-     * @param string        $action_class               What class is for the container
872
-     *                                                  element.
873
-     * @param string        $action_items               The contents for the action items
874
-     *                                                  container.  This is filtered before
875
-     *                                                  returned.
876
-     * @param string        $action_id                  What id (optional) is used for the
877
-     *                                                  container element.
878
-     * @param EE_Base_Class $item                       The object for the column displaying
879
-     *                                                  the actions.
880
-     * @return string The assembled action elements container.
881
-     */
882
-    protected function _action_string(
883
-        $action_items,
884
-        $item,
885
-        $action_container = 'ul',
886
-        $action_class = '',
887
-        $action_id = ''
888
-    ) {
889
-        $action_class = ! empty($action_class) ? ' class="' . esc_attr($action_class) . '"' : '';
890
-        $action_id    = ! empty($action_id) ? ' id="' . esc_attr($action_id) . '"' : '';
891
-        $open_tag     = ! empty($action_container) ? '<' . $action_container . $action_class . $action_id . '>' : '';
892
-        $close_tag    = ! empty($action_container) ? '</' . $action_container . '>' : '';
893
-        try {
894
-            $content = apply_filters(
895
-                'FHEE__EE_Admin_List_Table___action_string__action_items',
896
-                $action_items,
897
-                $item,
898
-                $this
899
-            );
900
-        } catch (Exception $e) {
901
-            if (WP_DEBUG) {
902
-                EE_Error::add_error($e->getMessage(), __FILE__, __FUNCTION__, __LINE__);
903
-            }
904
-            $content = $action_items;
905
-        }
906
-        return "{$open_tag}{$content}{$close_tag}";
907
-    }
908
-
909
-
910
-    /**
911
-     * @return string
912
-     */
913
-    protected function getReturnUrl()
914
-    {
915
-        $host = $this->_admin_page->get_request()->getServerParam('HTTP_HOST');
916
-        $uri  = $this->_admin_page->get_request()->getServerParam('REQUEST_URI');
917
-        return urlencode(esc_url_raw("//{$host}{$uri}"));
918
-    }
919
-
920
-
921
-    /**
922
-     * @param string $id
923
-     * @param string $content
924
-     * @param string $align     start (default), center, end
925
-     * @return string
926
-     * @since   5.0.0.p
927
-     */
928
-    protected function columnContent($id, $content, $align = 'start')
929
-    {
930
-        if (! isset($this->_columns[ $id ])) {
931
-            throw new DomainException('missing column id');
932
-        }
933
-        $heading = $id !== 'cb' ? $this->_columns[ $id ] : '';
934
-        $align = in_array($align, ['start', 'center', 'end']) ? $align : 'start';
935
-        $align = "ee-responsive-table-cell--{$align}";
936
-
937
-        $html = "<div class='ee-responsive-table-cell ee-responsive-table-cell--column-{$id} {$align} ee-layout-row'>";
938
-        $html .= "<div class='ee-responsive-table-cell__heading'>{$heading}</div>";
939
-        $html .= "<div class='ee-responsive-table-cell__content ee-layout-row'>{$content}</div>";
940
-        $html .= "</div>";
941
-        return $html;
942
-    }
943
-
944
-
945
-    protected function actionsModalMenu($actions): string
946
-    {
947
-        return '
482
+	}
483
+
484
+
485
+	/**
486
+	 * _filters
487
+	 * This receives the filters array from children _get_table_filters() and assembles the string including the filter
488
+	 * button.
489
+	 *
490
+	 * @access private
491
+	 * @return void  echos html showing filters
492
+	 */
493
+	private function _filters(): void
494
+	{
495
+		$classname = get_class($this);
496
+		$filters   = apply_filters(
497
+			"FHEE__{$classname}__filters",
498
+			$this->_get_table_filters(),
499
+			$this,
500
+			$this->_screen
501
+		);
502
+
503
+		if (empty($filters)) {
504
+			return;
505
+		}
506
+
507
+		$this->admin_list_table_filters->filters(
508
+			$filters,
509
+			$this->get_admin_page()->get_current_page_view_url()
510
+		);
511
+	}
512
+
513
+
514
+	/**
515
+	 * Callback for 'list_table_primary_column' WordPress filter
516
+	 * If child EE_Admin_List_Table classes set the _primary_column property then that will be set as the primary
517
+	 * column when class is instantiated.
518
+	 *
519
+	 * @param string $column_name
520
+	 * @return string
521
+	 * @see WP_List_Table::get_primary_column_name
522
+	 */
523
+	public function set_primary_column($column_name)
524
+	{
525
+		return ! empty($this->_primary_column) ? $this->_primary_column : $column_name;
526
+	}
527
+
528
+
529
+	/**
530
+	 *
531
+	 */
532
+	public function prepare_items()
533
+	{
534
+		$this->_set_column_info();
535
+		$this->process_bulk_action();
536
+
537
+		$this->items = $this->_data;
538
+		$this->set_pagination_args(
539
+			[
540
+				'total_items' => $this->_all_data_count,
541
+				'per_page'    => $this->_per_page,
542
+				'total_pages' => (int) ceil($this->_all_data_count / $this->_per_page),
543
+			]
544
+		);
545
+	}
546
+
547
+
548
+	/**
549
+	 * @param object|array $item
550
+	 * @return string html content for the column
551
+	 */
552
+	protected function column_cb($item)
553
+	{
554
+		return '';
555
+	}
556
+
557
+
558
+	/**
559
+	 * This column is the default for when there is no defined column method for a registered column.
560
+	 * This can be overridden by child classes, but allows for hooking in for custom columns.
561
+	 *
562
+	 * @param EE_Base_Class $item
563
+	 * @param string        $column_name The column being called.
564
+	 * @return string html content for the column
565
+	 */
566
+	public function column_default($item, $column_name)
567
+	{
568
+		/**
569
+		 * Dynamic hook allowing for adding additional column content in this list table.
570
+		 * Note that $this->screen->id is in the format
571
+		 * {sanitize_title($top_level_menu_label)}_page_{$espresso_admin_page_slug}.  So for the messages list
572
+		 * table it is: event-espresso_page_espresso_messages.
573
+		 * However, take note that if the top level menu label has been translated (i.e. "Event Espresso"). then the
574
+		 * hook prefix ("event-espresso") will be different.
575
+		 */
576
+		ob_start();
577
+		do_action(
578
+			'AHEE__EE_Admin_List_Table__column_' . $column_name . '__' . $this->screen->id,
579
+			$item,
580
+			$this->_screen
581
+		);
582
+		$content = ob_get_clean();
583
+		return $column_name === 'actions' ? $this->actionsModalMenu($content) : $content;
584
+	}
585
+
586
+
587
+	/**
588
+	 * Get a list of columns. The format is:
589
+	 * 'internal-name' => 'Title'
590
+	 *
591
+	 * @return array
592
+	 * @since  3.1.0
593
+	 * @access public
594
+	 * @abstract
595
+	 */
596
+	public function get_columns()
597
+	{
598
+		/**
599
+		 * Dynamic hook allowing for adding additional columns in this list table.
600
+		 * Note that $this->screen->id is in the format
601
+		 * {sanitize_title($top_level_menu_label)}_page_{$espresso_admin_page_slug}.  So for the messages list
602
+		 * table it is: event-espresso_page_espresso_messages.
603
+		 * However, take note that if the top level menu label has been translated (i.e. "Event Espresso"). then the
604
+		 * hook prefix ("event-espresso") will be different.
605
+		 *
606
+		 * @var array
607
+		 */
608
+		return apply_filters("FHEE_manage_{$this->screen->id}_columns", $this->_columns, $this->_screen, $this);
609
+	}
610
+
611
+
612
+	/**
613
+	 * Get an associative array ( id => link ) with the list
614
+	 * of views available on this table.
615
+	 *
616
+	 * @return array
617
+	 * @since  3.1.0
618
+	 * @access protected
619
+	 */
620
+	public function get_views()
621
+	{
622
+		return $this->_views;
623
+	}
624
+
625
+
626
+	/**
627
+	 * Generate the views html.
628
+	 */
629
+	public function display_views()
630
+	{
631
+		$views           = $this->get_views();
632
+		$assembled_views = [];
633
+
634
+		if (empty($views)) {
635
+			return;
636
+		}
637
+		echo "<ul class='subsubsub'>\n";
638
+		foreach ($views as $view) {
639
+			$count = isset($view['count']) && ! empty($view['count']) ? absint($view['count']) : 0;
640
+			if (isset($view['slug'], $view['class'], $view['url'], $view['label'])) {
641
+				$filter = "<li";
642
+				$filter .= $view['class'] ? " class='" . esc_attr($view['class']) . "'" : '';
643
+				$filter .= ">";
644
+				$filter .= '<a href="' . esc_url_raw($view['url']) . '">' . esc_html($view['label']) . '</a>';
645
+				$filter .= '<span class="count">(' . $count . ')</span>';
646
+				$filter .= '</li>';
647
+				$assembled_views[ $view['slug'] ] = $filter;
648
+			}
649
+		}
650
+
651
+		echo ! empty($assembled_views)
652
+			? implode("<li style='margin:0 .5rem;'>|</li>", $assembled_views)
653
+			: '';
654
+		echo "</ul>";
655
+	}
656
+
657
+
658
+	/**
659
+	 * Generates content for a single row of the table
660
+	 *
661
+	 * @param EE_Base_Class $item The current item
662
+	 * @since  4.1
663
+	 * @access public
664
+	 */
665
+	public function single_row($item)
666
+	{
667
+		$row_class = $this->_get_row_class($item);
668
+		echo '<tr class="' . esc_attr($row_class) . '">';
669
+		$this->single_row_columns($item); // already escaped
670
+		echo '</tr>';
671
+	}
672
+
673
+
674
+	/**
675
+	 * This simply sets up the row class for the table rows.
676
+	 * Allows for easier overriding of child methods for setting up sorting.
677
+	 *
678
+	 * @param EE_Base_Class $item the current item
679
+	 * @return string
680
+	 */
681
+	protected function _get_row_class($item)
682
+	{
683
+		static $row_class = '';
684
+		$row_class = ($row_class === '' ? 'alternate' : '');
685
+
686
+		$new_row_class = $row_class;
687
+
688
+		if (! empty($this->_ajax_sorting_callback)) {
689
+			$new_row_class .= ' rowsortable';
690
+		}
691
+
692
+		return $new_row_class;
693
+	}
694
+
695
+
696
+	/**
697
+	 * @return array
698
+	 */
699
+	public function get_sortable_columns()
700
+	{
701
+		return (array) $this->_sortable_columns;
702
+	}
703
+
704
+
705
+	/**
706
+	 * @return string
707
+	 */
708
+	public function get_ajax_sorting_callback()
709
+	{
710
+		return $this->_ajax_sorting_callback;
711
+	}
712
+
713
+
714
+	/**
715
+	 * @return array
716
+	 */
717
+	public function get_hidden_columns()
718
+	{
719
+		$user_id     = get_current_user_id();
720
+		$has_default = get_user_option('default' . $this->screen->id . 'columnshidden', $user_id);
721
+		if (empty($has_default) && ! empty($this->_hidden_columns)) {
722
+			update_user_option($user_id, 'default' . $this->screen->id . 'columnshidden', true);
723
+			update_user_option($user_id, 'manage' . $this->screen->id . 'columnshidden', $this->_hidden_columns, true);
724
+		}
725
+		$ref = 'manage' . $this->screen->id . 'columnshidden';
726
+		return (array) get_user_option($ref, $user_id);
727
+	}
728
+
729
+
730
+	/**
731
+	 * Generates the columns for a single row of the table.
732
+	 * Overridden from wp_list_table so as to allow us to filter the column content for a given
733
+	 * column.
734
+	 *
735
+	 * @param EE_Base_Class $item The current item
736
+	 * @since 3.1.0
737
+	 */
738
+	public function single_row_columns($item)
739
+	{
740
+		[$columns, $hidden, $sortable, $primary] = $this->get_column_info();
741
+
742
+		foreach ($columns as $column_name => $column_display_name) {
743
+
744
+			/**
745
+			 * With WordPress version 4.3.RC+ WordPress started using the hidden css class to control whether columns
746
+			 * are hidden or not instead of using "display:none;".  This bit of code provides backward compat.
747
+			 */
748
+			$hidden_class = in_array($column_name, $hidden) ? ' hidden' : '';
749
+
750
+			$classes = $column_name . ' column-' . $column_name . $hidden_class;
751
+			if ($primary === $column_name) {
752
+				$classes .= ' has-row-actions column-primary';
753
+			}
754
+
755
+			$data = ' data-colname="' . wp_strip_all_tags($column_display_name) . '"';
756
+
757
+			$class = 'class="' . esc_attr($classes) . '"';
758
+
759
+			$attributes = "{$class}{$data}";
760
+
761
+			if ($column_name === 'cb') {
762
+				echo '<th scope="row" class="check-column">';
763
+				echo apply_filters(
764
+					'FHEE__EE_Admin_List_Table__single_row_columns__column_cb_content',
765
+					$this->column_cb($item), // already escaped
766
+					$item,
767
+					$this
768
+				);
769
+				echo '</th>';
770
+			} elseif (method_exists($this, "column_$column_name")) {
771
+				echo "<td $attributes>"; // already escaped
772
+				echo apply_filters(
773
+					'FHEE__EE_Admin_List_Table__single_row_columns__column_' . $column_name . '__column_content',
774
+					call_user_func([$this, "column_$column_name"], $item),
775
+					$item,
776
+					$this
777
+				);
778
+				echo wp_kses($this->handle_row_actions($item, $column_name, $primary), AllowedTags::getWithFormTags());
779
+				echo "</td>";
780
+			} else {
781
+				echo "<td $attributes>"; // already escaped
782
+				echo apply_filters(
783
+					'FHEE__EE_Admin_List_Table__single_row_columns__column_default__column_content',
784
+					$this->column_default($item, $column_name),
785
+					$item,
786
+					$column_name,
787
+					$this
788
+				);
789
+				echo wp_kses($this->handle_row_actions($item, $column_name, $primary), AllowedTags::getWithFormTags());
790
+				echo "</td>";
791
+			}
792
+		}
793
+	}
794
+
795
+
796
+	/**
797
+	 * Extra controls to be displayed between bulk actions and pagination
798
+	 *
799
+	 * @access public
800
+	 * @param string $which
801
+	 * @throws EE_Error
802
+	 */
803
+	public function extra_tablenav($which)
804
+	{
805
+		if ($which === 'top') {
806
+			$this->_filters();
807
+			echo wp_kses($this->_get_hidden_fields(), AllowedTags::getWithFormTags());
808
+		} else {
809
+			echo '<div class="list-table-bottom-buttons alignleft actions">';
810
+			foreach ($this->_bottom_buttons as $type => $action) {
811
+				$route         = $action['route'] ?? '';
812
+				$extra_request = $action['extra_request'] ?? '';
813
+				$btn_class     = $action['btn_class'] ?? 'button button--secondary';
814
+				// already escaped
815
+				echo wp_kses($this->_admin_page->get_action_link_or_button(
816
+					$route,
817
+					$type,
818
+					$extra_request,
819
+					$btn_class
820
+				), AllowedTags::getWithFormTags());
821
+			}
822
+			do_action('AHEE__EE_Admin_List_Table__extra_tablenav__after_bottom_buttons', $this, $this->_screen);
823
+			echo '</div>';
824
+		}
825
+	}
826
+
827
+
828
+	/**
829
+	 * Get an associative array ( option_name => option_title ) with the list
830
+	 * of bulk actions available on this table.
831
+	 *
832
+	 * @return array
833
+	 * @since  3.1.0
834
+	 * @access protected
835
+	 */
836
+	public function get_bulk_actions()
837
+	{
838
+		return (array) $this->_get_bulk_actions();
839
+	}
840
+
841
+
842
+	/**
843
+	 * Processing bulk actions.
844
+	 */
845
+	public function process_bulk_action()
846
+	{
847
+		// this is not used it is handled by the child EE_Admin_Page class (routes).  However, including here for
848
+		// reference in case there is a case where it gets used.
849
+	}
850
+
851
+
852
+	/**
853
+	 * returns the EE admin page this list table is associated with
854
+	 *
855
+	 * @return EE_Admin_Page
856
+	 */
857
+	public function get_admin_page()
858
+	{
859
+		return $this->_admin_page;
860
+	}
861
+
862
+
863
+	/**
864
+	 * A "helper" function for all children to provide an html string of
865
+	 * actions to output in their content.  It is preferable for child classes
866
+	 * to use this method for generating their actions content so that it's
867
+	 * filterable by plugins
868
+	 *
869
+	 * @param string        $action_container           what are the html container
870
+	 *                                                  elements for this actions string?
871
+	 * @param string        $action_class               What class is for the container
872
+	 *                                                  element.
873
+	 * @param string        $action_items               The contents for the action items
874
+	 *                                                  container.  This is filtered before
875
+	 *                                                  returned.
876
+	 * @param string        $action_id                  What id (optional) is used for the
877
+	 *                                                  container element.
878
+	 * @param EE_Base_Class $item                       The object for the column displaying
879
+	 *                                                  the actions.
880
+	 * @return string The assembled action elements container.
881
+	 */
882
+	protected function _action_string(
883
+		$action_items,
884
+		$item,
885
+		$action_container = 'ul',
886
+		$action_class = '',
887
+		$action_id = ''
888
+	) {
889
+		$action_class = ! empty($action_class) ? ' class="' . esc_attr($action_class) . '"' : '';
890
+		$action_id    = ! empty($action_id) ? ' id="' . esc_attr($action_id) . '"' : '';
891
+		$open_tag     = ! empty($action_container) ? '<' . $action_container . $action_class . $action_id . '>' : '';
892
+		$close_tag    = ! empty($action_container) ? '</' . $action_container . '>' : '';
893
+		try {
894
+			$content = apply_filters(
895
+				'FHEE__EE_Admin_List_Table___action_string__action_items',
896
+				$action_items,
897
+				$item,
898
+				$this
899
+			);
900
+		} catch (Exception $e) {
901
+			if (WP_DEBUG) {
902
+				EE_Error::add_error($e->getMessage(), __FILE__, __FUNCTION__, __LINE__);
903
+			}
904
+			$content = $action_items;
905
+		}
906
+		return "{$open_tag}{$content}{$close_tag}";
907
+	}
908
+
909
+
910
+	/**
911
+	 * @return string
912
+	 */
913
+	protected function getReturnUrl()
914
+	{
915
+		$host = $this->_admin_page->get_request()->getServerParam('HTTP_HOST');
916
+		$uri  = $this->_admin_page->get_request()->getServerParam('REQUEST_URI');
917
+		return urlencode(esc_url_raw("//{$host}{$uri}"));
918
+	}
919
+
920
+
921
+	/**
922
+	 * @param string $id
923
+	 * @param string $content
924
+	 * @param string $align     start (default), center, end
925
+	 * @return string
926
+	 * @since   5.0.0.p
927
+	 */
928
+	protected function columnContent($id, $content, $align = 'start')
929
+	{
930
+		if (! isset($this->_columns[ $id ])) {
931
+			throw new DomainException('missing column id');
932
+		}
933
+		$heading = $id !== 'cb' ? $this->_columns[ $id ] : '';
934
+		$align = in_array($align, ['start', 'center', 'end']) ? $align : 'start';
935
+		$align = "ee-responsive-table-cell--{$align}";
936
+
937
+		$html = "<div class='ee-responsive-table-cell ee-responsive-table-cell--column-{$id} {$align} ee-layout-row'>";
938
+		$html .= "<div class='ee-responsive-table-cell__heading'>{$heading}</div>";
939
+		$html .= "<div class='ee-responsive-table-cell__content ee-layout-row'>{$content}</div>";
940
+		$html .= "</div>";
941
+		return $html;
942
+	}
943
+
944
+
945
+	protected function actionsModalMenu($actions): string
946
+	{
947
+		return '
948 948
         <div class="ee-modal-menu">
949 949
             <button class="ee-modal-menu__button button button--secondary button--icon-only ee-aria-tooltip"
950 950
                     aria-label="' . esc_attr__('list table actions menu', 'event_espresso') . '"
@@ -956,43 +956,43 @@  discard block
 block discarded – undo
956 956
                 ' . $actions . '
957 957
             </div>
958 958
         </div>';
959
-    }
959
+	}
960 960
 
961 961
 
962
-    public function actionsColumnHeader(): string
963
-    {
964
-        return '
962
+	public function actionsColumnHeader(): string
963
+	{
964
+		return '
965 965
             <span class="ee-actions-column-header-wrap">
966 966
                 <span class="dashicons dashicons-screenoptions"></span>
967 967
                 <span class="ee-actions-column-header">' . esc_html__('Actions', 'event_espresso') . '</span>
968 968
             </span>';
969
-    }
970
-
971
-
972
-    protected function getActionLink(string $url, string $display_text, string $label, $class = ''): string
973
-    {
974
-        $class = ! empty($class) ? "{$class} ee-list-table-action" : 'ee-list-table-action';
975
-        $class = ! empty($label) ? "{$class} ee-aria-tooltip" : $class;
976
-        $label = ! empty($label) ? " aria-label='{$label}'" : '';
977
-        return "<a href='{$url}' class='{$class}'{$label}>{$display_text}</a>";
978
-    }
979
-
980
-    /**
981
-     * Override the search box method of WP List Table to include a reset button
982
-     *
983
-     * @param string $text     The 'submit' button label.
984
-     * @param string $input_id ID attribute value for the search input field.
985
-     */
986
-    public function search_box($text, $input_id)
987
-    {
988
-        if (empty($_REQUEST['s']) && ! $this->has_items()) {
989
-            return;
990
-        }
991
-
992
-        $this->admin_list_table_filters->searchBox(
993
-            $text,
994
-            $input_id,
995
-            $this->get_admin_page()->get_current_page_view_url()
996
-        );
997
-    }
969
+	}
970
+
971
+
972
+	protected function getActionLink(string $url, string $display_text, string $label, $class = ''): string
973
+	{
974
+		$class = ! empty($class) ? "{$class} ee-list-table-action" : 'ee-list-table-action';
975
+		$class = ! empty($label) ? "{$class} ee-aria-tooltip" : $class;
976
+		$label = ! empty($label) ? " aria-label='{$label}'" : '';
977
+		return "<a href='{$url}' class='{$class}'{$label}>{$display_text}</a>";
978
+	}
979
+
980
+	/**
981
+	 * Override the search box method of WP List Table to include a reset button
982
+	 *
983
+	 * @param string $text     The 'submit' button label.
984
+	 * @param string $input_id ID attribute value for the search input field.
985
+	 */
986
+	public function search_box($text, $input_id)
987
+	{
988
+		if (empty($_REQUEST['s']) && ! $this->has_items()) {
989
+			return;
990
+		}
991
+
992
+		$this->admin_list_table_filters->searchBox(
993
+			$text,
994
+			$input_id,
995
+			$this->get_admin_page()->get_current_page_view_url()
996
+		);
997
+	}
998 998
 }
Please login to merge, or discard this patch.
core/admin/EE_Admin_Page_Init.core.php 1 patch
Indentation   +490 added lines, -490 removed lines patch added patch discarded remove patch
@@ -18,497 +18,497 @@
 block discarded – undo
18 18
  */
19 19
 abstract class EE_Admin_Page_Init extends EE_Base
20 20
 {
21
-    // identity properties (set in _set_defaults and _set_init_properties)
22
-    public $label;
21
+	// identity properties (set in _set_defaults and _set_init_properties)
22
+	public $label;
23 23
 
24
-    /**
25
-     * Menu map has a capability.  However, this allows admin pages to have separate capability requirements for menus
26
-     * and accessing pages.  If capability is NOT set, then it defaults to the menu_map capability.
27
-     *
28
-     * @var string
29
-     */
30
-    public $capability;
24
+	/**
25
+	 * Menu map has a capability.  However, this allows admin pages to have separate capability requirements for menus
26
+	 * and accessing pages.  If capability is NOT set, then it defaults to the menu_map capability.
27
+	 *
28
+	 * @var string
29
+	 */
30
+	public $capability;
31 31
 
32 32
 
33
-    /**
34
-     * This holds the menu map object for this admin page.
35
-     *
36
-     * @var AdminMenuItem
37
-     */
38
-    protected $_menu_map = null;
39
-
40
-    /**
41
-     * deprecated
42
-     */
43
-    public $menu_label;
44
-
45
-    public $menu_slug;
46
-
47
-
48
-    // set in _set_defaults
49
-    protected $_folder_name;
50
-
51
-    protected $_folder_path;
52
-
53
-    protected $_file_name;
54
-
55
-    public $hook_file;
56
-
57
-    protected $_wp_page_slug;
58
-
59
-    protected $_routing;
60
-
61
-
62
-    /**
63
-     * This holds the page object.
64
-     *
65
-     * @var EE_Admin_Page
66
-     */
67
-    protected $_loaded_page_object;
68
-
69
-
70
-    // for caf
71
-    protected $_files_hooked;
72
-
73
-    protected $_hook_paths;
74
-
75
-    // load_page?
76
-    private $_load_page;
77
-
78
-    /**
79
-     * @var LoaderInterface
80
-     */
81
-    protected $loader;
82
-
83
-    /**
84
-     * @var RequestInterface
85
-     */
86
-    protected $request;
87
-
88
-
89
-    /**
90
-     * @throws InvalidArgumentException
91
-     * @throws InvalidDataTypeException
92
-     * @throws InvalidInterfaceException
93
-     */
94
-    public function __construct(RequestInterface $request = null)
95
-    {
96
-        $this->loader  = LoaderFactory::getLoader();
97
-        $this->request = $request instanceof RequestInterface
98
-            ? $request
99
-            : $this->loader->getShared(RequestInterface::class);
100
-        // set global defaults
101
-        $this->_set_defaults();
102
-        // set properties that are always available with objects.
103
-        $this->_set_init_properties();
104
-        // global styles/scripts across all wp admin pages
105
-        add_action('admin_enqueue_scripts', [$this, 'load_wp_global_scripts_styles'], 5);
106
-        // load initial stuff.
107
-        $this->_set_file_and_folder_name();
108
-    }
109
-
110
-
111
-    /**
112
-     * _set_init_properties
113
-     * Child classes use to set the following properties:
114
-     * $label
115
-     *
116
-     * @abstract
117
-     * @return void
118
-     */
119
-    abstract protected function _set_init_properties();
120
-
121
-
122
-    /**
123
-     * @return AdminMenuItem|null
124
-     * @since       4.4.0
125
-     * @deprecated  5.0.0.p
126
-     */
127
-    public function get_menu_map()
128
-    {
129
-        return $this->adminMenu();
130
-    }
131
-
132
-
133
-    /**
134
-     * _set_menu_map is a function that child classes use to set the menu_map property (which should be an instance of
135
-     * EE_Admin_Page_Menu_Map.  Their menu can either be EE_Admin_Page_Main_Menu or AdminMenuSubItem.
136
-     *
137
-     * @since       4.4.0
138
-     * @deprecated  5.0.0.p
139
-     */
140
-    protected function _set_menu_map()
141
-    {
142
-        $this->_menu_map = null;
143
-    }
144
-
145
-
146
-    /**
147
-     * @since   5.0.0.p
148
-     */
149
-    public function setupLegacyAdminMenuItem()
150
-    {
151
-        // will be overridden by child classes not using new system
152
-        $this->_set_menu_map();
153
-    }
154
-
155
-
156
-    /**
157
-     * Child classes should return an array of properties used to construct the AdminMenuItem
158
-     *
159
-     * @return array
160
-     * @since 5.0.0.p
161
-     */
162
-    public function getMenuProperties(): array
163
-    {
164
-        return [];
165
-    }
166
-
167
-
168
-    /**
169
-     * @param AdminMenuItem $menu
170
-     * @return void
171
-     * @since 5.0.0.p
172
-     */
173
-    public function setAdminMenu(AdminMenuItem $menu): void
174
-    {
175
-        $this->_menu_map = $menu;
176
-    }
177
-
178
-
179
-    /**
180
-     * returns the menu map for this admin page
181
-     *
182
-     * @return AdminMenuItem|null
183
-     * @since 5.0.0.p
184
-     */
185
-    public function adminMenu(): ?AdminMenuItem
186
-    {
187
-        return $this->_menu_map;
188
-    }
189
-
190
-
191
-    /**
192
-     * @param string $wp_page_slug
193
-     * @since 5.0.0.p
194
-     */
195
-    public function setWpPageSlug(string $wp_page_slug): void
196
-    {
197
-        $this->_wp_page_slug = $wp_page_slug;
198
-    }
199
-
200
-
201
-    /**
202
-     * This loads scripts and styles for the EE_Admin system
203
-     * that must be available on ALL WP admin pages (i.e. EE_menu items)
204
-     *
205
-     * @return void
206
-     */
207
-    public function load_wp_global_scripts_styles()
208
-    {
209
-        wp_register_style(
210
-            'espresso_menu',
211
-            EE_ADMIN_URL . 'assets/admin-menu-styles.css',
212
-            ['dashicons'],
213
-            EVENT_ESPRESSO_VERSION
214
-        );
215
-        wp_enqueue_style('espresso_menu');
216
-    }
217
-
218
-
219
-    /**
220
-     * this sets default properties (might be overridden in _set_init_properties);
221
-     *
222
-     * @return  void
223
-     */
224
-    private function _set_defaults()
225
-    {
226
-        $this->_file_name    = $this->_folder_name = $this->_wp_page_slug = $this->capability = null;
227
-        $this->_routing      = true;
228
-        $this->_load_page    = false;
229
-        $this->_files_hooked = $this->_hook_paths = [];
230
-    }
231
-
232
-
233
-    public function setCapability($capability, $menu_slug)
234
-    {
235
-        $this->capability = apply_filters('FHEE_' . $menu_slug . '_capability', $capability);
236
-    }
237
-
238
-
239
-    /**
240
-     * @deprecated 5.0.0.p
241
-     */
242
-    protected function _set_capability()
243
-    {
244
-        if ($this->_menu_map instanceof AdminMenuItem) {
245
-            $this->setCapability($this->_menu_map->capability(), $this->_menu_map->menuSlug());
246
-        }
247
-    }
248
-
249
-
250
-    /**
251
-     * initialize_admin_page
252
-     * This method is what executes the loading of the specific page class for the given dir_name as called by the
253
-     * EE_Admin_Init class.
254
-     *
255
-     * @return void
256
-     * @throws EE_Error
257
-     * @throws ReflectionException
258
-     */
259
-    public function initialize_admin_page()
260
-    {
261
-        // let's check user access first
262
-        $this->_check_user_access();
263
-        if (! $this->_loaded_page_object instanceof EE_Admin_Page) {
264
-            return;
265
-        }
266
-        $this->_loaded_page_object->route_admin_request();
267
-    }
268
-
269
-
270
-    /**
271
-     * @param string $wp_page_slug
272
-     * @throws EE_Error
273
-     */
274
-    public function set_page_dependencies(string $wp_page_slug)
275
-    {
276
-        if (! $this->_load_page) {
277
-            return;
278
-        }
279
-        if (! $this->_loaded_page_object instanceof EE_Admin_Page) {
280
-            $msg[] = esc_html__(
281
-                'We can\'t load the page because we\'re missing a valid page object that tells us what to load',
282
-                'event_espresso'
283
-            );
284
-            $msg[] = $msg[0] . "\r\n"
285
-                     . sprintf(
286
-                         esc_html__(
287
-                             'The custom slug you have set for this page is %s. This means we\'re looking for the class %s_Admin_Page (found in %s_Admin_Page.core.php) within your %s directory',
288
-                             'event_espresso'
289
-                         ),
290
-                         $this->_file_name,
291
-                         $this->_file_name,
292
-                         $this->_folder_path . $this->_file_name,
293
-                         $this->_menu_map->menuSlug()
294
-                     );
295
-            throw new EE_Error(implode('||', $msg));
296
-        }
297
-        $this->_loaded_page_object->set_wp_page_slug($wp_page_slug);
298
-        $page_hook = "load-$wp_page_slug";
299
-        // hook into page load hook so all page specific stuff gets loaded.
300
-        if (! empty($wp_page_slug)) {
301
-            add_action($page_hook, [$this->_loaded_page_object, 'load_page_dependencies']);
302
-        }
303
-    }
304
-
305
-
306
-    /**
307
-     * This executes the initial page loads for EE_Admin pages to take care of any ajax or other code needing to run
308
-     * before the load-page... hook. Note, the page loads are happening around the wp_init hook.
309
-     *
310
-     * @return void
311
-     * @throws InvalidArgumentException
312
-     * @throws InvalidDataTypeException
313
-     * @throws InvalidInterfaceException
314
-     * @throws EE_Error
315
-     * @throws ReflectionException
316
-     */
317
-    public function do_initial_loads()
318
-    {
319
-        // no loading or initializing if menu map is setup incorrectly.
320
-        if (! $this->_menu_map instanceof AdminMenuItem) {
321
-            return;
322
-        }
323
-        $this->_initialize_admin_page();
324
-    }
325
-
326
-
327
-    /**
328
-     * all we're doing here is setting the $_file_name property for later use.
329
-     *
330
-     * @return void
331
-     */
332
-    private function _set_file_and_folder_name()
333
-    {
334
-        $bt = debug_backtrace();
335
-        // for more reliable determination of folder name
336
-        // we're using this to get the actual folder name of the CALLING class (i.e. the child class that extends this).  Why?  Because $this->menu_slug may be different than the folder name (to avoid conflicts with other plugins)
337
-        $class = get_class($this);
338
-        foreach ($bt as $index => $values) {
339
-            if (isset($values['class']) && $values['class'] == $class) {
340
-                $file_index         = $index - 1;
341
-                $this->_folder_name = basename(dirname($bt[ $file_index ]['file']));
342
-                if (! empty($this->_folder_name)) {
343
-                    break;
344
-                }
345
-            }
346
-        }
347
-        $this->_folder_path = EE_ADMIN_PAGES . $this->_folder_name . '/';
348
-        $this->_file_name   = preg_replace('/^ee/', 'EE', $this->_folder_name);
349
-        $this->_file_name   = ucwords(str_replace('_', ' ', $this->_file_name));
350
-        $this->_file_name   = str_replace(' ', '_', $this->_file_name);
351
-    }
352
-
353
-
354
-    /**
355
-     * This automatically checks if we have a hook class in the loaded child directory.  If we DO then we will register
356
-     * it with the appropriate pages.  That way all we have to do is make sure the file is named correctly and
357
-     * "dropped" in. Example: if we wanted to set this up for Messages hooking into Events then we would do:
358
-     * events_Messages_Hooks.class.php
359
-     *
360
-     * @param bool $extend This indicates whether we're checking the extend directory for any register_hooks
361
-     *                     files/classes
362
-     * @return array
363
-     */
364
-    public function register_hooks(bool $extend = false): array
365
-    {
366
-        // get a list of files in the directory that have the "Hook" in their name an
367
-        // if this is an extended check (i.e. caf is active) then we will scan the caffeinated/extend directory first and any hook files that are found will be have their reference added to the $_files_hook array property.  Then, we make sure that when we loop through the core decaf directories to find hook files that we skip over any hooks files that have already been set by caf.
368
-        if ($extend) {
369
-            $hook_files_glob_path = apply_filters(
370
-                'FHEE__EE_Admin_Page_Init__register_hooks__hook_files_glob_path__extend',
371
-                EE_CORE_CAF_ADMIN_EXTEND
372
-                . $this->_folder_name
373
-                . '/*'
374
-                . $this->_file_name
375
-                . '_Hooks_Extend.class.php'
376
-            );
377
-            $this->_hook_paths    = $this->_register_hook_files($hook_files_glob_path, $extend);
378
-        }
379
-        // loop through decaf folders
380
-        $hook_files_glob_path = apply_filters(
381
-            'FHEE__EE_Admin_Page_Init__register_hooks__hook_files_glob_path',
382
-            $this->_folder_path . '*' . $this->_file_name . '_Hooks.class.php'
383
-        );
384
-        $this->_hook_paths    = array_merge(
385
-            $this->_register_hook_files($hook_files_glob_path),
386
-            $this->_hook_paths
387
-        );  // making sure any extended hook paths are later in the array than the core hook paths!
388
-        return $this->_hook_paths;
389
-    }
390
-
391
-
392
-    protected function _register_hook_files($hook_files_glob_path, $extend = false): array
393
-    {
394
-        $hook_paths = glob($hook_files_glob_path);
395
-        if (empty($hook_paths)) {
396
-            return [];
397
-        }
398
-        foreach ($hook_paths as $file) {
399
-            // lets get the linked admin.
400
-            $hook_file = $extend
401
-                ? str_replace(EE_CORE_CAF_ADMIN_EXTEND . $this->_folder_name . '/', '', $file)
402
-                : str_replace($this->_folder_path, '', $file);
403
-            $replace   = $extend
404
-                ? '_' . $this->_file_name . '_Hooks_Extend.class.php'
405
-                : '_' . $this->_file_name . '_Hooks.class.php';
406
-            $rel_admin = str_replace($replace, '', $hook_file);
407
-            $rel_admin = strtolower($rel_admin);
408
-            // make sure we haven't already got a hook setup for this page path
409
-            if (in_array($rel_admin, $this->_files_hooked)) {
410
-                continue;
411
-            }
412
-            require_once $file;
413
-            $this->hook_file = $hook_file;
414
-            $rel_admin_hook  = 'FHEE_do_other_page_hooks_' . $rel_admin;
415
-            add_filter($rel_admin_hook, [$this, 'load_admin_hook']);
416
-            $this->_files_hooked[] = $rel_admin;
417
-        }
418
-        return $hook_paths;
419
-    }
420
-
421
-
422
-    public function load_admin_hook($registered_pages)
423
-    {
424
-        return array_merge((array) $this->hook_file, $registered_pages);
425
-    }
426
-
427
-
428
-    /**
429
-     * _initialize_admin_page
430
-     *
431
-     * @throws EE_Error
432
-     * @throws ReflectionException
433
-     * @see  initialize_admin_page() for info
434
-     */
435
-    protected function _initialize_admin_page()
436
-    {
437
-        // JUST CHECK WE'RE ON RIGHT PAGE.
438
-        $page      = $this->request->getRequestParam('page');
439
-        $page      = $this->request->getRequestParam('current_page', $page);
440
-        $menu_slug = $this->_menu_map->menuSlug();
441
-
442
-
443
-        if ($this->_routing && ($page === '' || $page !== $menu_slug)) {
444
-            // not on the right page so let's get out.
445
-            return;
446
-        }
447
-        $this->_load_page = true;
448
-
449
-        // we don't need to do a page_request check here because it's only called via WP menu system.
450
-        $admin_page  = $this->_file_name . '_Admin_Page';
451
-        $hook_suffix = "{$menu_slug}_$admin_page";
452
-        $admin_page  = apply_filters(
453
-            "FHEE__EE_Admin_Page_Init___initialize_admin_page__admin_page__$hook_suffix",
454
-            $admin_page
455
-        );
456
-        if (empty($admin_page)) {
457
-            return;
458
-        }
459
-        // define requested admin page class name then load the file and instantiate
460
-        $path_to_file = str_replace(['\\', '/'], '/', $this->_folder_path . $admin_page . '.core.php');
461
-        // so if the file would be in EE_ADMIN/attendees/Attendee_Admin_Page.core.php, the filter would be:
462
-        // FHEE__EE_Admin_Page_Init___initialize_admin_page__path_to_file__attendees_Attendee_Admin_Page
463
-        $path_to_file = apply_filters(
464
-            "FHEE__EE_Admin_Page_Init___initialize_admin_page__path_to_file__$hook_suffix",
465
-            $path_to_file
466
-        );
467
-        if (! is_readable($path_to_file)) {
468
-            return;
469
-        }
470
-        // This is a place where EE plugins can hook in to make sure their own files are required in the appropriate place
471
-        do_action('AHEE__EE_Admin_Page___initialize_admin_page__before_initialization');
472
-        do_action("AHEE__EE_Admin_Page___initialize_admin_page__before_initialization_$menu_slug");
473
-        require_once($path_to_file);
474
-        $this->_loaded_page_object = $this->loader->getShared($admin_page, [$this->_routing]);
475
-        $this->_loaded_page_object->initializePage();
476
-
477
-        do_action('AHEE__EE_Admin_Page___initialize_admin_page__after_initialization');
478
-        do_action("AHEE__EE_Admin_Page___initialize_admin_page__after_initialization_$menu_slug");
479
-    }
480
-
481
-
482
-    public function get_admin_page_name(): string
483
-    {
484
-        return $this->_file_name . '_Admin_Page';
485
-    }
486
-
487
-
488
-    /**
489
-     * @return EE_Admin_Page|null
490
-     */
491
-    public function loaded_page_object(): ?EE_Admin_Page
492
-    {
493
-        return $this->_loaded_page_object;
494
-    }
495
-
496
-
497
-    /**
498
-     * _check_user_access
499
-     * verifies user access for this admin page.  If no user access is available then let's gracefully exit with a
500
-     * WordPress die message.
501
-     *
502
-     * @return void  wp_die if fail
503
-     */
504
-    private function _check_user_access()
505
-    {
506
-        if (! $this->_menu_map->currentUserHasAccess()) {
507
-            wp_die(
508
-                esc_html__('You don\'t have access to this page.', 'event_espresso'),
509
-                '',
510
-                ['back_link' => true]
511
-            );
512
-        }
513
-    }
33
+	/**
34
+	 * This holds the menu map object for this admin page.
35
+	 *
36
+	 * @var AdminMenuItem
37
+	 */
38
+	protected $_menu_map = null;
39
+
40
+	/**
41
+	 * deprecated
42
+	 */
43
+	public $menu_label;
44
+
45
+	public $menu_slug;
46
+
47
+
48
+	// set in _set_defaults
49
+	protected $_folder_name;
50
+
51
+	protected $_folder_path;
52
+
53
+	protected $_file_name;
54
+
55
+	public $hook_file;
56
+
57
+	protected $_wp_page_slug;
58
+
59
+	protected $_routing;
60
+
61
+
62
+	/**
63
+	 * This holds the page object.
64
+	 *
65
+	 * @var EE_Admin_Page
66
+	 */
67
+	protected $_loaded_page_object;
68
+
69
+
70
+	// for caf
71
+	protected $_files_hooked;
72
+
73
+	protected $_hook_paths;
74
+
75
+	// load_page?
76
+	private $_load_page;
77
+
78
+	/**
79
+	 * @var LoaderInterface
80
+	 */
81
+	protected $loader;
82
+
83
+	/**
84
+	 * @var RequestInterface
85
+	 */
86
+	protected $request;
87
+
88
+
89
+	/**
90
+	 * @throws InvalidArgumentException
91
+	 * @throws InvalidDataTypeException
92
+	 * @throws InvalidInterfaceException
93
+	 */
94
+	public function __construct(RequestInterface $request = null)
95
+	{
96
+		$this->loader  = LoaderFactory::getLoader();
97
+		$this->request = $request instanceof RequestInterface
98
+			? $request
99
+			: $this->loader->getShared(RequestInterface::class);
100
+		// set global defaults
101
+		$this->_set_defaults();
102
+		// set properties that are always available with objects.
103
+		$this->_set_init_properties();
104
+		// global styles/scripts across all wp admin pages
105
+		add_action('admin_enqueue_scripts', [$this, 'load_wp_global_scripts_styles'], 5);
106
+		// load initial stuff.
107
+		$this->_set_file_and_folder_name();
108
+	}
109
+
110
+
111
+	/**
112
+	 * _set_init_properties
113
+	 * Child classes use to set the following properties:
114
+	 * $label
115
+	 *
116
+	 * @abstract
117
+	 * @return void
118
+	 */
119
+	abstract protected function _set_init_properties();
120
+
121
+
122
+	/**
123
+	 * @return AdminMenuItem|null
124
+	 * @since       4.4.0
125
+	 * @deprecated  5.0.0.p
126
+	 */
127
+	public function get_menu_map()
128
+	{
129
+		return $this->adminMenu();
130
+	}
131
+
132
+
133
+	/**
134
+	 * _set_menu_map is a function that child classes use to set the menu_map property (which should be an instance of
135
+	 * EE_Admin_Page_Menu_Map.  Their menu can either be EE_Admin_Page_Main_Menu or AdminMenuSubItem.
136
+	 *
137
+	 * @since       4.4.0
138
+	 * @deprecated  5.0.0.p
139
+	 */
140
+	protected function _set_menu_map()
141
+	{
142
+		$this->_menu_map = null;
143
+	}
144
+
145
+
146
+	/**
147
+	 * @since   5.0.0.p
148
+	 */
149
+	public function setupLegacyAdminMenuItem()
150
+	{
151
+		// will be overridden by child classes not using new system
152
+		$this->_set_menu_map();
153
+	}
154
+
155
+
156
+	/**
157
+	 * Child classes should return an array of properties used to construct the AdminMenuItem
158
+	 *
159
+	 * @return array
160
+	 * @since 5.0.0.p
161
+	 */
162
+	public function getMenuProperties(): array
163
+	{
164
+		return [];
165
+	}
166
+
167
+
168
+	/**
169
+	 * @param AdminMenuItem $menu
170
+	 * @return void
171
+	 * @since 5.0.0.p
172
+	 */
173
+	public function setAdminMenu(AdminMenuItem $menu): void
174
+	{
175
+		$this->_menu_map = $menu;
176
+	}
177
+
178
+
179
+	/**
180
+	 * returns the menu map for this admin page
181
+	 *
182
+	 * @return AdminMenuItem|null
183
+	 * @since 5.0.0.p
184
+	 */
185
+	public function adminMenu(): ?AdminMenuItem
186
+	{
187
+		return $this->_menu_map;
188
+	}
189
+
190
+
191
+	/**
192
+	 * @param string $wp_page_slug
193
+	 * @since 5.0.0.p
194
+	 */
195
+	public function setWpPageSlug(string $wp_page_slug): void
196
+	{
197
+		$this->_wp_page_slug = $wp_page_slug;
198
+	}
199
+
200
+
201
+	/**
202
+	 * This loads scripts and styles for the EE_Admin system
203
+	 * that must be available on ALL WP admin pages (i.e. EE_menu items)
204
+	 *
205
+	 * @return void
206
+	 */
207
+	public function load_wp_global_scripts_styles()
208
+	{
209
+		wp_register_style(
210
+			'espresso_menu',
211
+			EE_ADMIN_URL . 'assets/admin-menu-styles.css',
212
+			['dashicons'],
213
+			EVENT_ESPRESSO_VERSION
214
+		);
215
+		wp_enqueue_style('espresso_menu');
216
+	}
217
+
218
+
219
+	/**
220
+	 * this sets default properties (might be overridden in _set_init_properties);
221
+	 *
222
+	 * @return  void
223
+	 */
224
+	private function _set_defaults()
225
+	{
226
+		$this->_file_name    = $this->_folder_name = $this->_wp_page_slug = $this->capability = null;
227
+		$this->_routing      = true;
228
+		$this->_load_page    = false;
229
+		$this->_files_hooked = $this->_hook_paths = [];
230
+	}
231
+
232
+
233
+	public function setCapability($capability, $menu_slug)
234
+	{
235
+		$this->capability = apply_filters('FHEE_' . $menu_slug . '_capability', $capability);
236
+	}
237
+
238
+
239
+	/**
240
+	 * @deprecated 5.0.0.p
241
+	 */
242
+	protected function _set_capability()
243
+	{
244
+		if ($this->_menu_map instanceof AdminMenuItem) {
245
+			$this->setCapability($this->_menu_map->capability(), $this->_menu_map->menuSlug());
246
+		}
247
+	}
248
+
249
+
250
+	/**
251
+	 * initialize_admin_page
252
+	 * This method is what executes the loading of the specific page class for the given dir_name as called by the
253
+	 * EE_Admin_Init class.
254
+	 *
255
+	 * @return void
256
+	 * @throws EE_Error
257
+	 * @throws ReflectionException
258
+	 */
259
+	public function initialize_admin_page()
260
+	{
261
+		// let's check user access first
262
+		$this->_check_user_access();
263
+		if (! $this->_loaded_page_object instanceof EE_Admin_Page) {
264
+			return;
265
+		}
266
+		$this->_loaded_page_object->route_admin_request();
267
+	}
268
+
269
+
270
+	/**
271
+	 * @param string $wp_page_slug
272
+	 * @throws EE_Error
273
+	 */
274
+	public function set_page_dependencies(string $wp_page_slug)
275
+	{
276
+		if (! $this->_load_page) {
277
+			return;
278
+		}
279
+		if (! $this->_loaded_page_object instanceof EE_Admin_Page) {
280
+			$msg[] = esc_html__(
281
+				'We can\'t load the page because we\'re missing a valid page object that tells us what to load',
282
+				'event_espresso'
283
+			);
284
+			$msg[] = $msg[0] . "\r\n"
285
+					 . sprintf(
286
+						 esc_html__(
287
+							 'The custom slug you have set for this page is %s. This means we\'re looking for the class %s_Admin_Page (found in %s_Admin_Page.core.php) within your %s directory',
288
+							 'event_espresso'
289
+						 ),
290
+						 $this->_file_name,
291
+						 $this->_file_name,
292
+						 $this->_folder_path . $this->_file_name,
293
+						 $this->_menu_map->menuSlug()
294
+					 );
295
+			throw new EE_Error(implode('||', $msg));
296
+		}
297
+		$this->_loaded_page_object->set_wp_page_slug($wp_page_slug);
298
+		$page_hook = "load-$wp_page_slug";
299
+		// hook into page load hook so all page specific stuff gets loaded.
300
+		if (! empty($wp_page_slug)) {
301
+			add_action($page_hook, [$this->_loaded_page_object, 'load_page_dependencies']);
302
+		}
303
+	}
304
+
305
+
306
+	/**
307
+	 * This executes the initial page loads for EE_Admin pages to take care of any ajax or other code needing to run
308
+	 * before the load-page... hook. Note, the page loads are happening around the wp_init hook.
309
+	 *
310
+	 * @return void
311
+	 * @throws InvalidArgumentException
312
+	 * @throws InvalidDataTypeException
313
+	 * @throws InvalidInterfaceException
314
+	 * @throws EE_Error
315
+	 * @throws ReflectionException
316
+	 */
317
+	public function do_initial_loads()
318
+	{
319
+		// no loading or initializing if menu map is setup incorrectly.
320
+		if (! $this->_menu_map instanceof AdminMenuItem) {
321
+			return;
322
+		}
323
+		$this->_initialize_admin_page();
324
+	}
325
+
326
+
327
+	/**
328
+	 * all we're doing here is setting the $_file_name property for later use.
329
+	 *
330
+	 * @return void
331
+	 */
332
+	private function _set_file_and_folder_name()
333
+	{
334
+		$bt = debug_backtrace();
335
+		// for more reliable determination of folder name
336
+		// we're using this to get the actual folder name of the CALLING class (i.e. the child class that extends this).  Why?  Because $this->menu_slug may be different than the folder name (to avoid conflicts with other plugins)
337
+		$class = get_class($this);
338
+		foreach ($bt as $index => $values) {
339
+			if (isset($values['class']) && $values['class'] == $class) {
340
+				$file_index         = $index - 1;
341
+				$this->_folder_name = basename(dirname($bt[ $file_index ]['file']));
342
+				if (! empty($this->_folder_name)) {
343
+					break;
344
+				}
345
+			}
346
+		}
347
+		$this->_folder_path = EE_ADMIN_PAGES . $this->_folder_name . '/';
348
+		$this->_file_name   = preg_replace('/^ee/', 'EE', $this->_folder_name);
349
+		$this->_file_name   = ucwords(str_replace('_', ' ', $this->_file_name));
350
+		$this->_file_name   = str_replace(' ', '_', $this->_file_name);
351
+	}
352
+
353
+
354
+	/**
355
+	 * This automatically checks if we have a hook class in the loaded child directory.  If we DO then we will register
356
+	 * it with the appropriate pages.  That way all we have to do is make sure the file is named correctly and
357
+	 * "dropped" in. Example: if we wanted to set this up for Messages hooking into Events then we would do:
358
+	 * events_Messages_Hooks.class.php
359
+	 *
360
+	 * @param bool $extend This indicates whether we're checking the extend directory for any register_hooks
361
+	 *                     files/classes
362
+	 * @return array
363
+	 */
364
+	public function register_hooks(bool $extend = false): array
365
+	{
366
+		// get a list of files in the directory that have the "Hook" in their name an
367
+		// if this is an extended check (i.e. caf is active) then we will scan the caffeinated/extend directory first and any hook files that are found will be have their reference added to the $_files_hook array property.  Then, we make sure that when we loop through the core decaf directories to find hook files that we skip over any hooks files that have already been set by caf.
368
+		if ($extend) {
369
+			$hook_files_glob_path = apply_filters(
370
+				'FHEE__EE_Admin_Page_Init__register_hooks__hook_files_glob_path__extend',
371
+				EE_CORE_CAF_ADMIN_EXTEND
372
+				. $this->_folder_name
373
+				. '/*'
374
+				. $this->_file_name
375
+				. '_Hooks_Extend.class.php'
376
+			);
377
+			$this->_hook_paths    = $this->_register_hook_files($hook_files_glob_path, $extend);
378
+		}
379
+		// loop through decaf folders
380
+		$hook_files_glob_path = apply_filters(
381
+			'FHEE__EE_Admin_Page_Init__register_hooks__hook_files_glob_path',
382
+			$this->_folder_path . '*' . $this->_file_name . '_Hooks.class.php'
383
+		);
384
+		$this->_hook_paths    = array_merge(
385
+			$this->_register_hook_files($hook_files_glob_path),
386
+			$this->_hook_paths
387
+		);  // making sure any extended hook paths are later in the array than the core hook paths!
388
+		return $this->_hook_paths;
389
+	}
390
+
391
+
392
+	protected function _register_hook_files($hook_files_glob_path, $extend = false): array
393
+	{
394
+		$hook_paths = glob($hook_files_glob_path);
395
+		if (empty($hook_paths)) {
396
+			return [];
397
+		}
398
+		foreach ($hook_paths as $file) {
399
+			// lets get the linked admin.
400
+			$hook_file = $extend
401
+				? str_replace(EE_CORE_CAF_ADMIN_EXTEND . $this->_folder_name . '/', '', $file)
402
+				: str_replace($this->_folder_path, '', $file);
403
+			$replace   = $extend
404
+				? '_' . $this->_file_name . '_Hooks_Extend.class.php'
405
+				: '_' . $this->_file_name . '_Hooks.class.php';
406
+			$rel_admin = str_replace($replace, '', $hook_file);
407
+			$rel_admin = strtolower($rel_admin);
408
+			// make sure we haven't already got a hook setup for this page path
409
+			if (in_array($rel_admin, $this->_files_hooked)) {
410
+				continue;
411
+			}
412
+			require_once $file;
413
+			$this->hook_file = $hook_file;
414
+			$rel_admin_hook  = 'FHEE_do_other_page_hooks_' . $rel_admin;
415
+			add_filter($rel_admin_hook, [$this, 'load_admin_hook']);
416
+			$this->_files_hooked[] = $rel_admin;
417
+		}
418
+		return $hook_paths;
419
+	}
420
+
421
+
422
+	public function load_admin_hook($registered_pages)
423
+	{
424
+		return array_merge((array) $this->hook_file, $registered_pages);
425
+	}
426
+
427
+
428
+	/**
429
+	 * _initialize_admin_page
430
+	 *
431
+	 * @throws EE_Error
432
+	 * @throws ReflectionException
433
+	 * @see  initialize_admin_page() for info
434
+	 */
435
+	protected function _initialize_admin_page()
436
+	{
437
+		// JUST CHECK WE'RE ON RIGHT PAGE.
438
+		$page      = $this->request->getRequestParam('page');
439
+		$page      = $this->request->getRequestParam('current_page', $page);
440
+		$menu_slug = $this->_menu_map->menuSlug();
441
+
442
+
443
+		if ($this->_routing && ($page === '' || $page !== $menu_slug)) {
444
+			// not on the right page so let's get out.
445
+			return;
446
+		}
447
+		$this->_load_page = true;
448
+
449
+		// we don't need to do a page_request check here because it's only called via WP menu system.
450
+		$admin_page  = $this->_file_name . '_Admin_Page';
451
+		$hook_suffix = "{$menu_slug}_$admin_page";
452
+		$admin_page  = apply_filters(
453
+			"FHEE__EE_Admin_Page_Init___initialize_admin_page__admin_page__$hook_suffix",
454
+			$admin_page
455
+		);
456
+		if (empty($admin_page)) {
457
+			return;
458
+		}
459
+		// define requested admin page class name then load the file and instantiate
460
+		$path_to_file = str_replace(['\\', '/'], '/', $this->_folder_path . $admin_page . '.core.php');
461
+		// so if the file would be in EE_ADMIN/attendees/Attendee_Admin_Page.core.php, the filter would be:
462
+		// FHEE__EE_Admin_Page_Init___initialize_admin_page__path_to_file__attendees_Attendee_Admin_Page
463
+		$path_to_file = apply_filters(
464
+			"FHEE__EE_Admin_Page_Init___initialize_admin_page__path_to_file__$hook_suffix",
465
+			$path_to_file
466
+		);
467
+		if (! is_readable($path_to_file)) {
468
+			return;
469
+		}
470
+		// This is a place where EE plugins can hook in to make sure their own files are required in the appropriate place
471
+		do_action('AHEE__EE_Admin_Page___initialize_admin_page__before_initialization');
472
+		do_action("AHEE__EE_Admin_Page___initialize_admin_page__before_initialization_$menu_slug");
473
+		require_once($path_to_file);
474
+		$this->_loaded_page_object = $this->loader->getShared($admin_page, [$this->_routing]);
475
+		$this->_loaded_page_object->initializePage();
476
+
477
+		do_action('AHEE__EE_Admin_Page___initialize_admin_page__after_initialization');
478
+		do_action("AHEE__EE_Admin_Page___initialize_admin_page__after_initialization_$menu_slug");
479
+	}
480
+
481
+
482
+	public function get_admin_page_name(): string
483
+	{
484
+		return $this->_file_name . '_Admin_Page';
485
+	}
486
+
487
+
488
+	/**
489
+	 * @return EE_Admin_Page|null
490
+	 */
491
+	public function loaded_page_object(): ?EE_Admin_Page
492
+	{
493
+		return $this->_loaded_page_object;
494
+	}
495
+
496
+
497
+	/**
498
+	 * _check_user_access
499
+	 * verifies user access for this admin page.  If no user access is available then let's gracefully exit with a
500
+	 * WordPress die message.
501
+	 *
502
+	 * @return void  wp_die if fail
503
+	 */
504
+	private function _check_user_access()
505
+	{
506
+		if (! $this->_menu_map->currentUserHasAccess()) {
507
+			wp_die(
508
+				esc_html__('You don\'t have access to this page.', 'event_espresso'),
509
+				'',
510
+				['back_link' => true]
511
+			);
512
+		}
513
+	}
514 514
 }
Please login to merge, or discard this patch.
core/admin/EE_Admin_Page_Main_Menu.core.php 1 patch
Indentation   +8 added lines, -8 removed lines patch added patch discarded remove patch
@@ -12,12 +12,12 @@
 block discarded – undo
12 12
  */
13 13
 class EE_Admin_Page_Main_Menu extends AdminMenuTopLevel
14 14
 {
15
-    /**
16
-     * @return string
17
-     * @deprecated 5.0.0.p
18
-     */
19
-    protected function _add_menu_page()
20
-    {
21
-        return $this->registerMenuItem();
22
-    }
15
+	/**
16
+	 * @return string
17
+	 * @deprecated 5.0.0.p
18
+	 */
19
+	protected function _add_menu_page()
20
+	{
21
+		return $this->registerMenuItem();
22
+	}
23 23
 }
Please login to merge, or discard this patch.
core/admin/EE_Admin_Page_Menu_Map.core.php 1 patch
Indentation   +45 added lines, -45 removed lines patch added patch discarded remove patch
@@ -12,49 +12,49 @@
 block discarded – undo
12 12
  */
13 13
 abstract class EE_Admin_Page_Menu_Map extends AdminMenuItem
14 14
 {
15
-    const NONE                   = 0;
16
-
17
-    const BLOG_ADMIN_ONLY        = 1;
18
-
19
-    const BLOG_AND_NETWORK_ADMIN = 2;
20
-
21
-    const NETWORK_ADMIN_ONLY     = 3;
22
-
23
-
24
-    /**
25
-     * @return string
26
-     * @deprecated 5.0.0.p
27
-     */
28
-    protected function _add_menu_page(): string
29
-    {
30
-        return $this->registerMenuItem();
31
-    }
32
-
33
-
34
-    /**
35
-     * @param boolean $network_admin whether this is being added to the network admin page or not
36
-     * @deprecated 5.0.0.p
37
-     * @since  4.4.0
38
-     */
39
-    public function add_menu_page(bool $network_admin = false)
40
-    {
41
-        $this->registerAdminMenuItem($network_admin);
42
-    }
43
-
44
-
45
-    public function __get(string $property)
46
-    {
47
-        // converts a property name like 'menu_slug' into 'menuSlug'
48
-        $getter = lcfirst(ucwords($property, '_'));
49
-        return method_exists($this, $getter) ? $this->{$getter}() : null;
50
-    }
51
-
52
-    public function __set(string $property, $value)
53
-    {
54
-        // converts a property name like 'menu_slug' into 'setMenuSlug'
55
-        $setter = 'set' . ucwords($property, '_');
56
-        if (method_exists($this, $setter)) {
57
-            $this->{$setter}($value);
58
-        }
59
-    }
15
+	const NONE                   = 0;
16
+
17
+	const BLOG_ADMIN_ONLY        = 1;
18
+
19
+	const BLOG_AND_NETWORK_ADMIN = 2;
20
+
21
+	const NETWORK_ADMIN_ONLY     = 3;
22
+
23
+
24
+	/**
25
+	 * @return string
26
+	 * @deprecated 5.0.0.p
27
+	 */
28
+	protected function _add_menu_page(): string
29
+	{
30
+		return $this->registerMenuItem();
31
+	}
32
+
33
+
34
+	/**
35
+	 * @param boolean $network_admin whether this is being added to the network admin page or not
36
+	 * @deprecated 5.0.0.p
37
+	 * @since  4.4.0
38
+	 */
39
+	public function add_menu_page(bool $network_admin = false)
40
+	{
41
+		$this->registerAdminMenuItem($network_admin);
42
+	}
43
+
44
+
45
+	public function __get(string $property)
46
+	{
47
+		// converts a property name like 'menu_slug' into 'menuSlug'
48
+		$getter = lcfirst(ucwords($property, '_'));
49
+		return method_exists($this, $getter) ? $this->{$getter}() : null;
50
+	}
51
+
52
+	public function __set(string $property, $value)
53
+	{
54
+		// converts a property name like 'menu_slug' into 'setMenuSlug'
55
+		$setter = 'set' . ucwords($property, '_');
56
+		if (method_exists($this, $setter)) {
57
+			$this->{$setter}($value);
58
+		}
59
+	}
60 60
 }
Please login to merge, or discard this patch.
core/admin/EE_Admin_Page_Sub_Menu.core.php 1 patch
Indentation   +8 added lines, -8 removed lines patch added patch discarded remove patch
@@ -12,12 +12,12 @@
 block discarded – undo
12 12
  */
13 13
 class EE_Admin_Page_Sub_Menu extends AdminMenuSubItem
14 14
 {
15
-    /**
16
-     * @return string
17
-     * @deprecated 5.0.0.p
18
-     */
19
-    protected function _add_menu_page()
20
-    {
21
-        return $this->registerMenuItem();
22
-    }
15
+	/**
16
+	 * @return string
17
+	 * @deprecated 5.0.0.p
18
+	 */
19
+	protected function _add_menu_page()
20
+	{
21
+		return $this->registerMenuItem();
22
+	}
23 23
 }
Please login to merge, or discard this patch.
core/admin/EE_Admin_Page_Menu_Group.core.php 1 patch
Indentation   +16 added lines, -16 removed lines patch added patch discarded remove patch
@@ -10,22 +10,22 @@
 block discarded – undo
10 10
  */
11 11
 class EE_Admin_Page_Menu_Group extends AdminMenuGroup
12 12
 {
13
-    /**
14
-     * @return string
15
-     * @deprecated 5.0.0.p
16
-     */
17
-    protected function _add_menu_page(): string
18
-    {
19
-        return $this->registerMenuItem();
20
-    }
13
+	/**
14
+	 * @return string
15
+	 * @deprecated 5.0.0.p
16
+	 */
17
+	protected function _add_menu_page(): string
18
+	{
19
+		return $this->registerMenuItem();
20
+	}
21 21
 
22 22
 
23
-    /**
24
-     * @return string
25
-     * @deprecated 5.0.0.p
26
-     */
27
-    private function _group_link(): string
28
-    {
29
-        return $this->groupLink();
30
-    }
23
+	/**
24
+	 * @return string
25
+	 * @deprecated 5.0.0.p
26
+	 */
27
+	private function _group_link(): string
28
+	{
29
+		return $this->groupLink();
30
+	}
31 31
 }
Please login to merge, or discard this patch.