@@ -4,33 +4,33 @@ |
||
4 | 4 | |
5 | 5 | class TimeFormat extends BaseFormat |
6 | 6 | { |
7 | - protected const DEFAULT_FORMAT = 'H:i:s'; |
|
8 | - protected const WORDPRESS_FORMAT_OPTION_NAME = 'time_format'; |
|
7 | + protected const DEFAULT_FORMAT = 'H:i:s'; |
|
8 | + protected const WORDPRESS_FORMAT_OPTION_NAME = 'time_format'; |
|
9 | 9 | |
10 | - protected static array $allowed_chars = [ |
|
11 | - 'a', |
|
12 | - 'A', |
|
13 | - 'B', |
|
14 | - 'g', |
|
15 | - 'G', |
|
16 | - 'h', |
|
17 | - 'H', |
|
18 | - 'i', |
|
19 | - 's', |
|
20 | - 'u', |
|
21 | - 'v', |
|
22 | - 'e', |
|
23 | - 'I', |
|
24 | - 'O', |
|
25 | - 'P', |
|
26 | - 'T', |
|
27 | - 'Z', |
|
28 | - ':', |
|
29 | - '-', |
|
30 | - ',', |
|
31 | - '.', |
|
32 | - ' ', |
|
33 | - ]; |
|
10 | + protected static array $allowed_chars = [ |
|
11 | + 'a', |
|
12 | + 'A', |
|
13 | + 'B', |
|
14 | + 'g', |
|
15 | + 'G', |
|
16 | + 'h', |
|
17 | + 'H', |
|
18 | + 'i', |
|
19 | + 's', |
|
20 | + 'u', |
|
21 | + 'v', |
|
22 | + 'e', |
|
23 | + 'I', |
|
24 | + 'O', |
|
25 | + 'P', |
|
26 | + 'T', |
|
27 | + 'Z', |
|
28 | + ':', |
|
29 | + '-', |
|
30 | + ',', |
|
31 | + '.', |
|
32 | + ' ', |
|
33 | + ]; |
|
34 | 34 | |
35 | - protected static ?string $wordpress_format = null; |
|
35 | + protected static ?string $wordpress_format = null; |
|
36 | 36 | } |
@@ -7,7 +7,7 @@ |
||
7 | 7 | protected const DEFAULT_FORMAT = 'H:i:s'; |
8 | 8 | protected const WORDPRESS_FORMAT_OPTION_NAME = 'time_format'; |
9 | 9 | |
10 | - protected static array $allowed_chars = [ |
|
10 | + protected static array $allowed_chars = [ |
|
11 | 11 | 'a', |
12 | 12 | 'A', |
13 | 13 | 'B', |
@@ -17,46 +17,46 @@ |
||
17 | 17 | */ |
18 | 18 | class EspressoBatchJob extends AdminRoute |
19 | 19 | { |
20 | - /** |
|
21 | - * returns true if the current request matches this route |
|
22 | - * |
|
23 | - * @return bool |
|
24 | - * @since 5.0.0.p |
|
25 | - */ |
|
26 | - public function matchesCurrentRequest(): bool |
|
27 | - { |
|
28 | - global $pagenow; |
|
29 | - $page = $this->request->getRequestParam('page'); |
|
30 | - return ($pagenow === 'admin.php' || $pagenow === 'admin-ajax.php') |
|
31 | - && $page === 'espresso_batch' |
|
32 | - && parent::matchesCurrentRequest(); |
|
33 | - } |
|
20 | + /** |
|
21 | + * returns true if the current request matches this route |
|
22 | + * |
|
23 | + * @return bool |
|
24 | + * @since 5.0.0.p |
|
25 | + */ |
|
26 | + public function matchesCurrentRequest(): bool |
|
27 | + { |
|
28 | + global $pagenow; |
|
29 | + $page = $this->request->getRequestParam('page'); |
|
30 | + return ($pagenow === 'admin.php' || $pagenow === 'admin-ajax.php') |
|
31 | + && $page === 'espresso_batch' |
|
32 | + && parent::matchesCurrentRequest(); |
|
33 | + } |
|
34 | 34 | |
35 | 35 | |
36 | - /** |
|
37 | - * @since 5.0.0.p |
|
38 | - */ |
|
39 | - protected function registerDependencies() |
|
40 | - { |
|
41 | - $this->dependency_map->registerDependencies( |
|
42 | - 'EventEspresso\core\domain\services\admin\registrations\list_table\QueryBuilder', |
|
43 | - [ |
|
44 | - 'EventEspresso\core\services\request\Request' => EE_Dependency_Map::load_from_cache, |
|
45 | - 'EEM_Registration' => EE_Dependency_Map::load_from_cache, |
|
46 | - null, |
|
47 | - ] |
|
48 | - ); |
|
49 | - } |
|
36 | + /** |
|
37 | + * @since 5.0.0.p |
|
38 | + */ |
|
39 | + protected function registerDependencies() |
|
40 | + { |
|
41 | + $this->dependency_map->registerDependencies( |
|
42 | + 'EventEspresso\core\domain\services\admin\registrations\list_table\QueryBuilder', |
|
43 | + [ |
|
44 | + 'EventEspresso\core\services\request\Request' => EE_Dependency_Map::load_from_cache, |
|
45 | + 'EEM_Registration' => EE_Dependency_Map::load_from_cache, |
|
46 | + null, |
|
47 | + ] |
|
48 | + ); |
|
49 | + } |
|
50 | 50 | |
51 | 51 | |
52 | - /** |
|
53 | - * implements logic required to run during request |
|
54 | - * |
|
55 | - * @return bool |
|
56 | - * @since 5.0.0.p |
|
57 | - */ |
|
58 | - protected function requestHandler(): bool |
|
59 | - { |
|
60 | - return true; |
|
61 | - } |
|
52 | + /** |
|
53 | + * implements logic required to run during request |
|
54 | + * |
|
55 | + * @return bool |
|
56 | + * @since 5.0.0.p |
|
57 | + */ |
|
58 | + protected function requestHandler(): bool |
|
59 | + { |
|
60 | + return true; |
|
61 | + } |
|
62 | 62 | } |
@@ -13,75 +13,75 @@ |
||
13 | 13 | */ |
14 | 14 | class CurrentUser |
15 | 15 | { |
16 | - private EventManagers $event_managers; |
|
17 | - |
|
18 | - private ?WP_User $current_user = null; |
|
19 | - |
|
20 | - private bool $is_event_manager = false; |
|
21 | - |
|
22 | - private bool $is_logged_in = false; |
|
23 | - |
|
24 | - private bool $is_super_admin = false; |
|
25 | - |
|
26 | - |
|
27 | - /** |
|
28 | - * CurrentUser constructor. |
|
29 | - * |
|
30 | - * @param EventManagers $event_managers |
|
31 | - */ |
|
32 | - public function __construct(EventManagers $event_managers) |
|
33 | - { |
|
34 | - $this->event_managers = $event_managers; |
|
35 | - $this->setCurrentUser(); |
|
36 | - } |
|
37 | - |
|
38 | - |
|
39 | - public function setCurrentUser(): void |
|
40 | - { |
|
41 | - if (! $this->current_user instanceof WP_User) { |
|
42 | - $this->current_user = wp_get_current_user(); |
|
43 | - $event_manager_roles = array_keys($this->event_managers->roles()); |
|
44 | - $current_user_roles = $this->current_user->roles; |
|
45 | - $this->is_event_manager = ! empty(array_intersect($event_manager_roles, $current_user_roles)); |
|
46 | - $this->is_super_admin = is_super_admin($this->current_user->ID); |
|
47 | - $this->is_logged_in = $this->current_user->exists(); |
|
48 | - } |
|
49 | - } |
|
50 | - |
|
51 | - |
|
52 | - /** |
|
53 | - * @return WP_User |
|
54 | - */ |
|
55 | - public function currentUser(): ?WP_User |
|
56 | - { |
|
57 | - return $this->current_user; |
|
58 | - } |
|
59 | - |
|
60 | - |
|
61 | - /** |
|
62 | - * @return bool |
|
63 | - */ |
|
64 | - public function isEventManager(): bool |
|
65 | - { |
|
66 | - return $this->is_event_manager; |
|
67 | - } |
|
68 | - |
|
69 | - |
|
70 | - /** |
|
71 | - * @return bool |
|
72 | - */ |
|
73 | - public function isLoggedIn(): bool |
|
74 | - { |
|
75 | - return $this->is_logged_in; |
|
76 | - } |
|
77 | - |
|
78 | - |
|
79 | - /** |
|
80 | - * @return bool |
|
81 | - * @since 5.0.8.p |
|
82 | - */ |
|
83 | - public function isSuperAdmin(): bool |
|
84 | - { |
|
85 | - return $this->is_super_admin; |
|
86 | - } |
|
16 | + private EventManagers $event_managers; |
|
17 | + |
|
18 | + private ?WP_User $current_user = null; |
|
19 | + |
|
20 | + private bool $is_event_manager = false; |
|
21 | + |
|
22 | + private bool $is_logged_in = false; |
|
23 | + |
|
24 | + private bool $is_super_admin = false; |
|
25 | + |
|
26 | + |
|
27 | + /** |
|
28 | + * CurrentUser constructor. |
|
29 | + * |
|
30 | + * @param EventManagers $event_managers |
|
31 | + */ |
|
32 | + public function __construct(EventManagers $event_managers) |
|
33 | + { |
|
34 | + $this->event_managers = $event_managers; |
|
35 | + $this->setCurrentUser(); |
|
36 | + } |
|
37 | + |
|
38 | + |
|
39 | + public function setCurrentUser(): void |
|
40 | + { |
|
41 | + if (! $this->current_user instanceof WP_User) { |
|
42 | + $this->current_user = wp_get_current_user(); |
|
43 | + $event_manager_roles = array_keys($this->event_managers->roles()); |
|
44 | + $current_user_roles = $this->current_user->roles; |
|
45 | + $this->is_event_manager = ! empty(array_intersect($event_manager_roles, $current_user_roles)); |
|
46 | + $this->is_super_admin = is_super_admin($this->current_user->ID); |
|
47 | + $this->is_logged_in = $this->current_user->exists(); |
|
48 | + } |
|
49 | + } |
|
50 | + |
|
51 | + |
|
52 | + /** |
|
53 | + * @return WP_User |
|
54 | + */ |
|
55 | + public function currentUser(): ?WP_User |
|
56 | + { |
|
57 | + return $this->current_user; |
|
58 | + } |
|
59 | + |
|
60 | + |
|
61 | + /** |
|
62 | + * @return bool |
|
63 | + */ |
|
64 | + public function isEventManager(): bool |
|
65 | + { |
|
66 | + return $this->is_event_manager; |
|
67 | + } |
|
68 | + |
|
69 | + |
|
70 | + /** |
|
71 | + * @return bool |
|
72 | + */ |
|
73 | + public function isLoggedIn(): bool |
|
74 | + { |
|
75 | + return $this->is_logged_in; |
|
76 | + } |
|
77 | + |
|
78 | + |
|
79 | + /** |
|
80 | + * @return bool |
|
81 | + * @since 5.0.8.p |
|
82 | + */ |
|
83 | + public function isSuperAdmin(): bool |
|
84 | + { |
|
85 | + return $this->is_super_admin; |
|
86 | + } |
|
87 | 87 | } |
@@ -15,7 +15,7 @@ discard block |
||
15 | 15 | { |
16 | 16 | private EventManagers $event_managers; |
17 | 17 | |
18 | - private ?WP_User $current_user = null; |
|
18 | + private ?WP_User $current_user = null; |
|
19 | 19 | |
20 | 20 | private bool $is_event_manager = false; |
21 | 21 | |
@@ -38,7 +38,7 @@ discard block |
||
38 | 38 | |
39 | 39 | public function setCurrentUser(): void |
40 | 40 | { |
41 | - if (! $this->current_user instanceof WP_User) { |
|
41 | + if ( ! $this->current_user instanceof WP_User) { |
|
42 | 42 | $this->current_user = wp_get_current_user(); |
43 | 43 | $event_manager_roles = array_keys($this->event_managers->roles()); |
44 | 44 | $current_user_roles = $this->current_user->roles; |
@@ -5,277 +5,277 @@ |
||
5 | 5 | */ |
6 | 6 | class EE_Core_Config extends EE_Config_Base |
7 | 7 | { |
8 | - const OPTION_NAME_UXIP = 'ee_ueip_optin'; |
|
9 | - |
|
10 | - |
|
11 | - public int $current_blog_id = 1; |
|
12 | - |
|
13 | - public $ee_ueip_optin; |
|
14 | - |
|
15 | - public $ee_ueip_has_notified; |
|
16 | - |
|
17 | - /** |
|
18 | - * Not to be confused with the 4 critical page variables (See |
|
19 | - * get_critical_pages_array()), this is just an array of wp posts that have EE |
|
20 | - * shortcodes in them. Keys are slugs, values are arrays with only 1 element: where the key is the shortcode |
|
21 | - * in the page, and the value is the page's ID. The key 'posts' is basically a duplicate of this same array. |
|
22 | - * |
|
23 | - * @var array |
|
24 | - */ |
|
25 | - public array $post_shortcodes = []; |
|
26 | - |
|
27 | - public array $module_route_map = []; |
|
28 | - |
|
29 | - public array $module_forward_map = []; |
|
30 | - |
|
31 | - public array $module_view_map = []; |
|
32 | - |
|
33 | - /** |
|
34 | - * The next 4 vars are the IDs of critical EE pages. |
|
35 | - * |
|
36 | - * @var int |
|
37 | - */ |
|
38 | - public int $reg_page_id = 0; |
|
39 | - |
|
40 | - public int $txn_page_id = 0; |
|
41 | - |
|
42 | - public int $thank_you_page_id = 0; |
|
43 | - |
|
44 | - public int $cancel_page_id = 0; |
|
45 | - |
|
46 | - /** |
|
47 | - * The next 4 vars are the URLs of critical EE pages. |
|
48 | - * |
|
49 | - * @var string |
|
50 | - */ |
|
51 | - public string $reg_page_url = ''; |
|
52 | - |
|
53 | - public string $txn_page_url = ''; |
|
54 | - |
|
55 | - public string $thank_you_page_url = ''; |
|
56 | - |
|
57 | - public string $cancel_page_url = ''; |
|
58 | - |
|
59 | - /** |
|
60 | - * The next vars relate to the custom slugs for EE CPT routes |
|
61 | - */ |
|
62 | - public string $event_cpt_slug; |
|
63 | - |
|
64 | - /** |
|
65 | - * This caches the _ee_ueip_option in case this config is reset in the same |
|
66 | - * request across blog switches in a multisite context. |
|
67 | - * Avoids extra queries to the db for this option. |
|
68 | - * |
|
69 | - * @var bool|null |
|
70 | - */ |
|
71 | - public static $ee_ueip_option = null; |
|
72 | - |
|
73 | - |
|
74 | - public function __construct() |
|
75 | - { |
|
76 | - // set default organization settings |
|
77 | - $this->current_blog_id = get_current_blog_id() ?: 1; |
|
78 | - $this->ee_ueip_optin = $this->_get_main_ee_ueip_optin(); |
|
79 | - $this->ee_ueip_has_notified = is_main_site() ? get_option('ee_ueip_has_notified', false) : true; |
|
80 | - // cpt slugs |
|
81 | - $this->event_cpt_slug = esc_html__('events', 'event_espresso'); |
|
82 | - // ueip constant check |
|
83 | - if (defined('EE_DISABLE_UXIP') && EE_DISABLE_UXIP) { |
|
84 | - $this->ee_ueip_optin = false; |
|
85 | - $this->ee_ueip_has_notified = true; |
|
86 | - } |
|
87 | - } |
|
88 | - |
|
89 | - |
|
90 | - /** |
|
91 | - * @return array |
|
92 | - */ |
|
93 | - public function get_critical_pages_array(): array |
|
94 | - { |
|
95 | - return [ |
|
96 | - $this->reg_page_id, |
|
97 | - $this->txn_page_id, |
|
98 | - $this->thank_you_page_id, |
|
99 | - $this->cancel_page_id, |
|
100 | - ]; |
|
101 | - } |
|
102 | - |
|
103 | - |
|
104 | - /** |
|
105 | - * @return array |
|
106 | - */ |
|
107 | - public function get_critical_pages_shortcodes_array(): array |
|
108 | - { |
|
109 | - return [ |
|
110 | - $this->reg_page_id => 'ESPRESSO_CHECKOUT', |
|
111 | - $this->txn_page_id => 'ESPRESSO_TXN_PAGE', |
|
112 | - $this->thank_you_page_id => 'ESPRESSO_THANK_YOU', |
|
113 | - $this->cancel_page_id => 'ESPRESSO_CANCELLED', |
|
114 | - ]; |
|
115 | - } |
|
116 | - |
|
117 | - |
|
118 | - /** |
|
119 | - * gets/returns URL for EE reg_page |
|
120 | - * |
|
121 | - * @return string |
|
122 | - */ |
|
123 | - public function reg_page_url(): string |
|
124 | - { |
|
125 | - if (! $this->reg_page_url) { |
|
126 | - $this->reg_page_url = add_query_arg( |
|
127 | - ['uts' => time()], |
|
128 | - get_permalink($this->reg_page_id) |
|
129 | - ) . '#checkout'; |
|
130 | - } |
|
131 | - return $this->reg_page_url; |
|
132 | - } |
|
133 | - |
|
134 | - |
|
135 | - /** |
|
136 | - * gets/returns URL for EE txn_page |
|
137 | - * |
|
138 | - * @param array $query_args like what gets passed to add_query_arg() as the first argument |
|
139 | - * @return string |
|
140 | - */ |
|
141 | - public function txn_page_url(array $query_args = []): string |
|
142 | - { |
|
143 | - if (! $this->txn_page_url) { |
|
144 | - $this->txn_page_url = get_permalink($this->txn_page_id); |
|
145 | - } |
|
146 | - if ($query_args) { |
|
147 | - return add_query_arg($query_args, $this->txn_page_url); |
|
148 | - } |
|
149 | - return $this->txn_page_url; |
|
150 | - } |
|
151 | - |
|
152 | - |
|
153 | - /** |
|
154 | - * gets/returns URL for EE thank_you_page |
|
155 | - * |
|
156 | - * @param array $query_args like what gets passed to |
|
157 | - * add_query_arg() as the first argument |
|
158 | - * @return string |
|
159 | - */ |
|
160 | - public function thank_you_page_url(array $query_args = []): string |
|
161 | - { |
|
162 | - if (! $this->thank_you_page_url) { |
|
163 | - $this->thank_you_page_url = get_permalink($this->thank_you_page_id); |
|
164 | - } |
|
165 | - if ($query_args) { |
|
166 | - return add_query_arg($query_args, $this->thank_you_page_url); |
|
167 | - } |
|
168 | - return $this->thank_you_page_url; |
|
169 | - } |
|
170 | - |
|
171 | - |
|
172 | - /** |
|
173 | - * gets/returns URL for EE cancel_page |
|
174 | - * |
|
175 | - * @return string |
|
176 | - */ |
|
177 | - public function cancel_page_url(): string |
|
178 | - { |
|
179 | - if (! $this->cancel_page_url) { |
|
180 | - $this->cancel_page_url = get_permalink($this->cancel_page_id); |
|
181 | - } |
|
182 | - return $this->cancel_page_url; |
|
183 | - } |
|
184 | - |
|
185 | - |
|
186 | - /** |
|
187 | - * Resets all critical page urls to their original state. Used primarily by the __sleep() magic method currently. |
|
188 | - * |
|
189 | - * @since 4.7.5 |
|
190 | - */ |
|
191 | - protected function _reset_urls() |
|
192 | - { |
|
193 | - $this->reg_page_url = ''; |
|
194 | - $this->txn_page_url = ''; |
|
195 | - $this->cancel_page_url = ''; |
|
196 | - $this->thank_you_page_url = ''; |
|
197 | - } |
|
198 | - |
|
199 | - |
|
200 | - /** |
|
201 | - * Used to return what the optin value is set for the EE User Experience Program. |
|
202 | - * This accounts for multisite and this value being requested for a subsite. In multisite, the value is set |
|
203 | - * on the main site only. |
|
204 | - * |
|
205 | - * @return bool |
|
206 | - */ |
|
207 | - protected function _get_main_ee_ueip_optin() |
|
208 | - { |
|
209 | - // if this is the main site then we can just bypass our direct query. |
|
210 | - if (is_main_site()) { |
|
211 | - return get_option(self::OPTION_NAME_UXIP, false); |
|
212 | - } |
|
213 | - // is this already cached for this request? If so use it. |
|
214 | - if (EE_Core_Config::$ee_ueip_option !== null) { |
|
215 | - return EE_Core_Config::$ee_ueip_option; |
|
216 | - } |
|
217 | - global $wpdb; |
|
218 | - $current_network_main_site = is_multisite() ? get_current_site() : null; |
|
219 | - $current_main_site_id = $current_network_main_site instanceof WP_Network |
|
220 | - ? $current_network_main_site->blog_id |
|
221 | - : 1; |
|
222 | - $option = self::OPTION_NAME_UXIP; |
|
223 | - // set correct table for query |
|
224 | - $table_name = $wpdb->get_blog_prefix($current_main_site_id) . 'options'; |
|
225 | - // rather than getting blog option for the $current_main_site_id, we do a direct $wpdb query because |
|
226 | - // get_blog_option() does a switch_to_blog and that could cause infinite recursion because EE_Core_Config might be |
|
227 | - // re-constructed on the blog switch. Note, we are still executing any core wp filters on this option retrieval. |
|
228 | - // this bit of code is basically a direct copy of get_option without any caching because we are NOT switched to the blog |
|
229 | - // for the purpose of caching. |
|
230 | - $pre = apply_filters('pre_option_' . $option, false, $option); |
|
231 | - if ($pre !== false) { |
|
232 | - EE_Core_Config::$ee_ueip_option = $pre; |
|
233 | - return EE_Core_Config::$ee_ueip_option; |
|
234 | - } |
|
235 | - $row = $wpdb->get_row( |
|
236 | - $wpdb->prepare( |
|
237 | - "SELECT option_value FROM $table_name WHERE option_name = %s LIMIT 1", |
|
238 | - $option |
|
239 | - ) |
|
240 | - ); |
|
241 | - if (is_object($row)) { |
|
242 | - $value = $row->option_value; |
|
243 | - } else { // option does not exist so use default. |
|
244 | - EE_Core_Config::$ee_ueip_option = apply_filters('default_option_' . $option, false, $option); |
|
245 | - return EE_Core_Config::$ee_ueip_option; |
|
246 | - } |
|
247 | - EE_Core_Config::$ee_ueip_option = apply_filters('option_' . $option, maybe_unserialize($value), $option); |
|
248 | - return EE_Core_Config::$ee_ueip_option; |
|
249 | - } |
|
250 | - |
|
251 | - |
|
252 | - /** |
|
253 | - * Utility function for escaping the value of a property and returning. |
|
254 | - * |
|
255 | - * @param string $property property name (checks to see if exists). |
|
256 | - * @return mixed if a detected type found return the escaped value, otherwise just the raw value is returned. |
|
257 | - * @throws EE_Error |
|
258 | - */ |
|
259 | - public function get_pretty(string $property) |
|
260 | - { |
|
261 | - if ($property === self::OPTION_NAME_UXIP) { |
|
262 | - return $this->ee_ueip_optin ? 'yes' : 'no'; |
|
263 | - } |
|
264 | - return parent::get_pretty($property); |
|
265 | - } |
|
266 | - |
|
267 | - |
|
268 | - /** |
|
269 | - * Currently used to ensure critical page urls have initial values saved to the db instead of any current set values |
|
270 | - * on the object. |
|
271 | - * |
|
272 | - * @return array |
|
273 | - */ |
|
274 | - public function __sleep() |
|
275 | - { |
|
276 | - // reset all url properties |
|
277 | - $this->_reset_urls(); |
|
278 | - // return what to save to db |
|
279 | - return array_keys(get_object_vars($this)); |
|
280 | - } |
|
8 | + const OPTION_NAME_UXIP = 'ee_ueip_optin'; |
|
9 | + |
|
10 | + |
|
11 | + public int $current_blog_id = 1; |
|
12 | + |
|
13 | + public $ee_ueip_optin; |
|
14 | + |
|
15 | + public $ee_ueip_has_notified; |
|
16 | + |
|
17 | + /** |
|
18 | + * Not to be confused with the 4 critical page variables (See |
|
19 | + * get_critical_pages_array()), this is just an array of wp posts that have EE |
|
20 | + * shortcodes in them. Keys are slugs, values are arrays with only 1 element: where the key is the shortcode |
|
21 | + * in the page, and the value is the page's ID. The key 'posts' is basically a duplicate of this same array. |
|
22 | + * |
|
23 | + * @var array |
|
24 | + */ |
|
25 | + public array $post_shortcodes = []; |
|
26 | + |
|
27 | + public array $module_route_map = []; |
|
28 | + |
|
29 | + public array $module_forward_map = []; |
|
30 | + |
|
31 | + public array $module_view_map = []; |
|
32 | + |
|
33 | + /** |
|
34 | + * The next 4 vars are the IDs of critical EE pages. |
|
35 | + * |
|
36 | + * @var int |
|
37 | + */ |
|
38 | + public int $reg_page_id = 0; |
|
39 | + |
|
40 | + public int $txn_page_id = 0; |
|
41 | + |
|
42 | + public int $thank_you_page_id = 0; |
|
43 | + |
|
44 | + public int $cancel_page_id = 0; |
|
45 | + |
|
46 | + /** |
|
47 | + * The next 4 vars are the URLs of critical EE pages. |
|
48 | + * |
|
49 | + * @var string |
|
50 | + */ |
|
51 | + public string $reg_page_url = ''; |
|
52 | + |
|
53 | + public string $txn_page_url = ''; |
|
54 | + |
|
55 | + public string $thank_you_page_url = ''; |
|
56 | + |
|
57 | + public string $cancel_page_url = ''; |
|
58 | + |
|
59 | + /** |
|
60 | + * The next vars relate to the custom slugs for EE CPT routes |
|
61 | + */ |
|
62 | + public string $event_cpt_slug; |
|
63 | + |
|
64 | + /** |
|
65 | + * This caches the _ee_ueip_option in case this config is reset in the same |
|
66 | + * request across blog switches in a multisite context. |
|
67 | + * Avoids extra queries to the db for this option. |
|
68 | + * |
|
69 | + * @var bool|null |
|
70 | + */ |
|
71 | + public static $ee_ueip_option = null; |
|
72 | + |
|
73 | + |
|
74 | + public function __construct() |
|
75 | + { |
|
76 | + // set default organization settings |
|
77 | + $this->current_blog_id = get_current_blog_id() ?: 1; |
|
78 | + $this->ee_ueip_optin = $this->_get_main_ee_ueip_optin(); |
|
79 | + $this->ee_ueip_has_notified = is_main_site() ? get_option('ee_ueip_has_notified', false) : true; |
|
80 | + // cpt slugs |
|
81 | + $this->event_cpt_slug = esc_html__('events', 'event_espresso'); |
|
82 | + // ueip constant check |
|
83 | + if (defined('EE_DISABLE_UXIP') && EE_DISABLE_UXIP) { |
|
84 | + $this->ee_ueip_optin = false; |
|
85 | + $this->ee_ueip_has_notified = true; |
|
86 | + } |
|
87 | + } |
|
88 | + |
|
89 | + |
|
90 | + /** |
|
91 | + * @return array |
|
92 | + */ |
|
93 | + public function get_critical_pages_array(): array |
|
94 | + { |
|
95 | + return [ |
|
96 | + $this->reg_page_id, |
|
97 | + $this->txn_page_id, |
|
98 | + $this->thank_you_page_id, |
|
99 | + $this->cancel_page_id, |
|
100 | + ]; |
|
101 | + } |
|
102 | + |
|
103 | + |
|
104 | + /** |
|
105 | + * @return array |
|
106 | + */ |
|
107 | + public function get_critical_pages_shortcodes_array(): array |
|
108 | + { |
|
109 | + return [ |
|
110 | + $this->reg_page_id => 'ESPRESSO_CHECKOUT', |
|
111 | + $this->txn_page_id => 'ESPRESSO_TXN_PAGE', |
|
112 | + $this->thank_you_page_id => 'ESPRESSO_THANK_YOU', |
|
113 | + $this->cancel_page_id => 'ESPRESSO_CANCELLED', |
|
114 | + ]; |
|
115 | + } |
|
116 | + |
|
117 | + |
|
118 | + /** |
|
119 | + * gets/returns URL for EE reg_page |
|
120 | + * |
|
121 | + * @return string |
|
122 | + */ |
|
123 | + public function reg_page_url(): string |
|
124 | + { |
|
125 | + if (! $this->reg_page_url) { |
|
126 | + $this->reg_page_url = add_query_arg( |
|
127 | + ['uts' => time()], |
|
128 | + get_permalink($this->reg_page_id) |
|
129 | + ) . '#checkout'; |
|
130 | + } |
|
131 | + return $this->reg_page_url; |
|
132 | + } |
|
133 | + |
|
134 | + |
|
135 | + /** |
|
136 | + * gets/returns URL for EE txn_page |
|
137 | + * |
|
138 | + * @param array $query_args like what gets passed to add_query_arg() as the first argument |
|
139 | + * @return string |
|
140 | + */ |
|
141 | + public function txn_page_url(array $query_args = []): string |
|
142 | + { |
|
143 | + if (! $this->txn_page_url) { |
|
144 | + $this->txn_page_url = get_permalink($this->txn_page_id); |
|
145 | + } |
|
146 | + if ($query_args) { |
|
147 | + return add_query_arg($query_args, $this->txn_page_url); |
|
148 | + } |
|
149 | + return $this->txn_page_url; |
|
150 | + } |
|
151 | + |
|
152 | + |
|
153 | + /** |
|
154 | + * gets/returns URL for EE thank_you_page |
|
155 | + * |
|
156 | + * @param array $query_args like what gets passed to |
|
157 | + * add_query_arg() as the first argument |
|
158 | + * @return string |
|
159 | + */ |
|
160 | + public function thank_you_page_url(array $query_args = []): string |
|
161 | + { |
|
162 | + if (! $this->thank_you_page_url) { |
|
163 | + $this->thank_you_page_url = get_permalink($this->thank_you_page_id); |
|
164 | + } |
|
165 | + if ($query_args) { |
|
166 | + return add_query_arg($query_args, $this->thank_you_page_url); |
|
167 | + } |
|
168 | + return $this->thank_you_page_url; |
|
169 | + } |
|
170 | + |
|
171 | + |
|
172 | + /** |
|
173 | + * gets/returns URL for EE cancel_page |
|
174 | + * |
|
175 | + * @return string |
|
176 | + */ |
|
177 | + public function cancel_page_url(): string |
|
178 | + { |
|
179 | + if (! $this->cancel_page_url) { |
|
180 | + $this->cancel_page_url = get_permalink($this->cancel_page_id); |
|
181 | + } |
|
182 | + return $this->cancel_page_url; |
|
183 | + } |
|
184 | + |
|
185 | + |
|
186 | + /** |
|
187 | + * Resets all critical page urls to their original state. Used primarily by the __sleep() magic method currently. |
|
188 | + * |
|
189 | + * @since 4.7.5 |
|
190 | + */ |
|
191 | + protected function _reset_urls() |
|
192 | + { |
|
193 | + $this->reg_page_url = ''; |
|
194 | + $this->txn_page_url = ''; |
|
195 | + $this->cancel_page_url = ''; |
|
196 | + $this->thank_you_page_url = ''; |
|
197 | + } |
|
198 | + |
|
199 | + |
|
200 | + /** |
|
201 | + * Used to return what the optin value is set for the EE User Experience Program. |
|
202 | + * This accounts for multisite and this value being requested for a subsite. In multisite, the value is set |
|
203 | + * on the main site only. |
|
204 | + * |
|
205 | + * @return bool |
|
206 | + */ |
|
207 | + protected function _get_main_ee_ueip_optin() |
|
208 | + { |
|
209 | + // if this is the main site then we can just bypass our direct query. |
|
210 | + if (is_main_site()) { |
|
211 | + return get_option(self::OPTION_NAME_UXIP, false); |
|
212 | + } |
|
213 | + // is this already cached for this request? If so use it. |
|
214 | + if (EE_Core_Config::$ee_ueip_option !== null) { |
|
215 | + return EE_Core_Config::$ee_ueip_option; |
|
216 | + } |
|
217 | + global $wpdb; |
|
218 | + $current_network_main_site = is_multisite() ? get_current_site() : null; |
|
219 | + $current_main_site_id = $current_network_main_site instanceof WP_Network |
|
220 | + ? $current_network_main_site->blog_id |
|
221 | + : 1; |
|
222 | + $option = self::OPTION_NAME_UXIP; |
|
223 | + // set correct table for query |
|
224 | + $table_name = $wpdb->get_blog_prefix($current_main_site_id) . 'options'; |
|
225 | + // rather than getting blog option for the $current_main_site_id, we do a direct $wpdb query because |
|
226 | + // get_blog_option() does a switch_to_blog and that could cause infinite recursion because EE_Core_Config might be |
|
227 | + // re-constructed on the blog switch. Note, we are still executing any core wp filters on this option retrieval. |
|
228 | + // this bit of code is basically a direct copy of get_option without any caching because we are NOT switched to the blog |
|
229 | + // for the purpose of caching. |
|
230 | + $pre = apply_filters('pre_option_' . $option, false, $option); |
|
231 | + if ($pre !== false) { |
|
232 | + EE_Core_Config::$ee_ueip_option = $pre; |
|
233 | + return EE_Core_Config::$ee_ueip_option; |
|
234 | + } |
|
235 | + $row = $wpdb->get_row( |
|
236 | + $wpdb->prepare( |
|
237 | + "SELECT option_value FROM $table_name WHERE option_name = %s LIMIT 1", |
|
238 | + $option |
|
239 | + ) |
|
240 | + ); |
|
241 | + if (is_object($row)) { |
|
242 | + $value = $row->option_value; |
|
243 | + } else { // option does not exist so use default. |
|
244 | + EE_Core_Config::$ee_ueip_option = apply_filters('default_option_' . $option, false, $option); |
|
245 | + return EE_Core_Config::$ee_ueip_option; |
|
246 | + } |
|
247 | + EE_Core_Config::$ee_ueip_option = apply_filters('option_' . $option, maybe_unserialize($value), $option); |
|
248 | + return EE_Core_Config::$ee_ueip_option; |
|
249 | + } |
|
250 | + |
|
251 | + |
|
252 | + /** |
|
253 | + * Utility function for escaping the value of a property and returning. |
|
254 | + * |
|
255 | + * @param string $property property name (checks to see if exists). |
|
256 | + * @return mixed if a detected type found return the escaped value, otherwise just the raw value is returned. |
|
257 | + * @throws EE_Error |
|
258 | + */ |
|
259 | + public function get_pretty(string $property) |
|
260 | + { |
|
261 | + if ($property === self::OPTION_NAME_UXIP) { |
|
262 | + return $this->ee_ueip_optin ? 'yes' : 'no'; |
|
263 | + } |
|
264 | + return parent::get_pretty($property); |
|
265 | + } |
|
266 | + |
|
267 | + |
|
268 | + /** |
|
269 | + * Currently used to ensure critical page urls have initial values saved to the db instead of any current set values |
|
270 | + * on the object. |
|
271 | + * |
|
272 | + * @return array |
|
273 | + */ |
|
274 | + public function __sleep() |
|
275 | + { |
|
276 | + // reset all url properties |
|
277 | + $this->_reset_urls(); |
|
278 | + // return what to save to db |
|
279 | + return array_keys(get_object_vars($this)); |
|
280 | + } |
|
281 | 281 | } |
@@ -122,11 +122,11 @@ discard block |
||
122 | 122 | */ |
123 | 123 | public function reg_page_url(): string |
124 | 124 | { |
125 | - if (! $this->reg_page_url) { |
|
125 | + if ( ! $this->reg_page_url) { |
|
126 | 126 | $this->reg_page_url = add_query_arg( |
127 | 127 | ['uts' => time()], |
128 | 128 | get_permalink($this->reg_page_id) |
129 | - ) . '#checkout'; |
|
129 | + ).'#checkout'; |
|
130 | 130 | } |
131 | 131 | return $this->reg_page_url; |
132 | 132 | } |
@@ -140,7 +140,7 @@ discard block |
||
140 | 140 | */ |
141 | 141 | public function txn_page_url(array $query_args = []): string |
142 | 142 | { |
143 | - if (! $this->txn_page_url) { |
|
143 | + if ( ! $this->txn_page_url) { |
|
144 | 144 | $this->txn_page_url = get_permalink($this->txn_page_id); |
145 | 145 | } |
146 | 146 | if ($query_args) { |
@@ -159,7 +159,7 @@ discard block |
||
159 | 159 | */ |
160 | 160 | public function thank_you_page_url(array $query_args = []): string |
161 | 161 | { |
162 | - if (! $this->thank_you_page_url) { |
|
162 | + if ( ! $this->thank_you_page_url) { |
|
163 | 163 | $this->thank_you_page_url = get_permalink($this->thank_you_page_id); |
164 | 164 | } |
165 | 165 | if ($query_args) { |
@@ -176,7 +176,7 @@ discard block |
||
176 | 176 | */ |
177 | 177 | public function cancel_page_url(): string |
178 | 178 | { |
179 | - if (! $this->cancel_page_url) { |
|
179 | + if ( ! $this->cancel_page_url) { |
|
180 | 180 | $this->cancel_page_url = get_permalink($this->cancel_page_id); |
181 | 181 | } |
182 | 182 | return $this->cancel_page_url; |
@@ -221,13 +221,13 @@ discard block |
||
221 | 221 | : 1; |
222 | 222 | $option = self::OPTION_NAME_UXIP; |
223 | 223 | // set correct table for query |
224 | - $table_name = $wpdb->get_blog_prefix($current_main_site_id) . 'options'; |
|
224 | + $table_name = $wpdb->get_blog_prefix($current_main_site_id).'options'; |
|
225 | 225 | // rather than getting blog option for the $current_main_site_id, we do a direct $wpdb query because |
226 | 226 | // get_blog_option() does a switch_to_blog and that could cause infinite recursion because EE_Core_Config might be |
227 | 227 | // re-constructed on the blog switch. Note, we are still executing any core wp filters on this option retrieval. |
228 | 228 | // this bit of code is basically a direct copy of get_option without any caching because we are NOT switched to the blog |
229 | 229 | // for the purpose of caching. |
230 | - $pre = apply_filters('pre_option_' . $option, false, $option); |
|
230 | + $pre = apply_filters('pre_option_'.$option, false, $option); |
|
231 | 231 | if ($pre !== false) { |
232 | 232 | EE_Core_Config::$ee_ueip_option = $pre; |
233 | 233 | return EE_Core_Config::$ee_ueip_option; |
@@ -241,10 +241,10 @@ discard block |
||
241 | 241 | if (is_object($row)) { |
242 | 242 | $value = $row->option_value; |
243 | 243 | } else { // option does not exist so use default. |
244 | - EE_Core_Config::$ee_ueip_option = apply_filters('default_option_' . $option, false, $option); |
|
244 | + EE_Core_Config::$ee_ueip_option = apply_filters('default_option_'.$option, false, $option); |
|
245 | 245 | return EE_Core_Config::$ee_ueip_option; |
246 | 246 | } |
247 | - EE_Core_Config::$ee_ueip_option = apply_filters('option_' . $option, maybe_unserialize($value), $option); |
|
247 | + EE_Core_Config::$ee_ueip_option = apply_filters('option_'.$option, maybe_unserialize($value), $option); |
|
248 | 248 | return EE_Core_Config::$ee_ueip_option; |
249 | 249 | } |
250 | 250 |
@@ -10,127 +10,127 @@ |
||
10 | 10 | */ |
11 | 11 | abstract class EE_Config_Base |
12 | 12 | { |
13 | - /** |
|
14 | - * Utility function for escaping the value of a property and returning. |
|
15 | - * |
|
16 | - * @param string $property property name (checks to see if exists). |
|
17 | - * @return mixed if a detected type found return the escaped value, otherwise just the raw value is returned. |
|
18 | - * @throws EE_Error |
|
19 | - */ |
|
20 | - public function get_pretty(string $property) |
|
21 | - { |
|
22 | - if (! property_exists($this, $property)) { |
|
23 | - throw new EE_Error( |
|
24 | - sprintf( |
|
25 | - esc_html__( |
|
26 | - '%1$s::get_pretty() has been called with the property %2$s which does not exist on the %1$s config class.', |
|
27 | - 'event_espresso' |
|
28 | - ), |
|
29 | - get_class($this), |
|
30 | - $property |
|
31 | - ) |
|
32 | - ); |
|
33 | - } |
|
34 | - // just handling escaping of strings for now. |
|
35 | - if (is_string($this->{$property})) { |
|
36 | - return stripslashes($this->{$property}); |
|
37 | - } |
|
38 | - return $this->{$property}; |
|
39 | - } |
|
40 | - |
|
41 | - |
|
42 | - /** |
|
43 | - * @throws ReflectionException |
|
44 | - */ |
|
45 | - public function populate() |
|
46 | - { |
|
47 | - // grab defaults via a new instance of this class. |
|
48 | - $class_name = get_class($this); |
|
49 | - $mirror = $this->getReflector(); |
|
50 | - $defaults = $mirror->getDefaultProperties($class_name); |
|
51 | - $static_defaults = $mirror->getStaticProperties($class_name); |
|
52 | - // loop through the properties for this class and see if they are set. If they are NOT, then grab the |
|
53 | - // default from our $defaults object. |
|
54 | - foreach ($defaults as $property => $value) { |
|
55 | - $is_static_property = array_key_exists($property, $static_defaults); |
|
56 | - // double $$ is not a typo, it's how to access a static variable dynamically. |
|
57 | - if ($is_static_property && $class_name::$$property !== null) { |
|
58 | - continue; |
|
59 | - } |
|
60 | - $reflection_property = $mirror->getProperty($class_name, $property); |
|
61 | - $is_public_property = $reflection_property->isPublic(); |
|
62 | - if ($is_public_property && ! $is_static_property && $this->{$property} !== null) { |
|
63 | - continue; |
|
64 | - } |
|
65 | - $camelGetter = EEH_Inflector::camelize_all_but_first($property); |
|
66 | - if (method_exists($this, $camelGetter) && $this->{$camelGetter}() !== null) { |
|
67 | - continue; |
|
68 | - } |
|
69 | - $setter = "set_$property"; |
|
70 | - if (method_exists($this, $setter)) { |
|
71 | - $this->$setter($value); |
|
72 | - continue; |
|
73 | - } |
|
74 | - $camelSetter = 'set' . EEH_Inflector::camelize($property); |
|
75 | - if (method_exists($this, $camelSetter)) { |
|
76 | - $this->$camelSetter($value); |
|
77 | - continue; |
|
78 | - } |
|
79 | - if ($is_static_property) { |
|
80 | - // double $$ is not a typo, it's how to access a static variable dynamically. |
|
81 | - $class_name::$$property = $static_defaults[ $property ]; |
|
82 | - continue; |
|
83 | - } |
|
84 | - if ($is_public_property) { |
|
85 | - $this->{$property} = $value; |
|
86 | - } |
|
87 | - } |
|
88 | - // cleanup |
|
89 | - unset($defaults); |
|
90 | - } |
|
91 | - |
|
92 | - |
|
93 | - private function getReflector(): Mirror |
|
94 | - { |
|
95 | - static $mirror = null; |
|
96 | - if ($mirror === null) { |
|
97 | - $mirror = LoaderFactory::getShared(Mirror::class); |
|
98 | - } |
|
99 | - return $mirror; |
|
100 | - } |
|
101 | - |
|
102 | - |
|
103 | - /** |
|
104 | - * @param mixed $a |
|
105 | - * @return bool |
|
106 | - */ |
|
107 | - public function __isset($a) |
|
108 | - { |
|
109 | - return false; |
|
110 | - } |
|
111 | - |
|
112 | - |
|
113 | - /** |
|
114 | - * @param mixed $a |
|
115 | - * @return bool |
|
116 | - */ |
|
117 | - public function __unset($a) |
|
118 | - { |
|
119 | - return false; |
|
120 | - } |
|
121 | - |
|
122 | - |
|
123 | - public function __clone() |
|
124 | - { |
|
125 | - } |
|
126 | - |
|
127 | - |
|
128 | - public function __wakeup() |
|
129 | - { |
|
130 | - } |
|
131 | - |
|
132 | - |
|
133 | - public function __destruct() |
|
134 | - { |
|
135 | - } |
|
13 | + /** |
|
14 | + * Utility function for escaping the value of a property and returning. |
|
15 | + * |
|
16 | + * @param string $property property name (checks to see if exists). |
|
17 | + * @return mixed if a detected type found return the escaped value, otherwise just the raw value is returned. |
|
18 | + * @throws EE_Error |
|
19 | + */ |
|
20 | + public function get_pretty(string $property) |
|
21 | + { |
|
22 | + if (! property_exists($this, $property)) { |
|
23 | + throw new EE_Error( |
|
24 | + sprintf( |
|
25 | + esc_html__( |
|
26 | + '%1$s::get_pretty() has been called with the property %2$s which does not exist on the %1$s config class.', |
|
27 | + 'event_espresso' |
|
28 | + ), |
|
29 | + get_class($this), |
|
30 | + $property |
|
31 | + ) |
|
32 | + ); |
|
33 | + } |
|
34 | + // just handling escaping of strings for now. |
|
35 | + if (is_string($this->{$property})) { |
|
36 | + return stripslashes($this->{$property}); |
|
37 | + } |
|
38 | + return $this->{$property}; |
|
39 | + } |
|
40 | + |
|
41 | + |
|
42 | + /** |
|
43 | + * @throws ReflectionException |
|
44 | + */ |
|
45 | + public function populate() |
|
46 | + { |
|
47 | + // grab defaults via a new instance of this class. |
|
48 | + $class_name = get_class($this); |
|
49 | + $mirror = $this->getReflector(); |
|
50 | + $defaults = $mirror->getDefaultProperties($class_name); |
|
51 | + $static_defaults = $mirror->getStaticProperties($class_name); |
|
52 | + // loop through the properties for this class and see if they are set. If they are NOT, then grab the |
|
53 | + // default from our $defaults object. |
|
54 | + foreach ($defaults as $property => $value) { |
|
55 | + $is_static_property = array_key_exists($property, $static_defaults); |
|
56 | + // double $$ is not a typo, it's how to access a static variable dynamically. |
|
57 | + if ($is_static_property && $class_name::$$property !== null) { |
|
58 | + continue; |
|
59 | + } |
|
60 | + $reflection_property = $mirror->getProperty($class_name, $property); |
|
61 | + $is_public_property = $reflection_property->isPublic(); |
|
62 | + if ($is_public_property && ! $is_static_property && $this->{$property} !== null) { |
|
63 | + continue; |
|
64 | + } |
|
65 | + $camelGetter = EEH_Inflector::camelize_all_but_first($property); |
|
66 | + if (method_exists($this, $camelGetter) && $this->{$camelGetter}() !== null) { |
|
67 | + continue; |
|
68 | + } |
|
69 | + $setter = "set_$property"; |
|
70 | + if (method_exists($this, $setter)) { |
|
71 | + $this->$setter($value); |
|
72 | + continue; |
|
73 | + } |
|
74 | + $camelSetter = 'set' . EEH_Inflector::camelize($property); |
|
75 | + if (method_exists($this, $camelSetter)) { |
|
76 | + $this->$camelSetter($value); |
|
77 | + continue; |
|
78 | + } |
|
79 | + if ($is_static_property) { |
|
80 | + // double $$ is not a typo, it's how to access a static variable dynamically. |
|
81 | + $class_name::$$property = $static_defaults[ $property ]; |
|
82 | + continue; |
|
83 | + } |
|
84 | + if ($is_public_property) { |
|
85 | + $this->{$property} = $value; |
|
86 | + } |
|
87 | + } |
|
88 | + // cleanup |
|
89 | + unset($defaults); |
|
90 | + } |
|
91 | + |
|
92 | + |
|
93 | + private function getReflector(): Mirror |
|
94 | + { |
|
95 | + static $mirror = null; |
|
96 | + if ($mirror === null) { |
|
97 | + $mirror = LoaderFactory::getShared(Mirror::class); |
|
98 | + } |
|
99 | + return $mirror; |
|
100 | + } |
|
101 | + |
|
102 | + |
|
103 | + /** |
|
104 | + * @param mixed $a |
|
105 | + * @return bool |
|
106 | + */ |
|
107 | + public function __isset($a) |
|
108 | + { |
|
109 | + return false; |
|
110 | + } |
|
111 | + |
|
112 | + |
|
113 | + /** |
|
114 | + * @param mixed $a |
|
115 | + * @return bool |
|
116 | + */ |
|
117 | + public function __unset($a) |
|
118 | + { |
|
119 | + return false; |
|
120 | + } |
|
121 | + |
|
122 | + |
|
123 | + public function __clone() |
|
124 | + { |
|
125 | + } |
|
126 | + |
|
127 | + |
|
128 | + public function __wakeup() |
|
129 | + { |
|
130 | + } |
|
131 | + |
|
132 | + |
|
133 | + public function __destruct() |
|
134 | + { |
|
135 | + } |
|
136 | 136 | } |
@@ -19,7 +19,7 @@ discard block |
||
19 | 19 | */ |
20 | 20 | public function get_pretty(string $property) |
21 | 21 | { |
22 | - if (! property_exists($this, $property)) { |
|
22 | + if ( ! property_exists($this, $property)) { |
|
23 | 23 | throw new EE_Error( |
24 | 24 | sprintf( |
25 | 25 | esc_html__( |
@@ -52,7 +52,7 @@ discard block |
||
52 | 52 | // loop through the properties for this class and see if they are set. If they are NOT, then grab the |
53 | 53 | // default from our $defaults object. |
54 | 54 | foreach ($defaults as $property => $value) { |
55 | - $is_static_property = array_key_exists($property, $static_defaults); |
|
55 | + $is_static_property = array_key_exists($property, $static_defaults); |
|
56 | 56 | // double $$ is not a typo, it's how to access a static variable dynamically. |
57 | 57 | if ($is_static_property && $class_name::$$property !== null) { |
58 | 58 | continue; |
@@ -71,14 +71,14 @@ discard block |
||
71 | 71 | $this->$setter($value); |
72 | 72 | continue; |
73 | 73 | } |
74 | - $camelSetter = 'set' . EEH_Inflector::camelize($property); |
|
74 | + $camelSetter = 'set'.EEH_Inflector::camelize($property); |
|
75 | 75 | if (method_exists($this, $camelSetter)) { |
76 | 76 | $this->$camelSetter($value); |
77 | 77 | continue; |
78 | 78 | } |
79 | 79 | if ($is_static_property) { |
80 | 80 | // double $$ is not a typo, it's how to access a static variable dynamically. |
81 | - $class_name::$$property = $static_defaults[ $property ]; |
|
81 | + $class_name::$$property = $static_defaults[$property]; |
|
82 | 82 | continue; |
83 | 83 | } |
84 | 84 | if ($is_public_property) { |
@@ -18,447 +18,447 @@ |
||
18 | 18 | */ |
19 | 19 | class EE_Admin_Page_Loader |
20 | 20 | { |
21 | - /** |
|
22 | - * @var AdminMenuManager $menu_manager |
|
23 | - */ |
|
24 | - protected $menu_manager; |
|
25 | - |
|
26 | - /** |
|
27 | - * @var LoaderInterface $loader |
|
28 | - */ |
|
29 | - protected $loader; |
|
30 | - |
|
31 | - /** |
|
32 | - * _installed_pages |
|
33 | - * objects for page_init objects detected and loaded |
|
34 | - * |
|
35 | - * @access private |
|
36 | - * @var EE_Admin_Page_Init[] |
|
37 | - */ |
|
38 | - private $_installed_pages = []; |
|
39 | - |
|
40 | - |
|
41 | - /** |
|
42 | - * this is used to hold the registry of menu slugs for all the installed admin pages |
|
43 | - * |
|
44 | - * @var array |
|
45 | - */ |
|
46 | - private $_menu_slugs = []; |
|
47 | - |
|
48 | - |
|
49 | - /** |
|
50 | - * _caffeinated_extends |
|
51 | - * This array is the generated configuration array for which core EE_Admin pages are extended (and the bits and |
|
52 | - * pieces needed to do so). This property is defined in the _set_caffeinated method. |
|
53 | - * |
|
54 | - * @var array |
|
55 | - */ |
|
56 | - private $_caffeinated_extends = []; |
|
57 | - |
|
58 | - |
|
59 | - /** |
|
60 | - * This property will hold the hook file for setting up the filter that does all the connections between admin |
|
61 | - * pages. |
|
62 | - * |
|
63 | - * @var string |
|
64 | - */ |
|
65 | - public $hook_file; |
|
66 | - |
|
67 | - /** |
|
68 | - * @var bool |
|
69 | - * @since 5.0.0.p |
|
70 | - */ |
|
71 | - private bool $full_site_maintenance = false; |
|
72 | - |
|
73 | - |
|
74 | - /** |
|
75 | - * @throws InvalidArgumentException |
|
76 | - * @throws InvalidDataTypeException |
|
77 | - * @throws InvalidInterfaceException |
|
78 | - */ |
|
79 | - public function __construct(?LoaderInterface $loader) |
|
80 | - { |
|
81 | - $this->loader = $loader instanceof LoaderInterface ? $loader : LoaderFactory::getLoader(); |
|
82 | - $this->menu_manager = $this->loader->getShared(AdminMenuManager::class); |
|
83 | - } |
|
84 | - |
|
85 | - |
|
86 | - /** |
|
87 | - * @throws EE_Error |
|
88 | - * @throws ReflectionException |
|
89 | - * @since 5.0.0.p |
|
90 | - */ |
|
91 | - public function init() |
|
92 | - { |
|
93 | - $this->menu_manager->initialize(); |
|
94 | - $this->full_site_maintenance = MaintenanceStatus::isFullSite(); |
|
95 | - // let's do a scan and see what installed pages we have |
|
96 | - $this->findAndLoadAdminPages(); |
|
97 | - } |
|
98 | - |
|
99 | - |
|
100 | - /** |
|
101 | - * When caffeinated system is detected, this method is called to setup the caffeinated directory constants used by |
|
102 | - * files in the caffeinated folder. |
|
103 | - * |
|
104 | - * @access private |
|
105 | - * @return void |
|
106 | - */ |
|
107 | - private function defineCaffeinatedConstants() |
|
108 | - { |
|
109 | - if (! defined('EE_CORE_CAF_ADMIN')) { |
|
110 | - define('EE_CORE_CAF_ADMIN', EE_PLUGIN_DIR_PATH . 'caffeinated/admin/'); |
|
111 | - define('EE_CORE_CAF_ADMIN_URL', EE_PLUGIN_DIR_URL . 'caffeinated/admin/'); |
|
112 | - define('EE_CORE_CAF_ADMIN_NEW', EE_CORE_CAF_ADMIN . 'new/'); |
|
113 | - define('EE_CORE_CAF_ADMIN_EXTEND', EE_CORE_CAF_ADMIN . 'extend/'); |
|
114 | - define('EE_CORE_CAF_ADMIN_EXTEND_URL', EE_CORE_CAF_ADMIN_URL . 'extend/'); |
|
115 | - define('EE_CORE_CAF_ADMIN_HOOKS', EE_CORE_CAF_ADMIN . 'hooks/'); |
|
116 | - } |
|
117 | - } |
|
118 | - |
|
119 | - |
|
120 | - /** |
|
121 | - * This just gets the list of installed EE_Admin_pages. |
|
122 | - * |
|
123 | - * @access private |
|
124 | - * @return void |
|
125 | - * @throws EE_Error |
|
126 | - * @throws InvalidArgumentException |
|
127 | - * @throws InvalidDataTypeException |
|
128 | - * @throws InvalidInterfaceException |
|
129 | - * @throws ReflectionException |
|
130 | - */ |
|
131 | - private function findAndLoadAdminPages() |
|
132 | - { |
|
133 | - $admin_pages = $this->findAdminPages(); |
|
134 | - $isCaffeinated = ! (defined('EE_DECAF') && EE_DECAF) && is_dir(EE_PLUGIN_DIR_PATH . 'caffeinated/admin'); |
|
135 | - // first let's check if there IS a caffeinated folder. |
|
136 | - if ($isCaffeinated) { |
|
137 | - // this just checks the caffeinated folder and takes care of setting up any caffeinated stuff. |
|
138 | - $admin_pages = $this->findCaffeinatedAdminPages($admin_pages); |
|
139 | - // then extensions and hooks, although they don't get added to the admin pages array |
|
140 | - $this->findAdminPageExtensions(); |
|
141 | - $this->findAdminPageHooks(); |
|
142 | - } |
|
143 | - // allow plugins to add in their own pages (note at this point they will need to have an autoloader defined for their class) OR hook into EEH_Autoloader::load_admin_page() to add their path.; |
|
144 | - // loop through admin pages and setup the $_installed_pages array. |
|
145 | - $hooks_ref = []; |
|
146 | - $menu_pages = []; |
|
147 | - foreach ($admin_pages as $page => $path) { |
|
148 | - // don't load the page init class IF IT's ALREADY LOADED !!! |
|
149 | - if ( |
|
150 | - isset($this->_installed_pages[ $page ]) |
|
151 | - && $this->_installed_pages[ $page ] instanceof EE_Admin_Page_Init |
|
152 | - ) { |
|
153 | - continue; |
|
154 | - } |
|
155 | - // build list of installed pages |
|
156 | - $admin_page_init = $this->loadAdminPageInit($page); |
|
157 | - $this->_installed_pages[ $page ] = $admin_page_init; |
|
158 | - $admin_menu = $this->menu_manager->getAdminMenu($admin_page_init); |
|
159 | - $admin_page_init->setCapability($admin_menu->capability(), $admin_menu->menuSlug()); |
|
160 | - // skip if in full maintenance mode and maintenance_mode_parent is NOT set |
|
161 | - if ($this->full_site_maintenance && ! $admin_menu->maintenanceModeParent()) { |
|
162 | - unset($admin_pages[ $page ]); |
|
163 | - continue; |
|
164 | - } |
|
165 | - $menu_slug = $admin_menu->menuSlug(); |
|
166 | - $this->_menu_slugs[ $menu_slug ] = $page; |
|
167 | - $menu_pages[ $menu_slug ] = $admin_page_init; |
|
168 | - |
|
169 | - // now that we've got the admin_init objects... |
|
170 | - // let's see if there are any caffeinated pages extending the originals. |
|
171 | - // If there are then let's hook into the init admin filter and load our extentions instead. |
|
172 | - // Set flag for register hooks on extended pages b/c extended pages use the default INIT. |
|
173 | - $extended_hooks = $admin_page_init->register_hooks( |
|
174 | - $this->loadCaffeinatedExtensions($admin_page_init, $page, $menu_slug) |
|
175 | - ); |
|
176 | - $hooks_ref = array_merge($hooks_ref, $extended_hooks); |
|
177 | - } |
|
178 | - // the hooks_ref is all the pages where we have $extended _Hooks files |
|
179 | - // that will extend a class in a different folder. |
|
180 | - // So we want to make sure we load the file for the parent. |
|
181 | - // first make sure we've got unique values |
|
182 | - $hooks_ref = array_unique($hooks_ref); |
|
183 | - // now let's loop and require! |
|
184 | - foreach ($hooks_ref as $path) { |
|
185 | - // if we're not caffeinated, then we don't need to do any of the following. |
|
186 | - if (! $isCaffeinated && strpos($path, 'caffeinated') !== false) { |
|
187 | - continue; |
|
188 | - } |
|
189 | - require_once($path); |
|
190 | - } |
|
191 | - // make sure we have menu slugs global setup. Used in EE_Admin_Page->page_setup() to ensure we don't do a full class load for an admin page that isn't requested. |
|
192 | - global $ee_menu_slugs; |
|
193 | - $ee_menu_slugs = $this->_menu_slugs; |
|
194 | - // we need to loop again to run any early code |
|
195 | - foreach ($this->_installed_pages as $page) { |
|
196 | - $page->do_initial_loads(); |
|
197 | - } |
|
198 | - $this->menu_manager->setInstalledPages($menu_pages); |
|
199 | - do_action('AHEE__EE_Admin_Page_Loader___get_installed_pages_loaded', $this->_installed_pages); |
|
200 | - } |
|
201 | - |
|
202 | - |
|
203 | - /** |
|
204 | - * @return array |
|
205 | - * @throws EE_Error |
|
206 | - * @since 5.0.0.p |
|
207 | - */ |
|
208 | - private function findAdminPages(): array |
|
209 | - { |
|
210 | - // grab everything in the admin core directory |
|
211 | - $admin_page_folders = $this->findAdminPageFolders(EE_ADMIN_PAGES . '*'); |
|
212 | - $admin_page_folders = apply_filters( |
|
213 | - 'FHEE__EE_Admin_Page_Loader__findAdminPages__admin_page_folders', |
|
214 | - $admin_page_folders |
|
215 | - ); |
|
216 | - if (! empty($admin_page_folders)) { |
|
217 | - return $admin_page_folders; |
|
218 | - } |
|
219 | - $error_msg = esc_html__( |
|
220 | - 'There are no EE_Admin pages detected, it looks like EE did not install properly', |
|
221 | - 'event_espresso' |
|
222 | - ); |
|
223 | - $error_msg .= '||'; |
|
224 | - $error_msg .= sprintf( |
|
225 | - esc_html__( |
|
226 | - 'Check that the %s folder exists and is writable. Maybe try deactivating, then reactivating Event Espresso again.', |
|
227 | - 'event_espresso' |
|
228 | - ), |
|
229 | - EE_ADMIN_PAGES |
|
230 | - ); |
|
231 | - throw new RuntimeException($error_msg); |
|
232 | - } |
|
233 | - |
|
234 | - |
|
235 | - /** |
|
236 | - * get_admin_page_object |
|
237 | - * |
|
238 | - * @param string $page_slug |
|
239 | - * @return EE_Admin_Page |
|
240 | - */ |
|
241 | - public function get_admin_page_object(string $page_slug = ''): ?EE_Admin_Page |
|
242 | - { |
|
243 | - return isset($this->_installed_pages[ $page_slug ]) |
|
244 | - && $this->_installed_pages[ $page_slug ] instanceof EE_Admin_Page_Init |
|
245 | - ? $this->_installed_pages[ $page_slug ]->loaded_page_object() |
|
246 | - : null; |
|
247 | - } |
|
248 | - |
|
249 | - |
|
250 | - /** |
|
251 | - * generates an "Admin Page Init" class based on the directory name |
|
252 | - * |
|
253 | - * @param string $dir_name |
|
254 | - * @return string |
|
255 | - */ |
|
256 | - private function getClassnameForAdminPageInit(string $dir_name = ''): string |
|
257 | - { |
|
258 | - $class_name = str_replace('_', ' ', strtolower($dir_name)); |
|
259 | - return str_replace(' ', '_', ucwords($class_name)) . '_Admin_Page_Init'; |
|
260 | - } |
|
261 | - |
|
262 | - |
|
263 | - /** |
|
264 | - * _load_admin_page |
|
265 | - * Loads and instantiates page_init object for a single EE_admin page. |
|
266 | - * |
|
267 | - * @param string $page page_reference |
|
268 | - * @return EE_Admin_Page_Init |
|
269 | - * @throws EE_Error |
|
270 | - */ |
|
271 | - private function loadAdminPageInit(string $page = ''): EE_Admin_Page_Init |
|
272 | - { |
|
273 | - $class_name = $this->getClassnameForAdminPageInit($page); |
|
274 | - if (class_exists($class_name)) { |
|
275 | - $admin_page_init = $this->loader->getShared($class_name); |
|
276 | - // verify returned object |
|
277 | - if ($admin_page_init instanceof EE_Admin_Page_Init) { |
|
278 | - return $admin_page_init; |
|
279 | - } |
|
280 | - } |
|
281 | - $error_msg = sprintf( |
|
282 | - esc_html__('Something went wrong with loading the %s admin page.', 'event_espresso'), |
|
283 | - $page |
|
284 | - ); |
|
285 | - $error_msg .= '||'; // separates public from developer messages |
|
286 | - $error_msg .= "\r\n"; |
|
287 | - $error_msg .= sprintf( |
|
288 | - esc_html__('There is no Init class in place for the %s admin page.', 'event_espresso'), |
|
289 | - $page |
|
290 | - ); |
|
291 | - $error_msg .= '<br />'; |
|
292 | - $error_msg .= sprintf( |
|
293 | - esc_html__( |
|
294 | - 'Make sure you have %1$s defined. If this is a non-EE-core admin page then you also must have an autoloader in place for your class', |
|
295 | - 'event_espresso' |
|
296 | - ), |
|
297 | - '<strong>' . $class_name . '</strong>' |
|
298 | - ); |
|
299 | - throw new EE_Error($error_msg); |
|
300 | - } |
|
301 | - |
|
302 | - |
|
303 | - /** |
|
304 | - * This method is the "workhorse" for detecting and setting up caffeinated functionality. |
|
305 | - * In this method there are three checks being done: |
|
306 | - * 1. Do we have any NEW admin page sets. If we do, lets add them into the menu setup (via the $admin_pages |
|
307 | - * array) etc. (new page sets are found in caffeinated/new/{page}) |
|
308 | - * 2. Do we have any EXTENDED page sets. Basically an extended EE_Admin Page extends the core {child}_Admin_Page |
|
309 | - * class. eg. would be caffeinated/extend/events/Extend_Events_Admin_Page.core.php and in there would be a class: |
|
310 | - * Extend_Events_Admin_Page extends Events_Admin_Page. |
|
311 | - * 3. Do we have any files just for setting up hooks into other core pages. The files can be any name in |
|
312 | - * "caffeinated/hooks" EXCEPT they need a ".class.php" extension and the file name must correspond with the |
|
313 | - * classname inside. These classes are instantiated really early so that any hooks in them are run before the |
|
314 | - * corresponding apply_filters/do_actions that are found in any future loaded EE_Admin pages (INCLUDING caffeinated |
|
315 | - * admin_pages) |
|
316 | - * |
|
317 | - * @param array $admin_pages the original installed_refs array that may contain our NEW EE_Admin_Pages to be |
|
318 | - * loaded. |
|
319 | - * @return array |
|
320 | - * @throws EE_Error |
|
321 | - */ |
|
322 | - private function findCaffeinatedAdminPages(array $admin_pages): array |
|
323 | - { |
|
324 | - $this->defineCaffeinatedConstants(); |
|
325 | - |
|
326 | - $exclude = ['tickets']; |
|
327 | - $feature = $this->loader->getShared(FeatureFlags::class); |
|
328 | - if (! $feature->allowed('use_edd_plugin_licensing')) { |
|
329 | - $exclude[] = 'license_keys'; |
|
330 | - } |
|
331 | - // okay let's setup an "New" pages first (we'll return installed refs later) |
|
332 | - $admin_pages += $this->findAdminPageFolders(EE_CORE_CAF_ADMIN . 'new/*', $exclude); |
|
333 | - |
|
334 | - return apply_filters( |
|
335 | - 'FHEE__EE_Admin_Page_Loader___get_installed_pages__installed_refs', |
|
336 | - $admin_pages |
|
337 | - ); |
|
338 | - } |
|
339 | - |
|
340 | - |
|
341 | - /** |
|
342 | - * @throws EE_Error |
|
343 | - * @since 5.0.0.p |
|
344 | - */ |
|
345 | - private function findAdminPageExtensions() |
|
346 | - { |
|
347 | - // let's see if there are any EXTENDS to set up in the $_caffeinated_extends array |
|
348 | - // (that will be used later for hooking into the _initialize_admin_age in the related core_init admin page) |
|
349 | - $extensions = $this->findAdminPageFolders(EE_CORE_CAF_ADMIN . 'extend/*'); |
|
350 | - if ($extensions) { |
|
351 | - foreach ($extensions as $folder => $extension) { |
|
352 | - // convert lowercase_snake_case to Uppercase_Snake_Case |
|
353 | - $filename = str_replace(' ', '_', ucwords(str_replace('_', ' ', $folder))); |
|
354 | - $filename = "Extend_{$filename}_Admin_Page"; |
|
355 | - $filepath = EE_CORE_CAF_ADMIN . "extend/$folder/$filename.core.php"; |
|
356 | - // save filename and filepath for later |
|
357 | - $this->_caffeinated_extends[ $folder ]['path'] = str_replace(['\\', '/'], '/', $filepath); |
|
358 | - $this->_caffeinated_extends[ $folder ]['admin_page'] = $filename; |
|
359 | - } |
|
360 | - } |
|
361 | - $this->_caffeinated_extends = apply_filters( |
|
362 | - 'FHEE__EE_Admin_Page_Loader___get_installed_pages__caffeinated_extends', |
|
363 | - $this->_caffeinated_extends |
|
364 | - ); |
|
365 | - } |
|
366 | - |
|
367 | - |
|
368 | - private function loadCaffeinatedExtensions( |
|
369 | - EE_Admin_Page_Init $admin_page_init, |
|
370 | - string $page, |
|
371 | - string $menu_slug |
|
372 | - ): bool { |
|
373 | - if (! isset($this->_caffeinated_extends[ $page ])) { |
|
374 | - return false; |
|
375 | - } |
|
376 | - $admin_page_name = $admin_page_init->get_admin_page_name(); |
|
377 | - $caf_path = $this->_caffeinated_extends[ $page ]['path']; |
|
378 | - $caf_admin_page = $this->_caffeinated_extends[ $page ]['admin_page']; |
|
379 | - add_filter( |
|
380 | - "FHEE__EE_Admin_Page_Init___initialize_admin_page__path_to_file__{$menu_slug}_$admin_page_name", |
|
381 | - static function ($path_to_file) use ($caf_path) { |
|
382 | - return $caf_path; |
|
383 | - } |
|
384 | - ); |
|
385 | - add_filter( |
|
386 | - "FHEE__EE_Admin_Page_Init___initialize_admin_page__admin_page__{$menu_slug}_$admin_page_name", |
|
387 | - static function ($admin_page) use ($caf_admin_page) { |
|
388 | - return $caf_admin_page; |
|
389 | - } |
|
390 | - ); |
|
391 | - return true; |
|
392 | - } |
|
393 | - |
|
394 | - |
|
395 | - /** |
|
396 | - * @throws EE_Error |
|
397 | - * @since 5.0.0.p |
|
398 | - */ |
|
399 | - private function findAdminPageHooks() |
|
400 | - { |
|
401 | - // let's see if there are any HOOK files and instantiate them if there are (so that hooks are loaded early!). |
|
402 | - $ee_admin_hooks = []; |
|
403 | - $admin_page_hooks = $this->findAdminPageFolders(EE_CORE_CAF_ADMIN . 'hooks/*.class.php', [], 0, false); |
|
404 | - if ($admin_page_hooks) { |
|
405 | - foreach ($admin_page_hooks as $hook) { |
|
406 | - if (is_readable($hook)) { |
|
407 | - require_once $hook; |
|
408 | - $classname = str_replace([EE_CORE_CAF_ADMIN . 'hooks/', '.class.php'], '', $hook); |
|
409 | - if (class_exists($classname)) { |
|
410 | - $ee_admin_hooks[] = $this->loader->getShared($classname); |
|
411 | - } |
|
412 | - } |
|
413 | - } |
|
414 | - } |
|
415 | - apply_filters('FHEE__EE_Admin_Page_Loader__set_caffeinated__ee_admin_hooks', $ee_admin_hooks); |
|
416 | - } |
|
417 | - |
|
418 | - |
|
419 | - /** |
|
420 | - * _default_header_link |
|
421 | - * This is just a dummy method to use with header submenu items |
|
422 | - * |
|
423 | - * @return bool false |
|
424 | - */ |
|
425 | - public function _default_header_link(): bool |
|
426 | - { |
|
427 | - return false; |
|
428 | - } |
|
429 | - |
|
430 | - |
|
431 | - /** |
|
432 | - * @param string $path |
|
433 | - * @param int $flags |
|
434 | - * @param array $exclude |
|
435 | - * @param bool $register_autoloaders |
|
436 | - * @return array |
|
437 | - * @throws EE_Error |
|
438 | - * @since 5.0.0.p |
|
439 | - */ |
|
440 | - private function findAdminPageFolders( |
|
441 | - string $path, |
|
442 | - array $exclude = [], |
|
443 | - int $flags = GLOB_ONLYDIR, |
|
444 | - bool $register_autoloaders = true |
|
445 | - ): array { |
|
446 | - $folders = []; |
|
447 | - $subfolders = glob($path, $flags); |
|
448 | - if ($subfolders) { |
|
449 | - foreach ($subfolders as $admin_screen) { |
|
450 | - $admin_screen_name = basename($admin_screen); |
|
451 | - // files and anything in the exclude array need not apply |
|
452 | - if (! in_array($admin_screen_name, $exclude, true)) { |
|
453 | - // these folders represent the different EE admin pages |
|
454 | - $folders[ $admin_screen_name ] = $admin_screen; |
|
455 | - if ($register_autoloaders) { |
|
456 | - // set autoloaders for our admin page classes based on included path information |
|
457 | - EEH_Autoloader::register_autoloaders_for_each_file_in_folder($admin_screen); |
|
458 | - } |
|
459 | - } |
|
460 | - } |
|
461 | - } |
|
462 | - return $folders; |
|
463 | - } |
|
21 | + /** |
|
22 | + * @var AdminMenuManager $menu_manager |
|
23 | + */ |
|
24 | + protected $menu_manager; |
|
25 | + |
|
26 | + /** |
|
27 | + * @var LoaderInterface $loader |
|
28 | + */ |
|
29 | + protected $loader; |
|
30 | + |
|
31 | + /** |
|
32 | + * _installed_pages |
|
33 | + * objects for page_init objects detected and loaded |
|
34 | + * |
|
35 | + * @access private |
|
36 | + * @var EE_Admin_Page_Init[] |
|
37 | + */ |
|
38 | + private $_installed_pages = []; |
|
39 | + |
|
40 | + |
|
41 | + /** |
|
42 | + * this is used to hold the registry of menu slugs for all the installed admin pages |
|
43 | + * |
|
44 | + * @var array |
|
45 | + */ |
|
46 | + private $_menu_slugs = []; |
|
47 | + |
|
48 | + |
|
49 | + /** |
|
50 | + * _caffeinated_extends |
|
51 | + * This array is the generated configuration array for which core EE_Admin pages are extended (and the bits and |
|
52 | + * pieces needed to do so). This property is defined in the _set_caffeinated method. |
|
53 | + * |
|
54 | + * @var array |
|
55 | + */ |
|
56 | + private $_caffeinated_extends = []; |
|
57 | + |
|
58 | + |
|
59 | + /** |
|
60 | + * This property will hold the hook file for setting up the filter that does all the connections between admin |
|
61 | + * pages. |
|
62 | + * |
|
63 | + * @var string |
|
64 | + */ |
|
65 | + public $hook_file; |
|
66 | + |
|
67 | + /** |
|
68 | + * @var bool |
|
69 | + * @since 5.0.0.p |
|
70 | + */ |
|
71 | + private bool $full_site_maintenance = false; |
|
72 | + |
|
73 | + |
|
74 | + /** |
|
75 | + * @throws InvalidArgumentException |
|
76 | + * @throws InvalidDataTypeException |
|
77 | + * @throws InvalidInterfaceException |
|
78 | + */ |
|
79 | + public function __construct(?LoaderInterface $loader) |
|
80 | + { |
|
81 | + $this->loader = $loader instanceof LoaderInterface ? $loader : LoaderFactory::getLoader(); |
|
82 | + $this->menu_manager = $this->loader->getShared(AdminMenuManager::class); |
|
83 | + } |
|
84 | + |
|
85 | + |
|
86 | + /** |
|
87 | + * @throws EE_Error |
|
88 | + * @throws ReflectionException |
|
89 | + * @since 5.0.0.p |
|
90 | + */ |
|
91 | + public function init() |
|
92 | + { |
|
93 | + $this->menu_manager->initialize(); |
|
94 | + $this->full_site_maintenance = MaintenanceStatus::isFullSite(); |
|
95 | + // let's do a scan and see what installed pages we have |
|
96 | + $this->findAndLoadAdminPages(); |
|
97 | + } |
|
98 | + |
|
99 | + |
|
100 | + /** |
|
101 | + * When caffeinated system is detected, this method is called to setup the caffeinated directory constants used by |
|
102 | + * files in the caffeinated folder. |
|
103 | + * |
|
104 | + * @access private |
|
105 | + * @return void |
|
106 | + */ |
|
107 | + private function defineCaffeinatedConstants() |
|
108 | + { |
|
109 | + if (! defined('EE_CORE_CAF_ADMIN')) { |
|
110 | + define('EE_CORE_CAF_ADMIN', EE_PLUGIN_DIR_PATH . 'caffeinated/admin/'); |
|
111 | + define('EE_CORE_CAF_ADMIN_URL', EE_PLUGIN_DIR_URL . 'caffeinated/admin/'); |
|
112 | + define('EE_CORE_CAF_ADMIN_NEW', EE_CORE_CAF_ADMIN . 'new/'); |
|
113 | + define('EE_CORE_CAF_ADMIN_EXTEND', EE_CORE_CAF_ADMIN . 'extend/'); |
|
114 | + define('EE_CORE_CAF_ADMIN_EXTEND_URL', EE_CORE_CAF_ADMIN_URL . 'extend/'); |
|
115 | + define('EE_CORE_CAF_ADMIN_HOOKS', EE_CORE_CAF_ADMIN . 'hooks/'); |
|
116 | + } |
|
117 | + } |
|
118 | + |
|
119 | + |
|
120 | + /** |
|
121 | + * This just gets the list of installed EE_Admin_pages. |
|
122 | + * |
|
123 | + * @access private |
|
124 | + * @return void |
|
125 | + * @throws EE_Error |
|
126 | + * @throws InvalidArgumentException |
|
127 | + * @throws InvalidDataTypeException |
|
128 | + * @throws InvalidInterfaceException |
|
129 | + * @throws ReflectionException |
|
130 | + */ |
|
131 | + private function findAndLoadAdminPages() |
|
132 | + { |
|
133 | + $admin_pages = $this->findAdminPages(); |
|
134 | + $isCaffeinated = ! (defined('EE_DECAF') && EE_DECAF) && is_dir(EE_PLUGIN_DIR_PATH . 'caffeinated/admin'); |
|
135 | + // first let's check if there IS a caffeinated folder. |
|
136 | + if ($isCaffeinated) { |
|
137 | + // this just checks the caffeinated folder and takes care of setting up any caffeinated stuff. |
|
138 | + $admin_pages = $this->findCaffeinatedAdminPages($admin_pages); |
|
139 | + // then extensions and hooks, although they don't get added to the admin pages array |
|
140 | + $this->findAdminPageExtensions(); |
|
141 | + $this->findAdminPageHooks(); |
|
142 | + } |
|
143 | + // allow plugins to add in their own pages (note at this point they will need to have an autoloader defined for their class) OR hook into EEH_Autoloader::load_admin_page() to add their path.; |
|
144 | + // loop through admin pages and setup the $_installed_pages array. |
|
145 | + $hooks_ref = []; |
|
146 | + $menu_pages = []; |
|
147 | + foreach ($admin_pages as $page => $path) { |
|
148 | + // don't load the page init class IF IT's ALREADY LOADED !!! |
|
149 | + if ( |
|
150 | + isset($this->_installed_pages[ $page ]) |
|
151 | + && $this->_installed_pages[ $page ] instanceof EE_Admin_Page_Init |
|
152 | + ) { |
|
153 | + continue; |
|
154 | + } |
|
155 | + // build list of installed pages |
|
156 | + $admin_page_init = $this->loadAdminPageInit($page); |
|
157 | + $this->_installed_pages[ $page ] = $admin_page_init; |
|
158 | + $admin_menu = $this->menu_manager->getAdminMenu($admin_page_init); |
|
159 | + $admin_page_init->setCapability($admin_menu->capability(), $admin_menu->menuSlug()); |
|
160 | + // skip if in full maintenance mode and maintenance_mode_parent is NOT set |
|
161 | + if ($this->full_site_maintenance && ! $admin_menu->maintenanceModeParent()) { |
|
162 | + unset($admin_pages[ $page ]); |
|
163 | + continue; |
|
164 | + } |
|
165 | + $menu_slug = $admin_menu->menuSlug(); |
|
166 | + $this->_menu_slugs[ $menu_slug ] = $page; |
|
167 | + $menu_pages[ $menu_slug ] = $admin_page_init; |
|
168 | + |
|
169 | + // now that we've got the admin_init objects... |
|
170 | + // let's see if there are any caffeinated pages extending the originals. |
|
171 | + // If there are then let's hook into the init admin filter and load our extentions instead. |
|
172 | + // Set flag for register hooks on extended pages b/c extended pages use the default INIT. |
|
173 | + $extended_hooks = $admin_page_init->register_hooks( |
|
174 | + $this->loadCaffeinatedExtensions($admin_page_init, $page, $menu_slug) |
|
175 | + ); |
|
176 | + $hooks_ref = array_merge($hooks_ref, $extended_hooks); |
|
177 | + } |
|
178 | + // the hooks_ref is all the pages where we have $extended _Hooks files |
|
179 | + // that will extend a class in a different folder. |
|
180 | + // So we want to make sure we load the file for the parent. |
|
181 | + // first make sure we've got unique values |
|
182 | + $hooks_ref = array_unique($hooks_ref); |
|
183 | + // now let's loop and require! |
|
184 | + foreach ($hooks_ref as $path) { |
|
185 | + // if we're not caffeinated, then we don't need to do any of the following. |
|
186 | + if (! $isCaffeinated && strpos($path, 'caffeinated') !== false) { |
|
187 | + continue; |
|
188 | + } |
|
189 | + require_once($path); |
|
190 | + } |
|
191 | + // make sure we have menu slugs global setup. Used in EE_Admin_Page->page_setup() to ensure we don't do a full class load for an admin page that isn't requested. |
|
192 | + global $ee_menu_slugs; |
|
193 | + $ee_menu_slugs = $this->_menu_slugs; |
|
194 | + // we need to loop again to run any early code |
|
195 | + foreach ($this->_installed_pages as $page) { |
|
196 | + $page->do_initial_loads(); |
|
197 | + } |
|
198 | + $this->menu_manager->setInstalledPages($menu_pages); |
|
199 | + do_action('AHEE__EE_Admin_Page_Loader___get_installed_pages_loaded', $this->_installed_pages); |
|
200 | + } |
|
201 | + |
|
202 | + |
|
203 | + /** |
|
204 | + * @return array |
|
205 | + * @throws EE_Error |
|
206 | + * @since 5.0.0.p |
|
207 | + */ |
|
208 | + private function findAdminPages(): array |
|
209 | + { |
|
210 | + // grab everything in the admin core directory |
|
211 | + $admin_page_folders = $this->findAdminPageFolders(EE_ADMIN_PAGES . '*'); |
|
212 | + $admin_page_folders = apply_filters( |
|
213 | + 'FHEE__EE_Admin_Page_Loader__findAdminPages__admin_page_folders', |
|
214 | + $admin_page_folders |
|
215 | + ); |
|
216 | + if (! empty($admin_page_folders)) { |
|
217 | + return $admin_page_folders; |
|
218 | + } |
|
219 | + $error_msg = esc_html__( |
|
220 | + 'There are no EE_Admin pages detected, it looks like EE did not install properly', |
|
221 | + 'event_espresso' |
|
222 | + ); |
|
223 | + $error_msg .= '||'; |
|
224 | + $error_msg .= sprintf( |
|
225 | + esc_html__( |
|
226 | + 'Check that the %s folder exists and is writable. Maybe try deactivating, then reactivating Event Espresso again.', |
|
227 | + 'event_espresso' |
|
228 | + ), |
|
229 | + EE_ADMIN_PAGES |
|
230 | + ); |
|
231 | + throw new RuntimeException($error_msg); |
|
232 | + } |
|
233 | + |
|
234 | + |
|
235 | + /** |
|
236 | + * get_admin_page_object |
|
237 | + * |
|
238 | + * @param string $page_slug |
|
239 | + * @return EE_Admin_Page |
|
240 | + */ |
|
241 | + public function get_admin_page_object(string $page_slug = ''): ?EE_Admin_Page |
|
242 | + { |
|
243 | + return isset($this->_installed_pages[ $page_slug ]) |
|
244 | + && $this->_installed_pages[ $page_slug ] instanceof EE_Admin_Page_Init |
|
245 | + ? $this->_installed_pages[ $page_slug ]->loaded_page_object() |
|
246 | + : null; |
|
247 | + } |
|
248 | + |
|
249 | + |
|
250 | + /** |
|
251 | + * generates an "Admin Page Init" class based on the directory name |
|
252 | + * |
|
253 | + * @param string $dir_name |
|
254 | + * @return string |
|
255 | + */ |
|
256 | + private function getClassnameForAdminPageInit(string $dir_name = ''): string |
|
257 | + { |
|
258 | + $class_name = str_replace('_', ' ', strtolower($dir_name)); |
|
259 | + return str_replace(' ', '_', ucwords($class_name)) . '_Admin_Page_Init'; |
|
260 | + } |
|
261 | + |
|
262 | + |
|
263 | + /** |
|
264 | + * _load_admin_page |
|
265 | + * Loads and instantiates page_init object for a single EE_admin page. |
|
266 | + * |
|
267 | + * @param string $page page_reference |
|
268 | + * @return EE_Admin_Page_Init |
|
269 | + * @throws EE_Error |
|
270 | + */ |
|
271 | + private function loadAdminPageInit(string $page = ''): EE_Admin_Page_Init |
|
272 | + { |
|
273 | + $class_name = $this->getClassnameForAdminPageInit($page); |
|
274 | + if (class_exists($class_name)) { |
|
275 | + $admin_page_init = $this->loader->getShared($class_name); |
|
276 | + // verify returned object |
|
277 | + if ($admin_page_init instanceof EE_Admin_Page_Init) { |
|
278 | + return $admin_page_init; |
|
279 | + } |
|
280 | + } |
|
281 | + $error_msg = sprintf( |
|
282 | + esc_html__('Something went wrong with loading the %s admin page.', 'event_espresso'), |
|
283 | + $page |
|
284 | + ); |
|
285 | + $error_msg .= '||'; // separates public from developer messages |
|
286 | + $error_msg .= "\r\n"; |
|
287 | + $error_msg .= sprintf( |
|
288 | + esc_html__('There is no Init class in place for the %s admin page.', 'event_espresso'), |
|
289 | + $page |
|
290 | + ); |
|
291 | + $error_msg .= '<br />'; |
|
292 | + $error_msg .= sprintf( |
|
293 | + esc_html__( |
|
294 | + 'Make sure you have %1$s defined. If this is a non-EE-core admin page then you also must have an autoloader in place for your class', |
|
295 | + 'event_espresso' |
|
296 | + ), |
|
297 | + '<strong>' . $class_name . '</strong>' |
|
298 | + ); |
|
299 | + throw new EE_Error($error_msg); |
|
300 | + } |
|
301 | + |
|
302 | + |
|
303 | + /** |
|
304 | + * This method is the "workhorse" for detecting and setting up caffeinated functionality. |
|
305 | + * In this method there are three checks being done: |
|
306 | + * 1. Do we have any NEW admin page sets. If we do, lets add them into the menu setup (via the $admin_pages |
|
307 | + * array) etc. (new page sets are found in caffeinated/new/{page}) |
|
308 | + * 2. Do we have any EXTENDED page sets. Basically an extended EE_Admin Page extends the core {child}_Admin_Page |
|
309 | + * class. eg. would be caffeinated/extend/events/Extend_Events_Admin_Page.core.php and in there would be a class: |
|
310 | + * Extend_Events_Admin_Page extends Events_Admin_Page. |
|
311 | + * 3. Do we have any files just for setting up hooks into other core pages. The files can be any name in |
|
312 | + * "caffeinated/hooks" EXCEPT they need a ".class.php" extension and the file name must correspond with the |
|
313 | + * classname inside. These classes are instantiated really early so that any hooks in them are run before the |
|
314 | + * corresponding apply_filters/do_actions that are found in any future loaded EE_Admin pages (INCLUDING caffeinated |
|
315 | + * admin_pages) |
|
316 | + * |
|
317 | + * @param array $admin_pages the original installed_refs array that may contain our NEW EE_Admin_Pages to be |
|
318 | + * loaded. |
|
319 | + * @return array |
|
320 | + * @throws EE_Error |
|
321 | + */ |
|
322 | + private function findCaffeinatedAdminPages(array $admin_pages): array |
|
323 | + { |
|
324 | + $this->defineCaffeinatedConstants(); |
|
325 | + |
|
326 | + $exclude = ['tickets']; |
|
327 | + $feature = $this->loader->getShared(FeatureFlags::class); |
|
328 | + if (! $feature->allowed('use_edd_plugin_licensing')) { |
|
329 | + $exclude[] = 'license_keys'; |
|
330 | + } |
|
331 | + // okay let's setup an "New" pages first (we'll return installed refs later) |
|
332 | + $admin_pages += $this->findAdminPageFolders(EE_CORE_CAF_ADMIN . 'new/*', $exclude); |
|
333 | + |
|
334 | + return apply_filters( |
|
335 | + 'FHEE__EE_Admin_Page_Loader___get_installed_pages__installed_refs', |
|
336 | + $admin_pages |
|
337 | + ); |
|
338 | + } |
|
339 | + |
|
340 | + |
|
341 | + /** |
|
342 | + * @throws EE_Error |
|
343 | + * @since 5.0.0.p |
|
344 | + */ |
|
345 | + private function findAdminPageExtensions() |
|
346 | + { |
|
347 | + // let's see if there are any EXTENDS to set up in the $_caffeinated_extends array |
|
348 | + // (that will be used later for hooking into the _initialize_admin_age in the related core_init admin page) |
|
349 | + $extensions = $this->findAdminPageFolders(EE_CORE_CAF_ADMIN . 'extend/*'); |
|
350 | + if ($extensions) { |
|
351 | + foreach ($extensions as $folder => $extension) { |
|
352 | + // convert lowercase_snake_case to Uppercase_Snake_Case |
|
353 | + $filename = str_replace(' ', '_', ucwords(str_replace('_', ' ', $folder))); |
|
354 | + $filename = "Extend_{$filename}_Admin_Page"; |
|
355 | + $filepath = EE_CORE_CAF_ADMIN . "extend/$folder/$filename.core.php"; |
|
356 | + // save filename and filepath for later |
|
357 | + $this->_caffeinated_extends[ $folder ]['path'] = str_replace(['\\', '/'], '/', $filepath); |
|
358 | + $this->_caffeinated_extends[ $folder ]['admin_page'] = $filename; |
|
359 | + } |
|
360 | + } |
|
361 | + $this->_caffeinated_extends = apply_filters( |
|
362 | + 'FHEE__EE_Admin_Page_Loader___get_installed_pages__caffeinated_extends', |
|
363 | + $this->_caffeinated_extends |
|
364 | + ); |
|
365 | + } |
|
366 | + |
|
367 | + |
|
368 | + private function loadCaffeinatedExtensions( |
|
369 | + EE_Admin_Page_Init $admin_page_init, |
|
370 | + string $page, |
|
371 | + string $menu_slug |
|
372 | + ): bool { |
|
373 | + if (! isset($this->_caffeinated_extends[ $page ])) { |
|
374 | + return false; |
|
375 | + } |
|
376 | + $admin_page_name = $admin_page_init->get_admin_page_name(); |
|
377 | + $caf_path = $this->_caffeinated_extends[ $page ]['path']; |
|
378 | + $caf_admin_page = $this->_caffeinated_extends[ $page ]['admin_page']; |
|
379 | + add_filter( |
|
380 | + "FHEE__EE_Admin_Page_Init___initialize_admin_page__path_to_file__{$menu_slug}_$admin_page_name", |
|
381 | + static function ($path_to_file) use ($caf_path) { |
|
382 | + return $caf_path; |
|
383 | + } |
|
384 | + ); |
|
385 | + add_filter( |
|
386 | + "FHEE__EE_Admin_Page_Init___initialize_admin_page__admin_page__{$menu_slug}_$admin_page_name", |
|
387 | + static function ($admin_page) use ($caf_admin_page) { |
|
388 | + return $caf_admin_page; |
|
389 | + } |
|
390 | + ); |
|
391 | + return true; |
|
392 | + } |
|
393 | + |
|
394 | + |
|
395 | + /** |
|
396 | + * @throws EE_Error |
|
397 | + * @since 5.0.0.p |
|
398 | + */ |
|
399 | + private function findAdminPageHooks() |
|
400 | + { |
|
401 | + // let's see if there are any HOOK files and instantiate them if there are (so that hooks are loaded early!). |
|
402 | + $ee_admin_hooks = []; |
|
403 | + $admin_page_hooks = $this->findAdminPageFolders(EE_CORE_CAF_ADMIN . 'hooks/*.class.php', [], 0, false); |
|
404 | + if ($admin_page_hooks) { |
|
405 | + foreach ($admin_page_hooks as $hook) { |
|
406 | + if (is_readable($hook)) { |
|
407 | + require_once $hook; |
|
408 | + $classname = str_replace([EE_CORE_CAF_ADMIN . 'hooks/', '.class.php'], '', $hook); |
|
409 | + if (class_exists($classname)) { |
|
410 | + $ee_admin_hooks[] = $this->loader->getShared($classname); |
|
411 | + } |
|
412 | + } |
|
413 | + } |
|
414 | + } |
|
415 | + apply_filters('FHEE__EE_Admin_Page_Loader__set_caffeinated__ee_admin_hooks', $ee_admin_hooks); |
|
416 | + } |
|
417 | + |
|
418 | + |
|
419 | + /** |
|
420 | + * _default_header_link |
|
421 | + * This is just a dummy method to use with header submenu items |
|
422 | + * |
|
423 | + * @return bool false |
|
424 | + */ |
|
425 | + public function _default_header_link(): bool |
|
426 | + { |
|
427 | + return false; |
|
428 | + } |
|
429 | + |
|
430 | + |
|
431 | + /** |
|
432 | + * @param string $path |
|
433 | + * @param int $flags |
|
434 | + * @param array $exclude |
|
435 | + * @param bool $register_autoloaders |
|
436 | + * @return array |
|
437 | + * @throws EE_Error |
|
438 | + * @since 5.0.0.p |
|
439 | + */ |
|
440 | + private function findAdminPageFolders( |
|
441 | + string $path, |
|
442 | + array $exclude = [], |
|
443 | + int $flags = GLOB_ONLYDIR, |
|
444 | + bool $register_autoloaders = true |
|
445 | + ): array { |
|
446 | + $folders = []; |
|
447 | + $subfolders = glob($path, $flags); |
|
448 | + if ($subfolders) { |
|
449 | + foreach ($subfolders as $admin_screen) { |
|
450 | + $admin_screen_name = basename($admin_screen); |
|
451 | + // files and anything in the exclude array need not apply |
|
452 | + if (! in_array($admin_screen_name, $exclude, true)) { |
|
453 | + // these folders represent the different EE admin pages |
|
454 | + $folders[ $admin_screen_name ] = $admin_screen; |
|
455 | + if ($register_autoloaders) { |
|
456 | + // set autoloaders for our admin page classes based on included path information |
|
457 | + EEH_Autoloader::register_autoloaders_for_each_file_in_folder($admin_screen); |
|
458 | + } |
|
459 | + } |
|
460 | + } |
|
461 | + } |
|
462 | + return $folders; |
|
463 | + } |
|
464 | 464 | } |
@@ -106,13 +106,13 @@ discard block |
||
106 | 106 | */ |
107 | 107 | private function defineCaffeinatedConstants() |
108 | 108 | { |
109 | - if (! defined('EE_CORE_CAF_ADMIN')) { |
|
110 | - define('EE_CORE_CAF_ADMIN', EE_PLUGIN_DIR_PATH . 'caffeinated/admin/'); |
|
111 | - define('EE_CORE_CAF_ADMIN_URL', EE_PLUGIN_DIR_URL . 'caffeinated/admin/'); |
|
112 | - define('EE_CORE_CAF_ADMIN_NEW', EE_CORE_CAF_ADMIN . 'new/'); |
|
113 | - define('EE_CORE_CAF_ADMIN_EXTEND', EE_CORE_CAF_ADMIN . 'extend/'); |
|
114 | - define('EE_CORE_CAF_ADMIN_EXTEND_URL', EE_CORE_CAF_ADMIN_URL . 'extend/'); |
|
115 | - define('EE_CORE_CAF_ADMIN_HOOKS', EE_CORE_CAF_ADMIN . 'hooks/'); |
|
109 | + if ( ! defined('EE_CORE_CAF_ADMIN')) { |
|
110 | + define('EE_CORE_CAF_ADMIN', EE_PLUGIN_DIR_PATH.'caffeinated/admin/'); |
|
111 | + define('EE_CORE_CAF_ADMIN_URL', EE_PLUGIN_DIR_URL.'caffeinated/admin/'); |
|
112 | + define('EE_CORE_CAF_ADMIN_NEW', EE_CORE_CAF_ADMIN.'new/'); |
|
113 | + define('EE_CORE_CAF_ADMIN_EXTEND', EE_CORE_CAF_ADMIN.'extend/'); |
|
114 | + define('EE_CORE_CAF_ADMIN_EXTEND_URL', EE_CORE_CAF_ADMIN_URL.'extend/'); |
|
115 | + define('EE_CORE_CAF_ADMIN_HOOKS', EE_CORE_CAF_ADMIN.'hooks/'); |
|
116 | 116 | } |
117 | 117 | } |
118 | 118 | |
@@ -131,7 +131,7 @@ discard block |
||
131 | 131 | private function findAndLoadAdminPages() |
132 | 132 | { |
133 | 133 | $admin_pages = $this->findAdminPages(); |
134 | - $isCaffeinated = ! (defined('EE_DECAF') && EE_DECAF) && is_dir(EE_PLUGIN_DIR_PATH . 'caffeinated/admin'); |
|
134 | + $isCaffeinated = ! (defined('EE_DECAF') && EE_DECAF) && is_dir(EE_PLUGIN_DIR_PATH.'caffeinated/admin'); |
|
135 | 135 | // first let's check if there IS a caffeinated folder. |
136 | 136 | if ($isCaffeinated) { |
137 | 137 | // this just checks the caffeinated folder and takes care of setting up any caffeinated stuff. |
@@ -147,24 +147,24 @@ discard block |
||
147 | 147 | foreach ($admin_pages as $page => $path) { |
148 | 148 | // don't load the page init class IF IT's ALREADY LOADED !!! |
149 | 149 | if ( |
150 | - isset($this->_installed_pages[ $page ]) |
|
151 | - && $this->_installed_pages[ $page ] instanceof EE_Admin_Page_Init |
|
150 | + isset($this->_installed_pages[$page]) |
|
151 | + && $this->_installed_pages[$page] instanceof EE_Admin_Page_Init |
|
152 | 152 | ) { |
153 | 153 | continue; |
154 | 154 | } |
155 | 155 | // build list of installed pages |
156 | 156 | $admin_page_init = $this->loadAdminPageInit($page); |
157 | - $this->_installed_pages[ $page ] = $admin_page_init; |
|
157 | + $this->_installed_pages[$page] = $admin_page_init; |
|
158 | 158 | $admin_menu = $this->menu_manager->getAdminMenu($admin_page_init); |
159 | 159 | $admin_page_init->setCapability($admin_menu->capability(), $admin_menu->menuSlug()); |
160 | 160 | // skip if in full maintenance mode and maintenance_mode_parent is NOT set |
161 | 161 | if ($this->full_site_maintenance && ! $admin_menu->maintenanceModeParent()) { |
162 | - unset($admin_pages[ $page ]); |
|
162 | + unset($admin_pages[$page]); |
|
163 | 163 | continue; |
164 | 164 | } |
165 | 165 | $menu_slug = $admin_menu->menuSlug(); |
166 | - $this->_menu_slugs[ $menu_slug ] = $page; |
|
167 | - $menu_pages[ $menu_slug ] = $admin_page_init; |
|
166 | + $this->_menu_slugs[$menu_slug] = $page; |
|
167 | + $menu_pages[$menu_slug] = $admin_page_init; |
|
168 | 168 | |
169 | 169 | // now that we've got the admin_init objects... |
170 | 170 | // let's see if there are any caffeinated pages extending the originals. |
@@ -183,7 +183,7 @@ discard block |
||
183 | 183 | // now let's loop and require! |
184 | 184 | foreach ($hooks_ref as $path) { |
185 | 185 | // if we're not caffeinated, then we don't need to do any of the following. |
186 | - if (! $isCaffeinated && strpos($path, 'caffeinated') !== false) { |
|
186 | + if ( ! $isCaffeinated && strpos($path, 'caffeinated') !== false) { |
|
187 | 187 | continue; |
188 | 188 | } |
189 | 189 | require_once($path); |
@@ -208,12 +208,12 @@ discard block |
||
208 | 208 | private function findAdminPages(): array |
209 | 209 | { |
210 | 210 | // grab everything in the admin core directory |
211 | - $admin_page_folders = $this->findAdminPageFolders(EE_ADMIN_PAGES . '*'); |
|
211 | + $admin_page_folders = $this->findAdminPageFolders(EE_ADMIN_PAGES.'*'); |
|
212 | 212 | $admin_page_folders = apply_filters( |
213 | 213 | 'FHEE__EE_Admin_Page_Loader__findAdminPages__admin_page_folders', |
214 | 214 | $admin_page_folders |
215 | 215 | ); |
216 | - if (! empty($admin_page_folders)) { |
|
216 | + if ( ! empty($admin_page_folders)) { |
|
217 | 217 | return $admin_page_folders; |
218 | 218 | } |
219 | 219 | $error_msg = esc_html__( |
@@ -240,9 +240,9 @@ discard block |
||
240 | 240 | */ |
241 | 241 | public function get_admin_page_object(string $page_slug = ''): ?EE_Admin_Page |
242 | 242 | { |
243 | - return isset($this->_installed_pages[ $page_slug ]) |
|
244 | - && $this->_installed_pages[ $page_slug ] instanceof EE_Admin_Page_Init |
|
245 | - ? $this->_installed_pages[ $page_slug ]->loaded_page_object() |
|
243 | + return isset($this->_installed_pages[$page_slug]) |
|
244 | + && $this->_installed_pages[$page_slug] instanceof EE_Admin_Page_Init |
|
245 | + ? $this->_installed_pages[$page_slug]->loaded_page_object() |
|
246 | 246 | : null; |
247 | 247 | } |
248 | 248 | |
@@ -256,7 +256,7 @@ discard block |
||
256 | 256 | private function getClassnameForAdminPageInit(string $dir_name = ''): string |
257 | 257 | { |
258 | 258 | $class_name = str_replace('_', ' ', strtolower($dir_name)); |
259 | - return str_replace(' ', '_', ucwords($class_name)) . '_Admin_Page_Init'; |
|
259 | + return str_replace(' ', '_', ucwords($class_name)).'_Admin_Page_Init'; |
|
260 | 260 | } |
261 | 261 | |
262 | 262 | |
@@ -294,7 +294,7 @@ discard block |
||
294 | 294 | 'Make sure you have %1$s defined. If this is a non-EE-core admin page then you also must have an autoloader in place for your class', |
295 | 295 | 'event_espresso' |
296 | 296 | ), |
297 | - '<strong>' . $class_name . '</strong>' |
|
297 | + '<strong>'.$class_name.'</strong>' |
|
298 | 298 | ); |
299 | 299 | throw new EE_Error($error_msg); |
300 | 300 | } |
@@ -325,11 +325,11 @@ discard block |
||
325 | 325 | |
326 | 326 | $exclude = ['tickets']; |
327 | 327 | $feature = $this->loader->getShared(FeatureFlags::class); |
328 | - if (! $feature->allowed('use_edd_plugin_licensing')) { |
|
328 | + if ( ! $feature->allowed('use_edd_plugin_licensing')) { |
|
329 | 329 | $exclude[] = 'license_keys'; |
330 | 330 | } |
331 | 331 | // okay let's setup an "New" pages first (we'll return installed refs later) |
332 | - $admin_pages += $this->findAdminPageFolders(EE_CORE_CAF_ADMIN . 'new/*', $exclude); |
|
332 | + $admin_pages += $this->findAdminPageFolders(EE_CORE_CAF_ADMIN.'new/*', $exclude); |
|
333 | 333 | |
334 | 334 | return apply_filters( |
335 | 335 | 'FHEE__EE_Admin_Page_Loader___get_installed_pages__installed_refs', |
@@ -346,16 +346,16 @@ discard block |
||
346 | 346 | { |
347 | 347 | // let's see if there are any EXTENDS to set up in the $_caffeinated_extends array |
348 | 348 | // (that will be used later for hooking into the _initialize_admin_age in the related core_init admin page) |
349 | - $extensions = $this->findAdminPageFolders(EE_CORE_CAF_ADMIN . 'extend/*'); |
|
349 | + $extensions = $this->findAdminPageFolders(EE_CORE_CAF_ADMIN.'extend/*'); |
|
350 | 350 | if ($extensions) { |
351 | 351 | foreach ($extensions as $folder => $extension) { |
352 | 352 | // convert lowercase_snake_case to Uppercase_Snake_Case |
353 | 353 | $filename = str_replace(' ', '_', ucwords(str_replace('_', ' ', $folder))); |
354 | 354 | $filename = "Extend_{$filename}_Admin_Page"; |
355 | - $filepath = EE_CORE_CAF_ADMIN . "extend/$folder/$filename.core.php"; |
|
355 | + $filepath = EE_CORE_CAF_ADMIN."extend/$folder/$filename.core.php"; |
|
356 | 356 | // save filename and filepath for later |
357 | - $this->_caffeinated_extends[ $folder ]['path'] = str_replace(['\\', '/'], '/', $filepath); |
|
358 | - $this->_caffeinated_extends[ $folder ]['admin_page'] = $filename; |
|
357 | + $this->_caffeinated_extends[$folder]['path'] = str_replace(['\\', '/'], '/', $filepath); |
|
358 | + $this->_caffeinated_extends[$folder]['admin_page'] = $filename; |
|
359 | 359 | } |
360 | 360 | } |
361 | 361 | $this->_caffeinated_extends = apply_filters( |
@@ -370,21 +370,21 @@ discard block |
||
370 | 370 | string $page, |
371 | 371 | string $menu_slug |
372 | 372 | ): bool { |
373 | - if (! isset($this->_caffeinated_extends[ $page ])) { |
|
373 | + if ( ! isset($this->_caffeinated_extends[$page])) { |
|
374 | 374 | return false; |
375 | 375 | } |
376 | 376 | $admin_page_name = $admin_page_init->get_admin_page_name(); |
377 | - $caf_path = $this->_caffeinated_extends[ $page ]['path']; |
|
378 | - $caf_admin_page = $this->_caffeinated_extends[ $page ]['admin_page']; |
|
377 | + $caf_path = $this->_caffeinated_extends[$page]['path']; |
|
378 | + $caf_admin_page = $this->_caffeinated_extends[$page]['admin_page']; |
|
379 | 379 | add_filter( |
380 | 380 | "FHEE__EE_Admin_Page_Init___initialize_admin_page__path_to_file__{$menu_slug}_$admin_page_name", |
381 | - static function ($path_to_file) use ($caf_path) { |
|
381 | + static function($path_to_file) use ($caf_path) { |
|
382 | 382 | return $caf_path; |
383 | 383 | } |
384 | 384 | ); |
385 | 385 | add_filter( |
386 | 386 | "FHEE__EE_Admin_Page_Init___initialize_admin_page__admin_page__{$menu_slug}_$admin_page_name", |
387 | - static function ($admin_page) use ($caf_admin_page) { |
|
387 | + static function($admin_page) use ($caf_admin_page) { |
|
388 | 388 | return $caf_admin_page; |
389 | 389 | } |
390 | 390 | ); |
@@ -400,12 +400,12 @@ discard block |
||
400 | 400 | { |
401 | 401 | // let's see if there are any HOOK files and instantiate them if there are (so that hooks are loaded early!). |
402 | 402 | $ee_admin_hooks = []; |
403 | - $admin_page_hooks = $this->findAdminPageFolders(EE_CORE_CAF_ADMIN . 'hooks/*.class.php', [], 0, false); |
|
403 | + $admin_page_hooks = $this->findAdminPageFolders(EE_CORE_CAF_ADMIN.'hooks/*.class.php', [], 0, false); |
|
404 | 404 | if ($admin_page_hooks) { |
405 | 405 | foreach ($admin_page_hooks as $hook) { |
406 | 406 | if (is_readable($hook)) { |
407 | 407 | require_once $hook; |
408 | - $classname = str_replace([EE_CORE_CAF_ADMIN . 'hooks/', '.class.php'], '', $hook); |
|
408 | + $classname = str_replace([EE_CORE_CAF_ADMIN.'hooks/', '.class.php'], '', $hook); |
|
409 | 409 | if (class_exists($classname)) { |
410 | 410 | $ee_admin_hooks[] = $this->loader->getShared($classname); |
411 | 411 | } |
@@ -449,9 +449,9 @@ discard block |
||
449 | 449 | foreach ($subfolders as $admin_screen) { |
450 | 450 | $admin_screen_name = basename($admin_screen); |
451 | 451 | // files and anything in the exclude array need not apply |
452 | - if (! in_array($admin_screen_name, $exclude, true)) { |
|
452 | + if ( ! in_array($admin_screen_name, $exclude, true)) { |
|
453 | 453 | // these folders represent the different EE admin pages |
454 | - $folders[ $admin_screen_name ] = $admin_screen; |
|
454 | + $folders[$admin_screen_name] = $admin_screen; |
|
455 | 455 | if ($register_autoloaders) { |
456 | 456 | // set autoloaders for our admin page classes based on included path information |
457 | 457 | EEH_Autoloader::register_autoloaders_for_each_file_in_folder($admin_screen); |
@@ -18,494 +18,494 @@ |
||
18 | 18 | */ |
19 | 19 | abstract class EE_Admin_Page_Init extends EE_Base |
20 | 20 | { |
21 | - /** |
|
22 | - * This holds the menu map object for this admin page. |
|
23 | - */ |
|
24 | - protected ?AdminMenuItem $_menu_map = null; |
|
25 | - |
|
26 | - protected ?EE_Admin_Page $_loaded_page_object = null; |
|
21 | + /** |
|
22 | + * This holds the menu map object for this admin page. |
|
23 | + */ |
|
24 | + protected ?AdminMenuItem $_menu_map = null; |
|
25 | + |
|
26 | + protected ?EE_Admin_Page $_loaded_page_object = null; |
|
27 | 27 | |
28 | - protected ?LoaderInterface $loader = null; |
|
29 | - |
|
30 | - protected ?RequestInterface $request = null; |
|
31 | - |
|
32 | - private bool $_load_page = false; |
|
33 | - |
|
34 | - protected bool $_routing = false; |
|
35 | - |
|
36 | - /** |
|
37 | - * Menu map has a capability. However, this allows admin pages to have separate capability requirements for menus |
|
38 | - * and accessing pages. If capability is NOT set, then it defaults to the menu_map capability. |
|
39 | - * |
|
40 | - * @var string |
|
41 | - */ |
|
42 | - public string $capability = ''; |
|
43 | - |
|
44 | - /** |
|
45 | - * identity properties (set in _set_defaults and _set_init_properties) |
|
46 | - */ |
|
47 | - public string $label = ''; |
|
48 | - |
|
49 | - protected string $_file_name = ''; |
|
50 | - |
|
51 | - protected string $_folder_name = ''; |
|
52 | - |
|
53 | - protected string $_folder_path = ''; |
|
54 | - |
|
55 | - protected string $_wp_page_slug = ''; |
|
56 | - |
|
57 | - public string $hook_file = ''; |
|
58 | - |
|
59 | - public string $menu_slug = ''; |
|
60 | - |
|
61 | - /** |
|
62 | - * @deprecated |
|
63 | - */ |
|
64 | - public string $menu_label = ''; |
|
65 | - |
|
66 | - protected array $_files_hooked = []; |
|
67 | - |
|
68 | - protected array $_hook_paths = []; |
|
69 | - |
|
70 | - |
|
71 | - /** |
|
72 | - * @throws InvalidArgumentException |
|
73 | - * @throws InvalidDataTypeException |
|
74 | - * @throws InvalidInterfaceException |
|
75 | - */ |
|
76 | - public function __construct(RequestInterface $request = null) |
|
77 | - { |
|
78 | - $this->loader = LoaderFactory::getLoader(); |
|
79 | - $this->request = $request instanceof RequestInterface |
|
80 | - ? $request |
|
81 | - : $this->loader->getShared(RequestInterface::class); |
|
82 | - // set global defaults |
|
83 | - $this->_set_defaults(); |
|
84 | - // set properties that are always available with objects. |
|
85 | - $this->_set_init_properties(); |
|
86 | - // global styles/scripts across all wp admin pages |
|
87 | - add_action('admin_enqueue_scripts', [$this, 'load_wp_global_scripts_styles'], 5); |
|
88 | - // load initial stuff. |
|
89 | - $this->_set_file_and_folder_name(); |
|
90 | - } |
|
91 | - |
|
92 | - |
|
93 | - /** |
|
94 | - * _set_init_properties |
|
95 | - * Child classes use to set the following properties: |
|
96 | - * $label |
|
97 | - * |
|
98 | - * @abstract |
|
99 | - * @return void |
|
100 | - */ |
|
101 | - abstract protected function _set_init_properties(); |
|
102 | - |
|
103 | - |
|
104 | - /** |
|
105 | - * @return AdminMenuItem|null |
|
106 | - * @since 4.4.0 |
|
107 | - * @deprecated 5.0.0.p |
|
108 | - */ |
|
109 | - public function get_menu_map() |
|
110 | - { |
|
111 | - return $this->adminMenu(); |
|
112 | - } |
|
113 | - |
|
114 | - |
|
115 | - /** |
|
116 | - * _set_menu_map is a function that child classes use to set the menu_map property (which should be an instance of |
|
117 | - * EE_Admin_Page_Menu_Map. Their menu can either be EE_Admin_Page_Main_Menu or AdminMenuSubItem. |
|
118 | - * |
|
119 | - * @since 4.4.0 |
|
120 | - * @deprecated 5.0.0.p |
|
121 | - */ |
|
122 | - protected function _set_menu_map() |
|
123 | - { |
|
124 | - } |
|
125 | - |
|
126 | - |
|
127 | - /** |
|
128 | - * @since 5.0.0.p |
|
129 | - */ |
|
130 | - public function setupLegacyAdminMenuItem() |
|
131 | - { |
|
132 | - // will be overridden by child classes not using new system |
|
133 | - $this->_set_menu_map(); |
|
134 | - } |
|
135 | - |
|
136 | - |
|
137 | - /** |
|
138 | - * Child classes should return an array of properties used to construct the AdminMenuItem |
|
139 | - * |
|
140 | - * @return array |
|
141 | - * @since 5.0.0.p |
|
142 | - */ |
|
143 | - public function getMenuProperties(): array |
|
144 | - { |
|
145 | - return []; |
|
146 | - } |
|
147 | - |
|
148 | - |
|
149 | - /** |
|
150 | - * @param AdminMenuItem $menu |
|
151 | - * @return void |
|
152 | - * @since 5.0.0.p |
|
153 | - */ |
|
154 | - public function setAdminMenu(AdminMenuItem $menu): void |
|
155 | - { |
|
156 | - $this->_menu_map = $menu; |
|
157 | - } |
|
158 | - |
|
159 | - |
|
160 | - /** |
|
161 | - * returns the menu map for this admin page |
|
162 | - * |
|
163 | - * @return AdminMenuItem|null |
|
164 | - * @since 5.0.0.p |
|
165 | - */ |
|
166 | - public function adminMenu(): ?AdminMenuItem |
|
167 | - { |
|
168 | - return $this->_menu_map; |
|
169 | - } |
|
170 | - |
|
171 | - |
|
172 | - /** |
|
173 | - * @param string $wp_page_slug |
|
174 | - * @since 5.0.0.p |
|
175 | - */ |
|
176 | - public function setWpPageSlug(string $wp_page_slug): void |
|
177 | - { |
|
178 | - $this->_wp_page_slug = $wp_page_slug; |
|
179 | - } |
|
180 | - |
|
181 | - |
|
182 | - /** |
|
183 | - * This loads scripts and styles for the EE_Admin system |
|
184 | - * that must be available on ALL WP admin pages (i.e. EE_menu items) |
|
185 | - * |
|
186 | - * @return void |
|
187 | - */ |
|
188 | - public function load_wp_global_scripts_styles() |
|
189 | - { |
|
190 | - wp_register_style( |
|
191 | - 'espresso_admin_base', |
|
192 | - EE_ADMIN_URL . 'assets/ee-admin-base.css', |
|
193 | - ['dashicons'], |
|
194 | - EVENT_ESPRESSO_VERSION |
|
195 | - ); |
|
196 | - wp_register_style( |
|
197 | - 'espresso_menu', |
|
198 | - EE_ADMIN_URL . 'assets/ee-admin-menu.css', |
|
199 | - ['espresso_admin_base'], |
|
200 | - EVENT_ESPRESSO_VERSION |
|
201 | - ); |
|
202 | - wp_enqueue_style('espresso_admin_base'); |
|
203 | - wp_enqueue_style('espresso_menu'); |
|
204 | - } |
|
205 | - |
|
206 | - |
|
207 | - /** |
|
208 | - * this sets default properties (might be overridden in _set_init_properties); |
|
209 | - * |
|
210 | - * @return void |
|
211 | - */ |
|
212 | - private function _set_defaults() |
|
213 | - { |
|
214 | - $this->_file_name = ''; |
|
215 | - $this->_folder_name = ''; |
|
216 | - $this->_wp_page_slug = ''; |
|
217 | - $this->capability = ''; |
|
218 | - $this->_routing = true; |
|
219 | - $this->_load_page = false; |
|
220 | - $this->_files_hooked = []; |
|
221 | - $this->_hook_paths = []; |
|
222 | - } |
|
223 | - |
|
224 | - |
|
225 | - public function setCapability($capability, $menu_slug) |
|
226 | - { |
|
227 | - $this->capability = apply_filters('FHEE_' . $menu_slug . '_capability', $capability); |
|
228 | - } |
|
229 | - |
|
230 | - |
|
231 | - /** |
|
232 | - * @deprecated 5.0.0.p |
|
233 | - */ |
|
234 | - protected function _set_capability() |
|
235 | - { |
|
236 | - if ($this->_menu_map instanceof AdminMenuItem) { |
|
237 | - $this->setCapability($this->_menu_map->capability(), $this->_menu_map->menuSlug()); |
|
238 | - } |
|
239 | - } |
|
240 | - |
|
241 | - |
|
242 | - /** |
|
243 | - * initialize_admin_page |
|
244 | - * This method is what executes the loading of the specific page class for the given dir_name as called by the |
|
245 | - * EE_Admin_Init class. |
|
246 | - * |
|
247 | - * @return void |
|
248 | - * @throws EE_Error |
|
249 | - * @throws ReflectionException |
|
250 | - */ |
|
251 | - public function initialize_admin_page() |
|
252 | - { |
|
253 | - // let's check user access first |
|
254 | - $this->_check_user_access(); |
|
255 | - if (! $this->_loaded_page_object instanceof EE_Admin_Page) { |
|
256 | - return; |
|
257 | - } |
|
258 | - $this->_loaded_page_object->route_admin_request(); |
|
259 | - } |
|
260 | - |
|
261 | - |
|
262 | - /** |
|
263 | - * @param string $wp_page_slug |
|
264 | - * @throws EE_Error |
|
265 | - */ |
|
266 | - public function set_page_dependencies(string $wp_page_slug) |
|
267 | - { |
|
268 | - if (! $this->_load_page) { |
|
269 | - return; |
|
270 | - } |
|
271 | - if (! $this->_loaded_page_object instanceof EE_Admin_Page) { |
|
272 | - $msg[] = esc_html__( |
|
273 | - 'We can\'t load the page because we\'re missing a valid page object that tells us what to load', |
|
274 | - 'event_espresso' |
|
275 | - ); |
|
276 | - $msg[] = $msg[0] . "\r\n" |
|
277 | - . sprintf( |
|
278 | - esc_html__( |
|
279 | - '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', |
|
280 | - 'event_espresso' |
|
281 | - ), |
|
282 | - $this->_file_name, |
|
283 | - $this->_file_name, |
|
284 | - $this->_folder_path . $this->_file_name, |
|
285 | - $this->_menu_map->menuSlug() |
|
286 | - ); |
|
287 | - throw new EE_Error(implode('||', $msg)); |
|
288 | - } |
|
289 | - $this->_loaded_page_object->set_wp_page_slug($wp_page_slug); |
|
290 | - $page_hook = "load-$wp_page_slug"; |
|
291 | - // hook into page load hook so all page specific stuff gets loaded. |
|
292 | - if (! empty($wp_page_slug)) { |
|
293 | - add_action($page_hook, [$this->_loaded_page_object, 'load_page_dependencies']); |
|
294 | - } |
|
295 | - } |
|
296 | - |
|
297 | - |
|
298 | - /** |
|
299 | - * This executes the initial page loads for EE_Admin pages to take care of any ajax or other code needing to run |
|
300 | - * before the load-page... hook. Note, the page loads are happening around the wp_init hook. |
|
301 | - * |
|
302 | - * @return void |
|
303 | - * @throws InvalidArgumentException |
|
304 | - * @throws InvalidDataTypeException |
|
305 | - * @throws InvalidInterfaceException |
|
306 | - * @throws EE_Error |
|
307 | - * @throws ReflectionException |
|
308 | - */ |
|
309 | - public function do_initial_loads() |
|
310 | - { |
|
311 | - // no loading or initializing if menu map is setup incorrectly. |
|
312 | - if (! $this->_menu_map instanceof AdminMenuItem) { |
|
313 | - return; |
|
314 | - } |
|
315 | - $this->_initialize_admin_page(); |
|
316 | - } |
|
317 | - |
|
318 | - |
|
319 | - /** |
|
320 | - * all we're doing here is setting the $_file_name property for later use. |
|
321 | - * |
|
322 | - * @return void |
|
323 | - */ |
|
324 | - private function _set_file_and_folder_name() |
|
325 | - { |
|
326 | - $bt = debug_backtrace(); |
|
327 | - // for more reliable determination of folder name |
|
328 | - // 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) |
|
329 | - $class = get_class($this); |
|
330 | - foreach ($bt as $index => $values) { |
|
331 | - if (isset($values['class']) && $values['class'] == $class) { |
|
332 | - $file_index = $index - 1; |
|
333 | - $this->_folder_name = basename(dirname($bt[ $file_index ]['file'])); |
|
334 | - if (! empty($this->_folder_name)) { |
|
335 | - break; |
|
336 | - } |
|
337 | - } |
|
338 | - } |
|
339 | - $this->_folder_path = EE_ADMIN_PAGES . $this->_folder_name . '/'; |
|
340 | - $this->_file_name = preg_replace('/^ee/', 'EE', $this->_folder_name); |
|
341 | - $this->_file_name = ucwords(str_replace('_', ' ', $this->_file_name)); |
|
342 | - $this->_file_name = str_replace(' ', '_', $this->_file_name); |
|
343 | - } |
|
344 | - |
|
345 | - |
|
346 | - /** |
|
347 | - * This automatically checks if we have a hook class in the loaded child directory. If we DO then we will register |
|
348 | - * it with the appropriate pages. That way all we have to do is make sure the file is named correctly and |
|
349 | - * "dropped" in. Example: if we wanted to set this up for Messages hooking into Events then we would do: |
|
350 | - * events_Messages_Hooks.class.php |
|
351 | - * |
|
352 | - * @param bool $extend This indicates whether we're checking the extend directory for any register_hooks |
|
353 | - * files/classes |
|
354 | - * @return array |
|
355 | - */ |
|
356 | - public function register_hooks(bool $extend = false): array |
|
357 | - { |
|
358 | - // get a list of files in the directory that have the "Hook" in their name an |
|
359 | - // 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. |
|
360 | - if ($extend) { |
|
361 | - $hook_files_glob_path = apply_filters( |
|
362 | - 'FHEE__EE_Admin_Page_Init__register_hooks__hook_files_glob_path__extend', |
|
363 | - EE_CORE_CAF_ADMIN_EXTEND |
|
364 | - . $this->_folder_name |
|
365 | - . '/*' |
|
366 | - . $this->_file_name |
|
367 | - . '_Hooks_Extend.class.php' |
|
368 | - ); |
|
369 | - $this->_hook_paths = $this->_register_hook_files($hook_files_glob_path, $extend); |
|
370 | - } |
|
371 | - // loop through decaf folders |
|
372 | - $hook_files_glob_path = apply_filters( |
|
373 | - 'FHEE__EE_Admin_Page_Init__register_hooks__hook_files_glob_path', |
|
374 | - $this->_folder_path . '*' . $this->_file_name . '_Hooks.class.php' |
|
375 | - ); |
|
376 | - $this->_hook_paths = array_merge( |
|
377 | - $this->_register_hook_files($hook_files_glob_path), |
|
378 | - $this->_hook_paths |
|
379 | - ); // making sure any extended hook paths are later in the array than the core hook paths! |
|
380 | - return $this->_hook_paths; |
|
381 | - } |
|
382 | - |
|
383 | - |
|
384 | - protected function _register_hook_files($hook_files_glob_path, $extend = false): array |
|
385 | - { |
|
386 | - $hook_paths = glob($hook_files_glob_path); |
|
387 | - if (empty($hook_paths)) { |
|
388 | - return []; |
|
389 | - } |
|
390 | - foreach ($hook_paths as $file) { |
|
391 | - // lets get the linked admin. |
|
392 | - $hook_file = $extend |
|
393 | - ? str_replace(EE_CORE_CAF_ADMIN_EXTEND . $this->_folder_name . '/', '', $file) |
|
394 | - : str_replace($this->_folder_path, '', $file); |
|
395 | - $replace = $extend |
|
396 | - ? '_' . $this->_file_name . '_Hooks_Extend.class.php' |
|
397 | - : '_' . $this->_file_name . '_Hooks.class.php'; |
|
398 | - $rel_admin = str_replace($replace, '', $hook_file); |
|
399 | - $rel_admin = strtolower($rel_admin); |
|
400 | - // make sure we haven't already got a hook setup for this page path |
|
401 | - if (in_array($rel_admin, $this->_files_hooked)) { |
|
402 | - continue; |
|
403 | - } |
|
404 | - require_once $file; |
|
405 | - $this->hook_file = $hook_file; |
|
406 | - $rel_admin_hook = 'FHEE_do_other_page_hooks_' . $rel_admin; |
|
407 | - add_filter($rel_admin_hook, [$this, 'load_admin_hook']); |
|
408 | - $this->_files_hooked[] = $rel_admin; |
|
409 | - } |
|
410 | - return $hook_paths; |
|
411 | - } |
|
412 | - |
|
413 | - |
|
414 | - public function load_admin_hook($registered_pages) |
|
415 | - { |
|
416 | - return array_merge((array) $this->hook_file, $registered_pages); |
|
417 | - } |
|
418 | - |
|
419 | - |
|
420 | - /** |
|
421 | - * _initialize_admin_page |
|
422 | - * |
|
423 | - * @throws EE_Error |
|
424 | - * @throws ReflectionException |
|
425 | - * @see initialize_admin_page() for info |
|
426 | - */ |
|
427 | - protected function _initialize_admin_page() |
|
428 | - { |
|
429 | - // JUST CHECK WE'RE ON RIGHT PAGE. |
|
430 | - $page = $this->request->getRequestParam('page'); |
|
431 | - $page = $this->request->getRequestParam('current_page', $page); |
|
432 | - $menu_slug = $this->_menu_map->menuSlug(); |
|
433 | - |
|
434 | - // leaving the following in for the time being |
|
435 | - // because not sure if preventing multiple admin page loading will result in bad things happening |
|
436 | - $darren_logic = false; // true false |
|
437 | - $not_the_droids_you_are_looking_for = $darren_logic |
|
438 | - ? $this->_routing && ($page === '' || $page !== $menu_slug) |
|
439 | - : $page === '' || $page !== $menu_slug; |
|
440 | - if ($not_the_droids_you_are_looking_for) { |
|
441 | - // not on the right page so let's get out. |
|
442 | - return; |
|
443 | - } |
|
444 | - $this->_load_page = true; |
|
445 | - |
|
446 | - // we don't need to do a page_request check here because it's only called via WP menu system. |
|
447 | - $admin_page = $this->_file_name . '_Admin_Page'; |
|
448 | - $hook_suffix = "{$menu_slug}_$admin_page"; |
|
449 | - $admin_page = apply_filters( |
|
450 | - "FHEE__EE_Admin_Page_Init___initialize_admin_page__admin_page__$hook_suffix", |
|
451 | - $admin_page |
|
452 | - ); |
|
453 | - if (empty($admin_page)) { |
|
454 | - return; |
|
455 | - } |
|
456 | - // define requested admin page class name then load the file and instantiate |
|
457 | - $path_to_file = str_replace(['\\', '/'], '/', $this->_folder_path . $admin_page . '.core.php'); |
|
458 | - // so if the file would be in EE_ADMIN/attendees/Attendee_Admin_Page.core.php, the filter would be: |
|
459 | - // FHEE__EE_Admin_Page_Init___initialize_admin_page__path_to_file__attendees_Attendee_Admin_Page |
|
460 | - $path_to_file = apply_filters( |
|
461 | - "FHEE__EE_Admin_Page_Init___initialize_admin_page__path_to_file__$hook_suffix", |
|
462 | - $path_to_file |
|
463 | - ); |
|
464 | - if (! is_readable($path_to_file)) { |
|
465 | - return; |
|
466 | - } |
|
467 | - // This is a place where EE plugins can hook in to make sure their own files are required in the appropriate place |
|
468 | - do_action('AHEE__EE_Admin_Page___initialize_admin_page__before_initialization'); |
|
469 | - do_action("AHEE__EE_Admin_Page___initialize_admin_page__before_initialization_$menu_slug"); |
|
470 | - require_once($path_to_file); |
|
471 | - $this->_loaded_page_object = $this->loader->getShared($admin_page, [$this->_routing]); |
|
472 | - $this->_loaded_page_object->initializePage(); |
|
473 | - |
|
474 | - do_action('AHEE__EE_Admin_Page___initialize_admin_page__after_initialization'); |
|
475 | - do_action("AHEE__EE_Admin_Page___initialize_admin_page__after_initialization_$menu_slug"); |
|
476 | - } |
|
477 | - |
|
478 | - |
|
479 | - public function get_admin_page_name(): string |
|
480 | - { |
|
481 | - return $this->_file_name . '_Admin_Page'; |
|
482 | - } |
|
483 | - |
|
484 | - |
|
485 | - /** |
|
486 | - * @return EE_Admin_Page|null |
|
487 | - */ |
|
488 | - public function loaded_page_object(): ?EE_Admin_Page |
|
489 | - { |
|
490 | - return $this->_loaded_page_object; |
|
491 | - } |
|
492 | - |
|
493 | - |
|
494 | - /** |
|
495 | - * _check_user_access |
|
496 | - * verifies user access for this admin page. If no user access is available then let's gracefully exit with a |
|
497 | - * WordPress die message. |
|
498 | - * |
|
499 | - * @return void wp_die if fail |
|
500 | - */ |
|
501 | - private function _check_user_access() |
|
502 | - { |
|
503 | - if (! $this->_menu_map->currentUserHasAccess()) { |
|
504 | - wp_die( |
|
505 | - esc_html__('You don\'t have access to this page.', 'event_espresso'), |
|
506 | - '', |
|
507 | - ['back_link' => true] |
|
508 | - ); |
|
509 | - } |
|
510 | - } |
|
28 | + protected ?LoaderInterface $loader = null; |
|
29 | + |
|
30 | + protected ?RequestInterface $request = null; |
|
31 | + |
|
32 | + private bool $_load_page = false; |
|
33 | + |
|
34 | + protected bool $_routing = false; |
|
35 | + |
|
36 | + /** |
|
37 | + * Menu map has a capability. However, this allows admin pages to have separate capability requirements for menus |
|
38 | + * and accessing pages. If capability is NOT set, then it defaults to the menu_map capability. |
|
39 | + * |
|
40 | + * @var string |
|
41 | + */ |
|
42 | + public string $capability = ''; |
|
43 | + |
|
44 | + /** |
|
45 | + * identity properties (set in _set_defaults and _set_init_properties) |
|
46 | + */ |
|
47 | + public string $label = ''; |
|
48 | + |
|
49 | + protected string $_file_name = ''; |
|
50 | + |
|
51 | + protected string $_folder_name = ''; |
|
52 | + |
|
53 | + protected string $_folder_path = ''; |
|
54 | + |
|
55 | + protected string $_wp_page_slug = ''; |
|
56 | + |
|
57 | + public string $hook_file = ''; |
|
58 | + |
|
59 | + public string $menu_slug = ''; |
|
60 | + |
|
61 | + /** |
|
62 | + * @deprecated |
|
63 | + */ |
|
64 | + public string $menu_label = ''; |
|
65 | + |
|
66 | + protected array $_files_hooked = []; |
|
67 | + |
|
68 | + protected array $_hook_paths = []; |
|
69 | + |
|
70 | + |
|
71 | + /** |
|
72 | + * @throws InvalidArgumentException |
|
73 | + * @throws InvalidDataTypeException |
|
74 | + * @throws InvalidInterfaceException |
|
75 | + */ |
|
76 | + public function __construct(RequestInterface $request = null) |
|
77 | + { |
|
78 | + $this->loader = LoaderFactory::getLoader(); |
|
79 | + $this->request = $request instanceof RequestInterface |
|
80 | + ? $request |
|
81 | + : $this->loader->getShared(RequestInterface::class); |
|
82 | + // set global defaults |
|
83 | + $this->_set_defaults(); |
|
84 | + // set properties that are always available with objects. |
|
85 | + $this->_set_init_properties(); |
|
86 | + // global styles/scripts across all wp admin pages |
|
87 | + add_action('admin_enqueue_scripts', [$this, 'load_wp_global_scripts_styles'], 5); |
|
88 | + // load initial stuff. |
|
89 | + $this->_set_file_and_folder_name(); |
|
90 | + } |
|
91 | + |
|
92 | + |
|
93 | + /** |
|
94 | + * _set_init_properties |
|
95 | + * Child classes use to set the following properties: |
|
96 | + * $label |
|
97 | + * |
|
98 | + * @abstract |
|
99 | + * @return void |
|
100 | + */ |
|
101 | + abstract protected function _set_init_properties(); |
|
102 | + |
|
103 | + |
|
104 | + /** |
|
105 | + * @return AdminMenuItem|null |
|
106 | + * @since 4.4.0 |
|
107 | + * @deprecated 5.0.0.p |
|
108 | + */ |
|
109 | + public function get_menu_map() |
|
110 | + { |
|
111 | + return $this->adminMenu(); |
|
112 | + } |
|
113 | + |
|
114 | + |
|
115 | + /** |
|
116 | + * _set_menu_map is a function that child classes use to set the menu_map property (which should be an instance of |
|
117 | + * EE_Admin_Page_Menu_Map. Their menu can either be EE_Admin_Page_Main_Menu or AdminMenuSubItem. |
|
118 | + * |
|
119 | + * @since 4.4.0 |
|
120 | + * @deprecated 5.0.0.p |
|
121 | + */ |
|
122 | + protected function _set_menu_map() |
|
123 | + { |
|
124 | + } |
|
125 | + |
|
126 | + |
|
127 | + /** |
|
128 | + * @since 5.0.0.p |
|
129 | + */ |
|
130 | + public function setupLegacyAdminMenuItem() |
|
131 | + { |
|
132 | + // will be overridden by child classes not using new system |
|
133 | + $this->_set_menu_map(); |
|
134 | + } |
|
135 | + |
|
136 | + |
|
137 | + /** |
|
138 | + * Child classes should return an array of properties used to construct the AdminMenuItem |
|
139 | + * |
|
140 | + * @return array |
|
141 | + * @since 5.0.0.p |
|
142 | + */ |
|
143 | + public function getMenuProperties(): array |
|
144 | + { |
|
145 | + return []; |
|
146 | + } |
|
147 | + |
|
148 | + |
|
149 | + /** |
|
150 | + * @param AdminMenuItem $menu |
|
151 | + * @return void |
|
152 | + * @since 5.0.0.p |
|
153 | + */ |
|
154 | + public function setAdminMenu(AdminMenuItem $menu): void |
|
155 | + { |
|
156 | + $this->_menu_map = $menu; |
|
157 | + } |
|
158 | + |
|
159 | + |
|
160 | + /** |
|
161 | + * returns the menu map for this admin page |
|
162 | + * |
|
163 | + * @return AdminMenuItem|null |
|
164 | + * @since 5.0.0.p |
|
165 | + */ |
|
166 | + public function adminMenu(): ?AdminMenuItem |
|
167 | + { |
|
168 | + return $this->_menu_map; |
|
169 | + } |
|
170 | + |
|
171 | + |
|
172 | + /** |
|
173 | + * @param string $wp_page_slug |
|
174 | + * @since 5.0.0.p |
|
175 | + */ |
|
176 | + public function setWpPageSlug(string $wp_page_slug): void |
|
177 | + { |
|
178 | + $this->_wp_page_slug = $wp_page_slug; |
|
179 | + } |
|
180 | + |
|
181 | + |
|
182 | + /** |
|
183 | + * This loads scripts and styles for the EE_Admin system |
|
184 | + * that must be available on ALL WP admin pages (i.e. EE_menu items) |
|
185 | + * |
|
186 | + * @return void |
|
187 | + */ |
|
188 | + public function load_wp_global_scripts_styles() |
|
189 | + { |
|
190 | + wp_register_style( |
|
191 | + 'espresso_admin_base', |
|
192 | + EE_ADMIN_URL . 'assets/ee-admin-base.css', |
|
193 | + ['dashicons'], |
|
194 | + EVENT_ESPRESSO_VERSION |
|
195 | + ); |
|
196 | + wp_register_style( |
|
197 | + 'espresso_menu', |
|
198 | + EE_ADMIN_URL . 'assets/ee-admin-menu.css', |
|
199 | + ['espresso_admin_base'], |
|
200 | + EVENT_ESPRESSO_VERSION |
|
201 | + ); |
|
202 | + wp_enqueue_style('espresso_admin_base'); |
|
203 | + wp_enqueue_style('espresso_menu'); |
|
204 | + } |
|
205 | + |
|
206 | + |
|
207 | + /** |
|
208 | + * this sets default properties (might be overridden in _set_init_properties); |
|
209 | + * |
|
210 | + * @return void |
|
211 | + */ |
|
212 | + private function _set_defaults() |
|
213 | + { |
|
214 | + $this->_file_name = ''; |
|
215 | + $this->_folder_name = ''; |
|
216 | + $this->_wp_page_slug = ''; |
|
217 | + $this->capability = ''; |
|
218 | + $this->_routing = true; |
|
219 | + $this->_load_page = false; |
|
220 | + $this->_files_hooked = []; |
|
221 | + $this->_hook_paths = []; |
|
222 | + } |
|
223 | + |
|
224 | + |
|
225 | + public function setCapability($capability, $menu_slug) |
|
226 | + { |
|
227 | + $this->capability = apply_filters('FHEE_' . $menu_slug . '_capability', $capability); |
|
228 | + } |
|
229 | + |
|
230 | + |
|
231 | + /** |
|
232 | + * @deprecated 5.0.0.p |
|
233 | + */ |
|
234 | + protected function _set_capability() |
|
235 | + { |
|
236 | + if ($this->_menu_map instanceof AdminMenuItem) { |
|
237 | + $this->setCapability($this->_menu_map->capability(), $this->_menu_map->menuSlug()); |
|
238 | + } |
|
239 | + } |
|
240 | + |
|
241 | + |
|
242 | + /** |
|
243 | + * initialize_admin_page |
|
244 | + * This method is what executes the loading of the specific page class for the given dir_name as called by the |
|
245 | + * EE_Admin_Init class. |
|
246 | + * |
|
247 | + * @return void |
|
248 | + * @throws EE_Error |
|
249 | + * @throws ReflectionException |
|
250 | + */ |
|
251 | + public function initialize_admin_page() |
|
252 | + { |
|
253 | + // let's check user access first |
|
254 | + $this->_check_user_access(); |
|
255 | + if (! $this->_loaded_page_object instanceof EE_Admin_Page) { |
|
256 | + return; |
|
257 | + } |
|
258 | + $this->_loaded_page_object->route_admin_request(); |
|
259 | + } |
|
260 | + |
|
261 | + |
|
262 | + /** |
|
263 | + * @param string $wp_page_slug |
|
264 | + * @throws EE_Error |
|
265 | + */ |
|
266 | + public function set_page_dependencies(string $wp_page_slug) |
|
267 | + { |
|
268 | + if (! $this->_load_page) { |
|
269 | + return; |
|
270 | + } |
|
271 | + if (! $this->_loaded_page_object instanceof EE_Admin_Page) { |
|
272 | + $msg[] = esc_html__( |
|
273 | + 'We can\'t load the page because we\'re missing a valid page object that tells us what to load', |
|
274 | + 'event_espresso' |
|
275 | + ); |
|
276 | + $msg[] = $msg[0] . "\r\n" |
|
277 | + . sprintf( |
|
278 | + esc_html__( |
|
279 | + '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', |
|
280 | + 'event_espresso' |
|
281 | + ), |
|
282 | + $this->_file_name, |
|
283 | + $this->_file_name, |
|
284 | + $this->_folder_path . $this->_file_name, |
|
285 | + $this->_menu_map->menuSlug() |
|
286 | + ); |
|
287 | + throw new EE_Error(implode('||', $msg)); |
|
288 | + } |
|
289 | + $this->_loaded_page_object->set_wp_page_slug($wp_page_slug); |
|
290 | + $page_hook = "load-$wp_page_slug"; |
|
291 | + // hook into page load hook so all page specific stuff gets loaded. |
|
292 | + if (! empty($wp_page_slug)) { |
|
293 | + add_action($page_hook, [$this->_loaded_page_object, 'load_page_dependencies']); |
|
294 | + } |
|
295 | + } |
|
296 | + |
|
297 | + |
|
298 | + /** |
|
299 | + * This executes the initial page loads for EE_Admin pages to take care of any ajax or other code needing to run |
|
300 | + * before the load-page... hook. Note, the page loads are happening around the wp_init hook. |
|
301 | + * |
|
302 | + * @return void |
|
303 | + * @throws InvalidArgumentException |
|
304 | + * @throws InvalidDataTypeException |
|
305 | + * @throws InvalidInterfaceException |
|
306 | + * @throws EE_Error |
|
307 | + * @throws ReflectionException |
|
308 | + */ |
|
309 | + public function do_initial_loads() |
|
310 | + { |
|
311 | + // no loading or initializing if menu map is setup incorrectly. |
|
312 | + if (! $this->_menu_map instanceof AdminMenuItem) { |
|
313 | + return; |
|
314 | + } |
|
315 | + $this->_initialize_admin_page(); |
|
316 | + } |
|
317 | + |
|
318 | + |
|
319 | + /** |
|
320 | + * all we're doing here is setting the $_file_name property for later use. |
|
321 | + * |
|
322 | + * @return void |
|
323 | + */ |
|
324 | + private function _set_file_and_folder_name() |
|
325 | + { |
|
326 | + $bt = debug_backtrace(); |
|
327 | + // for more reliable determination of folder name |
|
328 | + // 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) |
|
329 | + $class = get_class($this); |
|
330 | + foreach ($bt as $index => $values) { |
|
331 | + if (isset($values['class']) && $values['class'] == $class) { |
|
332 | + $file_index = $index - 1; |
|
333 | + $this->_folder_name = basename(dirname($bt[ $file_index ]['file'])); |
|
334 | + if (! empty($this->_folder_name)) { |
|
335 | + break; |
|
336 | + } |
|
337 | + } |
|
338 | + } |
|
339 | + $this->_folder_path = EE_ADMIN_PAGES . $this->_folder_name . '/'; |
|
340 | + $this->_file_name = preg_replace('/^ee/', 'EE', $this->_folder_name); |
|
341 | + $this->_file_name = ucwords(str_replace('_', ' ', $this->_file_name)); |
|
342 | + $this->_file_name = str_replace(' ', '_', $this->_file_name); |
|
343 | + } |
|
344 | + |
|
345 | + |
|
346 | + /** |
|
347 | + * This automatically checks if we have a hook class in the loaded child directory. If we DO then we will register |
|
348 | + * it with the appropriate pages. That way all we have to do is make sure the file is named correctly and |
|
349 | + * "dropped" in. Example: if we wanted to set this up for Messages hooking into Events then we would do: |
|
350 | + * events_Messages_Hooks.class.php |
|
351 | + * |
|
352 | + * @param bool $extend This indicates whether we're checking the extend directory for any register_hooks |
|
353 | + * files/classes |
|
354 | + * @return array |
|
355 | + */ |
|
356 | + public function register_hooks(bool $extend = false): array |
|
357 | + { |
|
358 | + // get a list of files in the directory that have the "Hook" in their name an |
|
359 | + // 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. |
|
360 | + if ($extend) { |
|
361 | + $hook_files_glob_path = apply_filters( |
|
362 | + 'FHEE__EE_Admin_Page_Init__register_hooks__hook_files_glob_path__extend', |
|
363 | + EE_CORE_CAF_ADMIN_EXTEND |
|
364 | + . $this->_folder_name |
|
365 | + . '/*' |
|
366 | + . $this->_file_name |
|
367 | + . '_Hooks_Extend.class.php' |
|
368 | + ); |
|
369 | + $this->_hook_paths = $this->_register_hook_files($hook_files_glob_path, $extend); |
|
370 | + } |
|
371 | + // loop through decaf folders |
|
372 | + $hook_files_glob_path = apply_filters( |
|
373 | + 'FHEE__EE_Admin_Page_Init__register_hooks__hook_files_glob_path', |
|
374 | + $this->_folder_path . '*' . $this->_file_name . '_Hooks.class.php' |
|
375 | + ); |
|
376 | + $this->_hook_paths = array_merge( |
|
377 | + $this->_register_hook_files($hook_files_glob_path), |
|
378 | + $this->_hook_paths |
|
379 | + ); // making sure any extended hook paths are later in the array than the core hook paths! |
|
380 | + return $this->_hook_paths; |
|
381 | + } |
|
382 | + |
|
383 | + |
|
384 | + protected function _register_hook_files($hook_files_glob_path, $extend = false): array |
|
385 | + { |
|
386 | + $hook_paths = glob($hook_files_glob_path); |
|
387 | + if (empty($hook_paths)) { |
|
388 | + return []; |
|
389 | + } |
|
390 | + foreach ($hook_paths as $file) { |
|
391 | + // lets get the linked admin. |
|
392 | + $hook_file = $extend |
|
393 | + ? str_replace(EE_CORE_CAF_ADMIN_EXTEND . $this->_folder_name . '/', '', $file) |
|
394 | + : str_replace($this->_folder_path, '', $file); |
|
395 | + $replace = $extend |
|
396 | + ? '_' . $this->_file_name . '_Hooks_Extend.class.php' |
|
397 | + : '_' . $this->_file_name . '_Hooks.class.php'; |
|
398 | + $rel_admin = str_replace($replace, '', $hook_file); |
|
399 | + $rel_admin = strtolower($rel_admin); |
|
400 | + // make sure we haven't already got a hook setup for this page path |
|
401 | + if (in_array($rel_admin, $this->_files_hooked)) { |
|
402 | + continue; |
|
403 | + } |
|
404 | + require_once $file; |
|
405 | + $this->hook_file = $hook_file; |
|
406 | + $rel_admin_hook = 'FHEE_do_other_page_hooks_' . $rel_admin; |
|
407 | + add_filter($rel_admin_hook, [$this, 'load_admin_hook']); |
|
408 | + $this->_files_hooked[] = $rel_admin; |
|
409 | + } |
|
410 | + return $hook_paths; |
|
411 | + } |
|
412 | + |
|
413 | + |
|
414 | + public function load_admin_hook($registered_pages) |
|
415 | + { |
|
416 | + return array_merge((array) $this->hook_file, $registered_pages); |
|
417 | + } |
|
418 | + |
|
419 | + |
|
420 | + /** |
|
421 | + * _initialize_admin_page |
|
422 | + * |
|
423 | + * @throws EE_Error |
|
424 | + * @throws ReflectionException |
|
425 | + * @see initialize_admin_page() for info |
|
426 | + */ |
|
427 | + protected function _initialize_admin_page() |
|
428 | + { |
|
429 | + // JUST CHECK WE'RE ON RIGHT PAGE. |
|
430 | + $page = $this->request->getRequestParam('page'); |
|
431 | + $page = $this->request->getRequestParam('current_page', $page); |
|
432 | + $menu_slug = $this->_menu_map->menuSlug(); |
|
433 | + |
|
434 | + // leaving the following in for the time being |
|
435 | + // because not sure if preventing multiple admin page loading will result in bad things happening |
|
436 | + $darren_logic = false; // true false |
|
437 | + $not_the_droids_you_are_looking_for = $darren_logic |
|
438 | + ? $this->_routing && ($page === '' || $page !== $menu_slug) |
|
439 | + : $page === '' || $page !== $menu_slug; |
|
440 | + if ($not_the_droids_you_are_looking_for) { |
|
441 | + // not on the right page so let's get out. |
|
442 | + return; |
|
443 | + } |
|
444 | + $this->_load_page = true; |
|
445 | + |
|
446 | + // we don't need to do a page_request check here because it's only called via WP menu system. |
|
447 | + $admin_page = $this->_file_name . '_Admin_Page'; |
|
448 | + $hook_suffix = "{$menu_slug}_$admin_page"; |
|
449 | + $admin_page = apply_filters( |
|
450 | + "FHEE__EE_Admin_Page_Init___initialize_admin_page__admin_page__$hook_suffix", |
|
451 | + $admin_page |
|
452 | + ); |
|
453 | + if (empty($admin_page)) { |
|
454 | + return; |
|
455 | + } |
|
456 | + // define requested admin page class name then load the file and instantiate |
|
457 | + $path_to_file = str_replace(['\\', '/'], '/', $this->_folder_path . $admin_page . '.core.php'); |
|
458 | + // so if the file would be in EE_ADMIN/attendees/Attendee_Admin_Page.core.php, the filter would be: |
|
459 | + // FHEE__EE_Admin_Page_Init___initialize_admin_page__path_to_file__attendees_Attendee_Admin_Page |
|
460 | + $path_to_file = apply_filters( |
|
461 | + "FHEE__EE_Admin_Page_Init___initialize_admin_page__path_to_file__$hook_suffix", |
|
462 | + $path_to_file |
|
463 | + ); |
|
464 | + if (! is_readable($path_to_file)) { |
|
465 | + return; |
|
466 | + } |
|
467 | + // This is a place where EE plugins can hook in to make sure their own files are required in the appropriate place |
|
468 | + do_action('AHEE__EE_Admin_Page___initialize_admin_page__before_initialization'); |
|
469 | + do_action("AHEE__EE_Admin_Page___initialize_admin_page__before_initialization_$menu_slug"); |
|
470 | + require_once($path_to_file); |
|
471 | + $this->_loaded_page_object = $this->loader->getShared($admin_page, [$this->_routing]); |
|
472 | + $this->_loaded_page_object->initializePage(); |
|
473 | + |
|
474 | + do_action('AHEE__EE_Admin_Page___initialize_admin_page__after_initialization'); |
|
475 | + do_action("AHEE__EE_Admin_Page___initialize_admin_page__after_initialization_$menu_slug"); |
|
476 | + } |
|
477 | + |
|
478 | + |
|
479 | + public function get_admin_page_name(): string |
|
480 | + { |
|
481 | + return $this->_file_name . '_Admin_Page'; |
|
482 | + } |
|
483 | + |
|
484 | + |
|
485 | + /** |
|
486 | + * @return EE_Admin_Page|null |
|
487 | + */ |
|
488 | + public function loaded_page_object(): ?EE_Admin_Page |
|
489 | + { |
|
490 | + return $this->_loaded_page_object; |
|
491 | + } |
|
492 | + |
|
493 | + |
|
494 | + /** |
|
495 | + * _check_user_access |
|
496 | + * verifies user access for this admin page. If no user access is available then let's gracefully exit with a |
|
497 | + * WordPress die message. |
|
498 | + * |
|
499 | + * @return void wp_die if fail |
|
500 | + */ |
|
501 | + private function _check_user_access() |
|
502 | + { |
|
503 | + if (! $this->_menu_map->currentUserHasAccess()) { |
|
504 | + wp_die( |
|
505 | + esc_html__('You don\'t have access to this page.', 'event_espresso'), |
|
506 | + '', |
|
507 | + ['back_link' => true] |
|
508 | + ); |
|
509 | + } |
|
510 | + } |
|
511 | 511 | } |
@@ -25,13 +25,13 @@ discard block |
||
25 | 25 | |
26 | 26 | protected ?EE_Admin_Page $_loaded_page_object = null; |
27 | 27 | |
28 | - protected ?LoaderInterface $loader = null; |
|
28 | + protected ?LoaderInterface $loader = null; |
|
29 | 29 | |
30 | - protected ?RequestInterface $request = null; |
|
30 | + protected ?RequestInterface $request = null; |
|
31 | 31 | |
32 | - private bool $_load_page = false; |
|
32 | + private bool $_load_page = false; |
|
33 | 33 | |
34 | - protected bool $_routing = false; |
|
34 | + protected bool $_routing = false; |
|
35 | 35 | |
36 | 36 | /** |
37 | 37 | * Menu map has a capability. However, this allows admin pages to have separate capability requirements for menus |
@@ -44,7 +44,7 @@ discard block |
||
44 | 44 | /** |
45 | 45 | * identity properties (set in _set_defaults and _set_init_properties) |
46 | 46 | */ |
47 | - public string $label = ''; |
|
47 | + public string $label = ''; |
|
48 | 48 | |
49 | 49 | protected string $_file_name = ''; |
50 | 50 | |
@@ -61,7 +61,7 @@ discard block |
||
61 | 61 | /** |
62 | 62 | * @deprecated |
63 | 63 | */ |
64 | - public string $menu_label = ''; |
|
64 | + public string $menu_label = ''; |
|
65 | 65 | |
66 | 66 | protected array $_files_hooked = []; |
67 | 67 | |
@@ -189,13 +189,13 @@ discard block |
||
189 | 189 | { |
190 | 190 | wp_register_style( |
191 | 191 | 'espresso_admin_base', |
192 | - EE_ADMIN_URL . 'assets/ee-admin-base.css', |
|
192 | + EE_ADMIN_URL.'assets/ee-admin-base.css', |
|
193 | 193 | ['dashicons'], |
194 | 194 | EVENT_ESPRESSO_VERSION |
195 | 195 | ); |
196 | 196 | wp_register_style( |
197 | 197 | 'espresso_menu', |
198 | - EE_ADMIN_URL . 'assets/ee-admin-menu.css', |
|
198 | + EE_ADMIN_URL.'assets/ee-admin-menu.css', |
|
199 | 199 | ['espresso_admin_base'], |
200 | 200 | EVENT_ESPRESSO_VERSION |
201 | 201 | ); |
@@ -224,7 +224,7 @@ discard block |
||
224 | 224 | |
225 | 225 | public function setCapability($capability, $menu_slug) |
226 | 226 | { |
227 | - $this->capability = apply_filters('FHEE_' . $menu_slug . '_capability', $capability); |
|
227 | + $this->capability = apply_filters('FHEE_'.$menu_slug.'_capability', $capability); |
|
228 | 228 | } |
229 | 229 | |
230 | 230 | |
@@ -252,7 +252,7 @@ discard block |
||
252 | 252 | { |
253 | 253 | // let's check user access first |
254 | 254 | $this->_check_user_access(); |
255 | - if (! $this->_loaded_page_object instanceof EE_Admin_Page) { |
|
255 | + if ( ! $this->_loaded_page_object instanceof EE_Admin_Page) { |
|
256 | 256 | return; |
257 | 257 | } |
258 | 258 | $this->_loaded_page_object->route_admin_request(); |
@@ -265,15 +265,15 @@ discard block |
||
265 | 265 | */ |
266 | 266 | public function set_page_dependencies(string $wp_page_slug) |
267 | 267 | { |
268 | - if (! $this->_load_page) { |
|
268 | + if ( ! $this->_load_page) { |
|
269 | 269 | return; |
270 | 270 | } |
271 | - if (! $this->_loaded_page_object instanceof EE_Admin_Page) { |
|
271 | + if ( ! $this->_loaded_page_object instanceof EE_Admin_Page) { |
|
272 | 272 | $msg[] = esc_html__( |
273 | 273 | 'We can\'t load the page because we\'re missing a valid page object that tells us what to load', |
274 | 274 | 'event_espresso' |
275 | 275 | ); |
276 | - $msg[] = $msg[0] . "\r\n" |
|
276 | + $msg[] = $msg[0]."\r\n" |
|
277 | 277 | . sprintf( |
278 | 278 | esc_html__( |
279 | 279 | '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', |
@@ -281,7 +281,7 @@ discard block |
||
281 | 281 | ), |
282 | 282 | $this->_file_name, |
283 | 283 | $this->_file_name, |
284 | - $this->_folder_path . $this->_file_name, |
|
284 | + $this->_folder_path.$this->_file_name, |
|
285 | 285 | $this->_menu_map->menuSlug() |
286 | 286 | ); |
287 | 287 | throw new EE_Error(implode('||', $msg)); |
@@ -289,7 +289,7 @@ discard block |
||
289 | 289 | $this->_loaded_page_object->set_wp_page_slug($wp_page_slug); |
290 | 290 | $page_hook = "load-$wp_page_slug"; |
291 | 291 | // hook into page load hook so all page specific stuff gets loaded. |
292 | - if (! empty($wp_page_slug)) { |
|
292 | + if ( ! empty($wp_page_slug)) { |
|
293 | 293 | add_action($page_hook, [$this->_loaded_page_object, 'load_page_dependencies']); |
294 | 294 | } |
295 | 295 | } |
@@ -309,7 +309,7 @@ discard block |
||
309 | 309 | public function do_initial_loads() |
310 | 310 | { |
311 | 311 | // no loading or initializing if menu map is setup incorrectly. |
312 | - if (! $this->_menu_map instanceof AdminMenuItem) { |
|
312 | + if ( ! $this->_menu_map instanceof AdminMenuItem) { |
|
313 | 313 | return; |
314 | 314 | } |
315 | 315 | $this->_initialize_admin_page(); |
@@ -330,13 +330,13 @@ discard block |
||
330 | 330 | foreach ($bt as $index => $values) { |
331 | 331 | if (isset($values['class']) && $values['class'] == $class) { |
332 | 332 | $file_index = $index - 1; |
333 | - $this->_folder_name = basename(dirname($bt[ $file_index ]['file'])); |
|
334 | - if (! empty($this->_folder_name)) { |
|
333 | + $this->_folder_name = basename(dirname($bt[$file_index]['file'])); |
|
334 | + if ( ! empty($this->_folder_name)) { |
|
335 | 335 | break; |
336 | 336 | } |
337 | 337 | } |
338 | 338 | } |
339 | - $this->_folder_path = EE_ADMIN_PAGES . $this->_folder_name . '/'; |
|
339 | + $this->_folder_path = EE_ADMIN_PAGES.$this->_folder_name.'/'; |
|
340 | 340 | $this->_file_name = preg_replace('/^ee/', 'EE', $this->_folder_name); |
341 | 341 | $this->_file_name = ucwords(str_replace('_', ' ', $this->_file_name)); |
342 | 342 | $this->_file_name = str_replace(' ', '_', $this->_file_name); |
@@ -366,17 +366,17 @@ discard block |
||
366 | 366 | . $this->_file_name |
367 | 367 | . '_Hooks_Extend.class.php' |
368 | 368 | ); |
369 | - $this->_hook_paths = $this->_register_hook_files($hook_files_glob_path, $extend); |
|
369 | + $this->_hook_paths = $this->_register_hook_files($hook_files_glob_path, $extend); |
|
370 | 370 | } |
371 | 371 | // loop through decaf folders |
372 | 372 | $hook_files_glob_path = apply_filters( |
373 | 373 | 'FHEE__EE_Admin_Page_Init__register_hooks__hook_files_glob_path', |
374 | - $this->_folder_path . '*' . $this->_file_name . '_Hooks.class.php' |
|
374 | + $this->_folder_path.'*'.$this->_file_name.'_Hooks.class.php' |
|
375 | 375 | ); |
376 | - $this->_hook_paths = array_merge( |
|
376 | + $this->_hook_paths = array_merge( |
|
377 | 377 | $this->_register_hook_files($hook_files_glob_path), |
378 | 378 | $this->_hook_paths |
379 | - ); // making sure any extended hook paths are later in the array than the core hook paths! |
|
379 | + ); // making sure any extended hook paths are later in the array than the core hook paths! |
|
380 | 380 | return $this->_hook_paths; |
381 | 381 | } |
382 | 382 | |
@@ -390,11 +390,11 @@ discard block |
||
390 | 390 | foreach ($hook_paths as $file) { |
391 | 391 | // lets get the linked admin. |
392 | 392 | $hook_file = $extend |
393 | - ? str_replace(EE_CORE_CAF_ADMIN_EXTEND . $this->_folder_name . '/', '', $file) |
|
393 | + ? str_replace(EE_CORE_CAF_ADMIN_EXTEND.$this->_folder_name.'/', '', $file) |
|
394 | 394 | : str_replace($this->_folder_path, '', $file); |
395 | 395 | $replace = $extend |
396 | - ? '_' . $this->_file_name . '_Hooks_Extend.class.php' |
|
397 | - : '_' . $this->_file_name . '_Hooks.class.php'; |
|
396 | + ? '_'.$this->_file_name.'_Hooks_Extend.class.php' |
|
397 | + : '_'.$this->_file_name.'_Hooks.class.php'; |
|
398 | 398 | $rel_admin = str_replace($replace, '', $hook_file); |
399 | 399 | $rel_admin = strtolower($rel_admin); |
400 | 400 | // make sure we haven't already got a hook setup for this page path |
@@ -403,7 +403,7 @@ discard block |
||
403 | 403 | } |
404 | 404 | require_once $file; |
405 | 405 | $this->hook_file = $hook_file; |
406 | - $rel_admin_hook = 'FHEE_do_other_page_hooks_' . $rel_admin; |
|
406 | + $rel_admin_hook = 'FHEE_do_other_page_hooks_'.$rel_admin; |
|
407 | 407 | add_filter($rel_admin_hook, [$this, 'load_admin_hook']); |
408 | 408 | $this->_files_hooked[] = $rel_admin; |
409 | 409 | } |
@@ -433,7 +433,7 @@ discard block |
||
433 | 433 | |
434 | 434 | // leaving the following in for the time being |
435 | 435 | // because not sure if preventing multiple admin page loading will result in bad things happening |
436 | - $darren_logic = false; // true false |
|
436 | + $darren_logic = false; // true false |
|
437 | 437 | $not_the_droids_you_are_looking_for = $darren_logic |
438 | 438 | ? $this->_routing && ($page === '' || $page !== $menu_slug) |
439 | 439 | : $page === '' || $page !== $menu_slug; |
@@ -444,7 +444,7 @@ discard block |
||
444 | 444 | $this->_load_page = true; |
445 | 445 | |
446 | 446 | // we don't need to do a page_request check here because it's only called via WP menu system. |
447 | - $admin_page = $this->_file_name . '_Admin_Page'; |
|
447 | + $admin_page = $this->_file_name.'_Admin_Page'; |
|
448 | 448 | $hook_suffix = "{$menu_slug}_$admin_page"; |
449 | 449 | $admin_page = apply_filters( |
450 | 450 | "FHEE__EE_Admin_Page_Init___initialize_admin_page__admin_page__$hook_suffix", |
@@ -454,14 +454,14 @@ discard block |
||
454 | 454 | return; |
455 | 455 | } |
456 | 456 | // define requested admin page class name then load the file and instantiate |
457 | - $path_to_file = str_replace(['\\', '/'], '/', $this->_folder_path . $admin_page . '.core.php'); |
|
457 | + $path_to_file = str_replace(['\\', '/'], '/', $this->_folder_path.$admin_page.'.core.php'); |
|
458 | 458 | // so if the file would be in EE_ADMIN/attendees/Attendee_Admin_Page.core.php, the filter would be: |
459 | 459 | // FHEE__EE_Admin_Page_Init___initialize_admin_page__path_to_file__attendees_Attendee_Admin_Page |
460 | 460 | $path_to_file = apply_filters( |
461 | 461 | "FHEE__EE_Admin_Page_Init___initialize_admin_page__path_to_file__$hook_suffix", |
462 | 462 | $path_to_file |
463 | 463 | ); |
464 | - if (! is_readable($path_to_file)) { |
|
464 | + if ( ! is_readable($path_to_file)) { |
|
465 | 465 | return; |
466 | 466 | } |
467 | 467 | // This is a place where EE plugins can hook in to make sure their own files are required in the appropriate place |
@@ -478,7 +478,7 @@ discard block |
||
478 | 478 | |
479 | 479 | public function get_admin_page_name(): string |
480 | 480 | { |
481 | - return $this->_file_name . '_Admin_Page'; |
|
481 | + return $this->_file_name.'_Admin_Page'; |
|
482 | 482 | } |
483 | 483 | |
484 | 484 | |
@@ -500,7 +500,7 @@ discard block |
||
500 | 500 | */ |
501 | 501 | private function _check_user_access() |
502 | 502 | { |
503 | - if (! $this->_menu_map->currentUserHasAccess()) { |
|
503 | + if ( ! $this->_menu_map->currentUserHasAccess()) { |
|
504 | 504 | wp_die( |
505 | 505 | esc_html__('You don\'t have access to this page.', 'event_espresso'), |
506 | 506 | '', |
@@ -19,11 +19,11 @@ |
||
19 | 19 | |
20 | 20 | <div class="ee-notices"><?php echo isset($ajax_notices) ? $ajax_notices : '';// already escaped ?></div> |
21 | 21 | <?php |
22 | - do_action('AHEE__admin_wrapper__template__before_admin_page_content'); |
|
23 | - echo wp_kses($before_admin_page_content, AllowedTags::getWithFormTags()); |
|
24 | - echo wp_kses($admin_page_content, AllowedTags::getWithFullTags()); |
|
25 | - echo wp_kses($after_admin_page_content, AllowedTags::getWithFormTags()); |
|
26 | - do_action('AHEE__admin_wrapper__template__after_admin_page_content'); |
|
27 | - ?> |
|
22 | + do_action('AHEE__admin_wrapper__template__before_admin_page_content'); |
|
23 | + echo wp_kses($before_admin_page_content, AllowedTags::getWithFormTags()); |
|
24 | + echo wp_kses($admin_page_content, AllowedTags::getWithFullTags()); |
|
25 | + echo wp_kses($after_admin_page_content, AllowedTags::getWithFormTags()); |
|
26 | + do_action('AHEE__admin_wrapper__template__after_admin_page_content'); |
|
27 | + ?> |
|
28 | 28 | </div> |
29 | 29 | <!-- espresso-admin --> |
@@ -14,10 +14,10 @@ |
||
14 | 14 | |
15 | 15 | <div class="wrap espresso-admin"> |
16 | 16 | <h1> |
17 | - <?php echo esc_html__('Event Espresso', 'event_espresso') . ' ' . wp_kses($admin_page_title, AllowedTags::getWithFormTags()); ?> |
|
17 | + <?php echo esc_html__('Event Espresso', 'event_espresso').' '.wp_kses($admin_page_title, AllowedTags::getWithFormTags()); ?> |
|
18 | 18 | </h1> |
19 | 19 | |
20 | - <div class="ee-notices"><?php echo isset($ajax_notices) ? $ajax_notices : '';// already escaped ?></div> |
|
20 | + <div class="ee-notices"><?php echo isset($ajax_notices) ? $ajax_notices : ''; // already escaped ?></div> |
|
21 | 21 | <?php |
22 | 22 | do_action('AHEE__admin_wrapper__template__before_admin_page_content'); |
23 | 23 | echo wp_kses($before_admin_page_content, AllowedTags::getWithFormTags()); |
@@ -6,7 +6,7 @@ discard block |
||
6 | 6 | use EventEspresso\core\services\request\sanitizers\AllowedTags; |
7 | 7 | |
8 | 8 | if (! class_exists('WP_List_Table')) { |
9 | - require_once ABSPATH . 'wp-admin/includes/class-wp-list-table.php'; |
|
9 | + require_once ABSPATH . 'wp-admin/includes/class-wp-list-table.php'; |
|
10 | 10 | } |
11 | 11 | |
12 | 12 | |
@@ -24,465 +24,465 @@ discard block |
||
24 | 24 | */ |
25 | 25 | abstract class EE_Admin_List_Table extends WP_List_Table |
26 | 26 | { |
27 | - const ACTION_COPY = 'duplicate'; |
|
28 | - |
|
29 | - const ACTION_DELETE = 'delete'; |
|
30 | - |
|
31 | - const ACTION_EDIT = 'edit'; |
|
32 | - |
|
33 | - const ACTION_RESTORE = 'restore'; |
|
34 | - |
|
35 | - const ACTION_TRASH = 'trash'; |
|
36 | - |
|
37 | - protected static array $actions = [ |
|
38 | - self::ACTION_COPY, |
|
39 | - self::ACTION_DELETE, |
|
40 | - self::ACTION_EDIT, |
|
41 | - self::ACTION_RESTORE, |
|
42 | - self::ACTION_TRASH, |
|
43 | - ]; |
|
44 | - |
|
45 | - /** |
|
46 | - * holds the data that will be processed for the table |
|
47 | - * |
|
48 | - * @var array $_data |
|
49 | - */ |
|
50 | - protected array $_data; |
|
51 | - |
|
52 | - |
|
53 | - /** |
|
54 | - * This holds the value of all the data available for the given view (for all pages). |
|
55 | - * |
|
56 | - * @var int $_all_data_count |
|
57 | - */ |
|
58 | - protected int $_all_data_count; |
|
59 | - |
|
60 | - |
|
61 | - /** |
|
62 | - * Will contain the count of trashed items for the view label. |
|
63 | - * |
|
64 | - * @var int $_trashed_count |
|
65 | - */ |
|
66 | - protected int $_trashed_count; |
|
67 | - |
|
68 | - |
|
69 | - /** |
|
70 | - * This is what will be referenced as the slug for the current screen |
|
71 | - * |
|
72 | - * @var string $_screen |
|
73 | - */ |
|
74 | - protected string $_screen; |
|
75 | - |
|
76 | - |
|
77 | - /** |
|
78 | - * this is the EE_Admin_Page object |
|
79 | - * |
|
80 | - * @var EE_Admin_Page $_admin_page |
|
81 | - */ |
|
82 | - protected EE_Admin_Page $_admin_page; |
|
83 | - |
|
84 | - |
|
85 | - /** |
|
86 | - * The current view |
|
87 | - * |
|
88 | - * @var string $_view |
|
89 | - */ |
|
90 | - protected string $_view; |
|
91 | - |
|
92 | - |
|
93 | - /** |
|
94 | - * array of possible views for this table |
|
95 | - * |
|
96 | - * @var array $_views |
|
97 | - */ |
|
98 | - protected array $_views; |
|
99 | - |
|
100 | - |
|
101 | - /** |
|
102 | - * An array of key => value pairs containing information about the current table |
|
103 | - * array( |
|
104 | - * 'plural' => 'plural label', |
|
105 | - * 'singular' => 'singular label', |
|
106 | - * 'ajax' => false, //whether to use ajax or not |
|
107 | - * 'screen' => null, //string used to reference what screen this is |
|
108 | - * (WP_List_table converts to screen object) |
|
109 | - * ) |
|
110 | - * |
|
111 | - * @var array $_wp_list_args |
|
112 | - */ |
|
113 | - protected array $_wp_list_args; |
|
114 | - |
|
115 | - /** |
|
116 | - * an array of column names |
|
117 | - * array( |
|
118 | - * 'internal-name' => 'Title' |
|
119 | - * ) |
|
120 | - * |
|
121 | - * @var array $_columns |
|
122 | - */ |
|
123 | - protected array $_columns; |
|
124 | - |
|
125 | - /** |
|
126 | - * An array of sortable columns |
|
127 | - * array( |
|
128 | - * 'internal-name' => 'orderby' //or |
|
129 | - * 'internal-name' => array( 'orderby', true ) |
|
130 | - * ) |
|
131 | - * |
|
132 | - * @var array $_sortable_columns |
|
133 | - */ |
|
134 | - protected array $_sortable_columns; |
|
135 | - |
|
136 | - /** |
|
137 | - * callback method used to perform AJAX row reordering |
|
138 | - * |
|
139 | - * @var string|null $_ajax_sorting_callback |
|
140 | - */ |
|
141 | - protected ?string $_ajax_sorting_callback = null; |
|
142 | - |
|
143 | - /** |
|
144 | - * An array of hidden columns (if needed) |
|
145 | - * array('internal-name', 'internal-name') |
|
146 | - * |
|
147 | - * @var array $_hidden_columns |
|
148 | - */ |
|
149 | - protected array $_hidden_columns; |
|
150 | - |
|
151 | - /** |
|
152 | - * holds the per_page value |
|
153 | - * |
|
154 | - * @var int $_per_page |
|
155 | - */ |
|
156 | - protected int $_per_page; |
|
157 | - |
|
158 | - /** |
|
159 | - * holds what page number is currently being viewed |
|
160 | - * |
|
161 | - * @var int $_current_page |
|
162 | - */ |
|
163 | - protected int $_current_page; |
|
164 | - |
|
165 | - /** |
|
166 | - * the reference string for the nonce_action |
|
167 | - * |
|
168 | - * @var string $_nonce_action_ref |
|
169 | - */ |
|
170 | - protected string $_nonce_action_ref; |
|
171 | - |
|
172 | - /** |
|
173 | - * property to hold incoming request data (as set by the admin_page_core) |
|
174 | - * |
|
175 | - * @var array $_req_data |
|
176 | - */ |
|
177 | - protected array $_req_data; |
|
178 | - |
|
179 | - |
|
180 | - /** |
|
181 | - * yes / no array for admin form fields |
|
182 | - * |
|
183 | - * @var array $_yes_no |
|
184 | - */ |
|
185 | - protected array $_yes_no = []; |
|
186 | - |
|
187 | - /** |
|
188 | - * Array describing buttons that should appear at the bottom of the page |
|
189 | - * Keys are strings that represent the button's function (specifically a key in _labels['buttons']), |
|
190 | - * and the values are another array with the following keys |
|
191 | - * array( |
|
192 | - * 'route' => 'page_route', |
|
193 | - * 'extra_request' => array('evt_id' => 1 ); //extra request vars that need to be included in the button. |
|
194 | - * ) |
|
195 | - * |
|
196 | - * @var array $_bottom_buttons |
|
197 | - */ |
|
198 | - protected array $_bottom_buttons = []; |
|
199 | - |
|
200 | - |
|
201 | - /** |
|
202 | - * Used to indicate what should be the primary column for the list table. |
|
203 | - * If not present then falls back to what WP calculates |
|
204 | - * as the primary column. |
|
205 | - * |
|
206 | - * @type string $_primary_column |
|
207 | - */ |
|
208 | - protected string $_primary_column = ''; |
|
209 | - |
|
210 | - |
|
211 | - /** |
|
212 | - * Used to indicate whether the table has a checkbox column or not. |
|
213 | - * |
|
214 | - * @type bool $_has_checkbox_column |
|
215 | - */ |
|
216 | - protected bool $_has_checkbox_column = false; |
|
217 | - |
|
218 | - /** |
|
219 | - * @var AdminListTableFilters|null |
|
220 | - */ |
|
221 | - protected ?AdminListTableFilters $admin_list_table_filters = null; |
|
222 | - |
|
223 | - protected ?RequestInterface $request = null; |
|
224 | - |
|
225 | - |
|
226 | - /** |
|
227 | - * @param EE_Admin_Page $admin_page we use this for obtaining everything we need in the list table |
|
228 | - * @param AdminListTableFilters|null $filters to display list table filters |
|
229 | - */ |
|
230 | - public function __construct(EE_Admin_Page $admin_page, ?AdminListTableFilters $filters = null) |
|
231 | - { |
|
232 | - $this->request = $this->request ?? LoaderFactory::getShared(RequestInterface::class); |
|
233 | - $this->_admin_page = $admin_page; |
|
234 | - // kept for back compat |
|
235 | - $this->_req_data = $this->_admin_page->get_request_data(); |
|
236 | - $this->_view = $this->_admin_page->get_view(); |
|
237 | - $this->_views = $this->_admin_page->get_list_table_view_RLs(); |
|
238 | - $this->_current_page = $this->get_pagenum(); |
|
239 | - $this->_screen = $this->_admin_page->get_current_page() . '_' . $this->_admin_page->get_current_view(); |
|
240 | - $this->_yes_no = [ |
|
241 | - esc_html__('No', 'event_espresso'), |
|
242 | - esc_html__('Yes', 'event_espresso'), |
|
243 | - ]; |
|
244 | - |
|
245 | - $this->_per_page = $this->get_items_per_page($this->_screen . '_per_page'); |
|
246 | - |
|
247 | - $this->admin_list_table_filters = $filters instanceof AdminListTableFilters |
|
248 | - ? $filters |
|
249 | - : LoaderFactory::getShared(AdminListTableFilters::class); |
|
250 | - |
|
251 | - $this->_setup_data(); |
|
252 | - $this->_add_view_counts(); |
|
253 | - // ensure changes made to views in child classes get ported back to the admin page |
|
254 | - $this->_admin_page->updateViews($this->_views); |
|
255 | - |
|
256 | - $this->_nonce_action_ref = $this->_view; |
|
257 | - |
|
258 | - $this->_set_properties(); |
|
259 | - |
|
260 | - // set primary column |
|
261 | - add_filter('list_table_primary_column', [$this, 'set_primary_column']); |
|
262 | - |
|
263 | - // set parent defaults |
|
264 | - parent::__construct($this->_wp_list_args); |
|
265 | - |
|
266 | - $this->prepare_items(); |
|
267 | - } |
|
268 | - |
|
269 | - |
|
270 | - /** |
|
271 | - * _setup_data |
|
272 | - * this method is used to setup the $_data, $_all_data_count, and _per_page properties |
|
273 | - * |
|
274 | - * @return void |
|
275 | - * @uses $this->_admin_page |
|
276 | - */ |
|
277 | - abstract protected function _setup_data(); |
|
278 | - |
|
279 | - |
|
280 | - /** |
|
281 | - * set the properties that this class needs to be able to execute wp_list_table properly |
|
282 | - * properties set: |
|
283 | - * _wp_list_args = what the arguments required for the parent _wp_list_table. |
|
284 | - * _columns = set the columns in an array. |
|
285 | - * _sortable_columns = columns that are sortable (array). |
|
286 | - * _hidden_columns = columns that are hidden (array) |
|
287 | - * _default_orderby = the default orderby for sorting. |
|
288 | - * |
|
289 | - * @abstract |
|
290 | - * @access protected |
|
291 | - * @return void |
|
292 | - */ |
|
293 | - abstract protected function _set_properties(); |
|
294 | - |
|
295 | - |
|
296 | - /** |
|
297 | - * _get_table_filters |
|
298 | - * We use this to assemble and return any filters that are associated with this table that help further refine what |
|
299 | - * gets shown in the table. |
|
300 | - * |
|
301 | - * @abstract |
|
302 | - * @access protected |
|
303 | - * @return string[] |
|
304 | - */ |
|
305 | - abstract protected function _get_table_filters(); |
|
306 | - |
|
307 | - |
|
308 | - /** |
|
309 | - * this is a method that child class will do to add counts to the views array so when views are displayed the |
|
310 | - * counts of the views is accurate. |
|
311 | - * |
|
312 | - * @abstract |
|
313 | - * @access protected |
|
314 | - * @return void |
|
315 | - */ |
|
316 | - abstract protected function _add_view_counts(); |
|
317 | - |
|
318 | - |
|
319 | - /** |
|
320 | - * _get_hidden_fields |
|
321 | - * returns a html string of hidden fields so if any table filters are used the current view will be respected. |
|
322 | - * |
|
323 | - * @return string |
|
324 | - */ |
|
325 | - protected function _get_hidden_fields() |
|
326 | - { |
|
327 | - $page = $this->request->getRequestParam('page', ''); |
|
328 | - $action = $this->request->getRequestParam('route', ''); |
|
329 | - $action = $this->request->getRequestParam('action', $action); |
|
330 | - // if action is STILL empty, then we set it to default |
|
331 | - $action = empty($action) || $action === '-1' ? 'default' : $action; |
|
332 | - $field = '<input type="hidden" name="page" value="' . esc_attr($page) . '" />' . "\n"; |
|
333 | - $field .= '<input type="hidden" name="route" value="' . esc_attr($action) . '" />' . "\n"; |
|
334 | - $field .= '<input type="hidden" name="perpage" value="' . esc_attr($this->_per_page) . '" />' . "\n"; |
|
335 | - |
|
336 | - $bulk_actions = $this->_get_bulk_actions(); |
|
337 | - foreach ($bulk_actions as $bulk_action => $label) { |
|
338 | - $field .= '<input type="hidden" name="' . $bulk_action . '_nonce"' |
|
339 | - . ' value="' . wp_create_nonce($bulk_action . '_nonce') . '" />' . "\n"; |
|
340 | - } |
|
341 | - |
|
342 | - return $field; |
|
343 | - } |
|
344 | - |
|
345 | - |
|
346 | - /** |
|
347 | - * _set_column_info |
|
348 | - * we're using this to set the column headers property. |
|
349 | - * |
|
350 | - * @access protected |
|
351 | - * @return void |
|
352 | - */ |
|
353 | - protected function _set_column_info() |
|
354 | - { |
|
355 | - $columns = $this->get_columns(); |
|
356 | - $hidden = $this->get_hidden_columns(); |
|
357 | - $_sortable = $this->get_sortable_columns(); |
|
358 | - |
|
359 | - /** |
|
360 | - * Dynamic hook allowing for adding sortable columns in this list table. |
|
361 | - * Note that $this->screen->id is in the format |
|
362 | - * {sanitize_title($top_level_menu_label)}_page_{$espresso_admin_page_slug}. So for the messages list |
|
363 | - * table it is: event-espresso_page_espresso_messages. |
|
364 | - * However, take note that if the top level menu label has been translated (i.e. "Event Espresso"). then the |
|
365 | - * hook prefix ("event-espresso") will be different. |
|
366 | - * |
|
367 | - * @var array $_sortable |
|
368 | - */ |
|
369 | - $_sortable = apply_filters( |
|
370 | - "FHEE_manage_{$this->screen->id}_sortable_columns", |
|
371 | - $_sortable, |
|
372 | - $this->_screen, |
|
373 | - $this |
|
374 | - ); |
|
375 | - |
|
376 | - $sortable = []; |
|
377 | - foreach ($_sortable as $id => $data) { |
|
378 | - if (empty($data)) { |
|
379 | - continue; |
|
380 | - } |
|
381 | - // fix for offset errors with WP_List_Table default get_columninfo() |
|
382 | - if (is_array($data)) { |
|
383 | - $_data[0] = key($data); |
|
384 | - $_data[1] = $data[1] ?? false; |
|
385 | - } else { |
|
386 | - $_data[0] = $data; |
|
387 | - } |
|
388 | - |
|
389 | - $data = (array) $data; |
|
390 | - |
|
391 | - if (! isset($data[1])) { |
|
392 | - $_data[1] = false; |
|
393 | - } |
|
394 | - |
|
395 | - $sortable[ $id ] = $_data; |
|
396 | - } |
|
397 | - $primary = $this->get_primary_column_name(); |
|
398 | - $this->_column_headers = [$columns, $hidden, $sortable, $primary]; |
|
399 | - } |
|
400 | - |
|
401 | - |
|
402 | - /** |
|
403 | - * Added for WP4.1 backward compat (@see https://events.codebasehq.com/projects/event-espresso/tickets/8814) |
|
404 | - * |
|
405 | - * @return string |
|
406 | - */ |
|
407 | - protected function get_primary_column_name() |
|
408 | - { |
|
409 | - foreach (class_parents($this) as $parent) { |
|
410 | - if ($parent === 'WP_List_Table' && method_exists($parent, 'get_primary_column_name')) { |
|
411 | - return parent::get_primary_column_name(); |
|
412 | - } |
|
413 | - } |
|
414 | - return $this->_primary_column; |
|
415 | - } |
|
416 | - |
|
417 | - |
|
418 | - /** |
|
419 | - * Added for WP4.1 backward compat (@see https://events.codebasehq.com/projects/event-espresso/tickets/8814) |
|
420 | - * |
|
421 | - * @param EE_Base_Class $item |
|
422 | - * @param string $column_name |
|
423 | - * @param string $primary |
|
424 | - * @return string |
|
425 | - */ |
|
426 | - protected function handle_row_actions($item, $column_name, $primary) |
|
427 | - { |
|
428 | - foreach (class_parents($this) as $parent) { |
|
429 | - if ($parent === 'WP_List_Table' && method_exists($parent, 'handle_row_actions')) { |
|
430 | - return parent::handle_row_actions($item, $column_name, $primary); |
|
431 | - } |
|
432 | - } |
|
433 | - return ''; |
|
434 | - } |
|
435 | - |
|
436 | - |
|
437 | - /** |
|
438 | - * _get_bulk_actions |
|
439 | - * This is a wrapper called by WP_List_Table::get_bulk_actions() |
|
440 | - * |
|
441 | - * @access protected |
|
442 | - * @return array bulk_actions |
|
443 | - */ |
|
444 | - protected function _get_bulk_actions(): array |
|
445 | - { |
|
446 | - $actions = []; |
|
447 | - // the _views property should have the bulk_actions, so let's go through and extract them into a properly |
|
448 | - // formatted array for the wp_list_table(); |
|
449 | - foreach ($this->_views as $view => $args) { |
|
450 | - if ($this->_view === $view && isset($args['bulk_action']) && is_array($args['bulk_action'])) { |
|
451 | - // each bulk action will correspond with a admin page route, so we can check whatever the capability is |
|
452 | - // for that page route and skip adding the bulk action if no access for the current logged in user. |
|
453 | - foreach ($args['bulk_action'] as $route => $label) { |
|
454 | - if ($this->_admin_page->check_user_access($route, true)) { |
|
455 | - $actions[ $route ] = $label; |
|
456 | - } |
|
457 | - } |
|
458 | - } |
|
459 | - } |
|
460 | - return $actions; |
|
461 | - } |
|
462 | - |
|
463 | - |
|
464 | - /** |
|
465 | - * Generate the table navigation above or below the table. |
|
466 | - * Overrides the parent table nav in WP_List_Table so we can hide the bulk action div if there are no bulk actions. |
|
467 | - * |
|
468 | - * @throws EE_Error |
|
469 | - * @since 4.9.44.rc.001 |
|
470 | - */ |
|
471 | - public function display_tablenav($which) |
|
472 | - { |
|
473 | - if ('top' === $which) { |
|
474 | - wp_nonce_field('bulk-' . $this->_args['plural']); |
|
475 | - } |
|
476 | - |
|
477 | - ob_start(); |
|
478 | - $this->extra_tablenav($which); |
|
479 | - $ee_tablenav = ob_get_clean(); |
|
480 | - |
|
481 | - ob_start(); |
|
482 | - $this->bulk_actions(); |
|
483 | - $bulkactions = ob_get_clean(); |
|
484 | - |
|
485 | - ?> |
|
27 | + const ACTION_COPY = 'duplicate'; |
|
28 | + |
|
29 | + const ACTION_DELETE = 'delete'; |
|
30 | + |
|
31 | + const ACTION_EDIT = 'edit'; |
|
32 | + |
|
33 | + const ACTION_RESTORE = 'restore'; |
|
34 | + |
|
35 | + const ACTION_TRASH = 'trash'; |
|
36 | + |
|
37 | + protected static array $actions = [ |
|
38 | + self::ACTION_COPY, |
|
39 | + self::ACTION_DELETE, |
|
40 | + self::ACTION_EDIT, |
|
41 | + self::ACTION_RESTORE, |
|
42 | + self::ACTION_TRASH, |
|
43 | + ]; |
|
44 | + |
|
45 | + /** |
|
46 | + * holds the data that will be processed for the table |
|
47 | + * |
|
48 | + * @var array $_data |
|
49 | + */ |
|
50 | + protected array $_data; |
|
51 | + |
|
52 | + |
|
53 | + /** |
|
54 | + * This holds the value of all the data available for the given view (for all pages). |
|
55 | + * |
|
56 | + * @var int $_all_data_count |
|
57 | + */ |
|
58 | + protected int $_all_data_count; |
|
59 | + |
|
60 | + |
|
61 | + /** |
|
62 | + * Will contain the count of trashed items for the view label. |
|
63 | + * |
|
64 | + * @var int $_trashed_count |
|
65 | + */ |
|
66 | + protected int $_trashed_count; |
|
67 | + |
|
68 | + |
|
69 | + /** |
|
70 | + * This is what will be referenced as the slug for the current screen |
|
71 | + * |
|
72 | + * @var string $_screen |
|
73 | + */ |
|
74 | + protected string $_screen; |
|
75 | + |
|
76 | + |
|
77 | + /** |
|
78 | + * this is the EE_Admin_Page object |
|
79 | + * |
|
80 | + * @var EE_Admin_Page $_admin_page |
|
81 | + */ |
|
82 | + protected EE_Admin_Page $_admin_page; |
|
83 | + |
|
84 | + |
|
85 | + /** |
|
86 | + * The current view |
|
87 | + * |
|
88 | + * @var string $_view |
|
89 | + */ |
|
90 | + protected string $_view; |
|
91 | + |
|
92 | + |
|
93 | + /** |
|
94 | + * array of possible views for this table |
|
95 | + * |
|
96 | + * @var array $_views |
|
97 | + */ |
|
98 | + protected array $_views; |
|
99 | + |
|
100 | + |
|
101 | + /** |
|
102 | + * An array of key => value pairs containing information about the current table |
|
103 | + * array( |
|
104 | + * 'plural' => 'plural label', |
|
105 | + * 'singular' => 'singular label', |
|
106 | + * 'ajax' => false, //whether to use ajax or not |
|
107 | + * 'screen' => null, //string used to reference what screen this is |
|
108 | + * (WP_List_table converts to screen object) |
|
109 | + * ) |
|
110 | + * |
|
111 | + * @var array $_wp_list_args |
|
112 | + */ |
|
113 | + protected array $_wp_list_args; |
|
114 | + |
|
115 | + /** |
|
116 | + * an array of column names |
|
117 | + * array( |
|
118 | + * 'internal-name' => 'Title' |
|
119 | + * ) |
|
120 | + * |
|
121 | + * @var array $_columns |
|
122 | + */ |
|
123 | + protected array $_columns; |
|
124 | + |
|
125 | + /** |
|
126 | + * An array of sortable columns |
|
127 | + * array( |
|
128 | + * 'internal-name' => 'orderby' //or |
|
129 | + * 'internal-name' => array( 'orderby', true ) |
|
130 | + * ) |
|
131 | + * |
|
132 | + * @var array $_sortable_columns |
|
133 | + */ |
|
134 | + protected array $_sortable_columns; |
|
135 | + |
|
136 | + /** |
|
137 | + * callback method used to perform AJAX row reordering |
|
138 | + * |
|
139 | + * @var string|null $_ajax_sorting_callback |
|
140 | + */ |
|
141 | + protected ?string $_ajax_sorting_callback = null; |
|
142 | + |
|
143 | + /** |
|
144 | + * An array of hidden columns (if needed) |
|
145 | + * array('internal-name', 'internal-name') |
|
146 | + * |
|
147 | + * @var array $_hidden_columns |
|
148 | + */ |
|
149 | + protected array $_hidden_columns; |
|
150 | + |
|
151 | + /** |
|
152 | + * holds the per_page value |
|
153 | + * |
|
154 | + * @var int $_per_page |
|
155 | + */ |
|
156 | + protected int $_per_page; |
|
157 | + |
|
158 | + /** |
|
159 | + * holds what page number is currently being viewed |
|
160 | + * |
|
161 | + * @var int $_current_page |
|
162 | + */ |
|
163 | + protected int $_current_page; |
|
164 | + |
|
165 | + /** |
|
166 | + * the reference string for the nonce_action |
|
167 | + * |
|
168 | + * @var string $_nonce_action_ref |
|
169 | + */ |
|
170 | + protected string $_nonce_action_ref; |
|
171 | + |
|
172 | + /** |
|
173 | + * property to hold incoming request data (as set by the admin_page_core) |
|
174 | + * |
|
175 | + * @var array $_req_data |
|
176 | + */ |
|
177 | + protected array $_req_data; |
|
178 | + |
|
179 | + |
|
180 | + /** |
|
181 | + * yes / no array for admin form fields |
|
182 | + * |
|
183 | + * @var array $_yes_no |
|
184 | + */ |
|
185 | + protected array $_yes_no = []; |
|
186 | + |
|
187 | + /** |
|
188 | + * Array describing buttons that should appear at the bottom of the page |
|
189 | + * Keys are strings that represent the button's function (specifically a key in _labels['buttons']), |
|
190 | + * and the values are another array with the following keys |
|
191 | + * array( |
|
192 | + * 'route' => 'page_route', |
|
193 | + * 'extra_request' => array('evt_id' => 1 ); //extra request vars that need to be included in the button. |
|
194 | + * ) |
|
195 | + * |
|
196 | + * @var array $_bottom_buttons |
|
197 | + */ |
|
198 | + protected array $_bottom_buttons = []; |
|
199 | + |
|
200 | + |
|
201 | + /** |
|
202 | + * Used to indicate what should be the primary column for the list table. |
|
203 | + * If not present then falls back to what WP calculates |
|
204 | + * as the primary column. |
|
205 | + * |
|
206 | + * @type string $_primary_column |
|
207 | + */ |
|
208 | + protected string $_primary_column = ''; |
|
209 | + |
|
210 | + |
|
211 | + /** |
|
212 | + * Used to indicate whether the table has a checkbox column or not. |
|
213 | + * |
|
214 | + * @type bool $_has_checkbox_column |
|
215 | + */ |
|
216 | + protected bool $_has_checkbox_column = false; |
|
217 | + |
|
218 | + /** |
|
219 | + * @var AdminListTableFilters|null |
|
220 | + */ |
|
221 | + protected ?AdminListTableFilters $admin_list_table_filters = null; |
|
222 | + |
|
223 | + protected ?RequestInterface $request = null; |
|
224 | + |
|
225 | + |
|
226 | + /** |
|
227 | + * @param EE_Admin_Page $admin_page we use this for obtaining everything we need in the list table |
|
228 | + * @param AdminListTableFilters|null $filters to display list table filters |
|
229 | + */ |
|
230 | + public function __construct(EE_Admin_Page $admin_page, ?AdminListTableFilters $filters = null) |
|
231 | + { |
|
232 | + $this->request = $this->request ?? LoaderFactory::getShared(RequestInterface::class); |
|
233 | + $this->_admin_page = $admin_page; |
|
234 | + // kept for back compat |
|
235 | + $this->_req_data = $this->_admin_page->get_request_data(); |
|
236 | + $this->_view = $this->_admin_page->get_view(); |
|
237 | + $this->_views = $this->_admin_page->get_list_table_view_RLs(); |
|
238 | + $this->_current_page = $this->get_pagenum(); |
|
239 | + $this->_screen = $this->_admin_page->get_current_page() . '_' . $this->_admin_page->get_current_view(); |
|
240 | + $this->_yes_no = [ |
|
241 | + esc_html__('No', 'event_espresso'), |
|
242 | + esc_html__('Yes', 'event_espresso'), |
|
243 | + ]; |
|
244 | + |
|
245 | + $this->_per_page = $this->get_items_per_page($this->_screen . '_per_page'); |
|
246 | + |
|
247 | + $this->admin_list_table_filters = $filters instanceof AdminListTableFilters |
|
248 | + ? $filters |
|
249 | + : LoaderFactory::getShared(AdminListTableFilters::class); |
|
250 | + |
|
251 | + $this->_setup_data(); |
|
252 | + $this->_add_view_counts(); |
|
253 | + // ensure changes made to views in child classes get ported back to the admin page |
|
254 | + $this->_admin_page->updateViews($this->_views); |
|
255 | + |
|
256 | + $this->_nonce_action_ref = $this->_view; |
|
257 | + |
|
258 | + $this->_set_properties(); |
|
259 | + |
|
260 | + // set primary column |
|
261 | + add_filter('list_table_primary_column', [$this, 'set_primary_column']); |
|
262 | + |
|
263 | + // set parent defaults |
|
264 | + parent::__construct($this->_wp_list_args); |
|
265 | + |
|
266 | + $this->prepare_items(); |
|
267 | + } |
|
268 | + |
|
269 | + |
|
270 | + /** |
|
271 | + * _setup_data |
|
272 | + * this method is used to setup the $_data, $_all_data_count, and _per_page properties |
|
273 | + * |
|
274 | + * @return void |
|
275 | + * @uses $this->_admin_page |
|
276 | + */ |
|
277 | + abstract protected function _setup_data(); |
|
278 | + |
|
279 | + |
|
280 | + /** |
|
281 | + * set the properties that this class needs to be able to execute wp_list_table properly |
|
282 | + * properties set: |
|
283 | + * _wp_list_args = what the arguments required for the parent _wp_list_table. |
|
284 | + * _columns = set the columns in an array. |
|
285 | + * _sortable_columns = columns that are sortable (array). |
|
286 | + * _hidden_columns = columns that are hidden (array) |
|
287 | + * _default_orderby = the default orderby for sorting. |
|
288 | + * |
|
289 | + * @abstract |
|
290 | + * @access protected |
|
291 | + * @return void |
|
292 | + */ |
|
293 | + abstract protected function _set_properties(); |
|
294 | + |
|
295 | + |
|
296 | + /** |
|
297 | + * _get_table_filters |
|
298 | + * We use this to assemble and return any filters that are associated with this table that help further refine what |
|
299 | + * gets shown in the table. |
|
300 | + * |
|
301 | + * @abstract |
|
302 | + * @access protected |
|
303 | + * @return string[] |
|
304 | + */ |
|
305 | + abstract protected function _get_table_filters(); |
|
306 | + |
|
307 | + |
|
308 | + /** |
|
309 | + * this is a method that child class will do to add counts to the views array so when views are displayed the |
|
310 | + * counts of the views is accurate. |
|
311 | + * |
|
312 | + * @abstract |
|
313 | + * @access protected |
|
314 | + * @return void |
|
315 | + */ |
|
316 | + abstract protected function _add_view_counts(); |
|
317 | + |
|
318 | + |
|
319 | + /** |
|
320 | + * _get_hidden_fields |
|
321 | + * returns a html string of hidden fields so if any table filters are used the current view will be respected. |
|
322 | + * |
|
323 | + * @return string |
|
324 | + */ |
|
325 | + protected function _get_hidden_fields() |
|
326 | + { |
|
327 | + $page = $this->request->getRequestParam('page', ''); |
|
328 | + $action = $this->request->getRequestParam('route', ''); |
|
329 | + $action = $this->request->getRequestParam('action', $action); |
|
330 | + // if action is STILL empty, then we set it to default |
|
331 | + $action = empty($action) || $action === '-1' ? 'default' : $action; |
|
332 | + $field = '<input type="hidden" name="page" value="' . esc_attr($page) . '" />' . "\n"; |
|
333 | + $field .= '<input type="hidden" name="route" value="' . esc_attr($action) . '" />' . "\n"; |
|
334 | + $field .= '<input type="hidden" name="perpage" value="' . esc_attr($this->_per_page) . '" />' . "\n"; |
|
335 | + |
|
336 | + $bulk_actions = $this->_get_bulk_actions(); |
|
337 | + foreach ($bulk_actions as $bulk_action => $label) { |
|
338 | + $field .= '<input type="hidden" name="' . $bulk_action . '_nonce"' |
|
339 | + . ' value="' . wp_create_nonce($bulk_action . '_nonce') . '" />' . "\n"; |
|
340 | + } |
|
341 | + |
|
342 | + return $field; |
|
343 | + } |
|
344 | + |
|
345 | + |
|
346 | + /** |
|
347 | + * _set_column_info |
|
348 | + * we're using this to set the column headers property. |
|
349 | + * |
|
350 | + * @access protected |
|
351 | + * @return void |
|
352 | + */ |
|
353 | + protected function _set_column_info() |
|
354 | + { |
|
355 | + $columns = $this->get_columns(); |
|
356 | + $hidden = $this->get_hidden_columns(); |
|
357 | + $_sortable = $this->get_sortable_columns(); |
|
358 | + |
|
359 | + /** |
|
360 | + * Dynamic hook allowing for adding sortable columns in this list table. |
|
361 | + * Note that $this->screen->id is in the format |
|
362 | + * {sanitize_title($top_level_menu_label)}_page_{$espresso_admin_page_slug}. So for the messages list |
|
363 | + * table it is: event-espresso_page_espresso_messages. |
|
364 | + * However, take note that if the top level menu label has been translated (i.e. "Event Espresso"). then the |
|
365 | + * hook prefix ("event-espresso") will be different. |
|
366 | + * |
|
367 | + * @var array $_sortable |
|
368 | + */ |
|
369 | + $_sortable = apply_filters( |
|
370 | + "FHEE_manage_{$this->screen->id}_sortable_columns", |
|
371 | + $_sortable, |
|
372 | + $this->_screen, |
|
373 | + $this |
|
374 | + ); |
|
375 | + |
|
376 | + $sortable = []; |
|
377 | + foreach ($_sortable as $id => $data) { |
|
378 | + if (empty($data)) { |
|
379 | + continue; |
|
380 | + } |
|
381 | + // fix for offset errors with WP_List_Table default get_columninfo() |
|
382 | + if (is_array($data)) { |
|
383 | + $_data[0] = key($data); |
|
384 | + $_data[1] = $data[1] ?? false; |
|
385 | + } else { |
|
386 | + $_data[0] = $data; |
|
387 | + } |
|
388 | + |
|
389 | + $data = (array) $data; |
|
390 | + |
|
391 | + if (! isset($data[1])) { |
|
392 | + $_data[1] = false; |
|
393 | + } |
|
394 | + |
|
395 | + $sortable[ $id ] = $_data; |
|
396 | + } |
|
397 | + $primary = $this->get_primary_column_name(); |
|
398 | + $this->_column_headers = [$columns, $hidden, $sortable, $primary]; |
|
399 | + } |
|
400 | + |
|
401 | + |
|
402 | + /** |
|
403 | + * Added for WP4.1 backward compat (@see https://events.codebasehq.com/projects/event-espresso/tickets/8814) |
|
404 | + * |
|
405 | + * @return string |
|
406 | + */ |
|
407 | + protected function get_primary_column_name() |
|
408 | + { |
|
409 | + foreach (class_parents($this) as $parent) { |
|
410 | + if ($parent === 'WP_List_Table' && method_exists($parent, 'get_primary_column_name')) { |
|
411 | + return parent::get_primary_column_name(); |
|
412 | + } |
|
413 | + } |
|
414 | + return $this->_primary_column; |
|
415 | + } |
|
416 | + |
|
417 | + |
|
418 | + /** |
|
419 | + * Added for WP4.1 backward compat (@see https://events.codebasehq.com/projects/event-espresso/tickets/8814) |
|
420 | + * |
|
421 | + * @param EE_Base_Class $item |
|
422 | + * @param string $column_name |
|
423 | + * @param string $primary |
|
424 | + * @return string |
|
425 | + */ |
|
426 | + protected function handle_row_actions($item, $column_name, $primary) |
|
427 | + { |
|
428 | + foreach (class_parents($this) as $parent) { |
|
429 | + if ($parent === 'WP_List_Table' && method_exists($parent, 'handle_row_actions')) { |
|
430 | + return parent::handle_row_actions($item, $column_name, $primary); |
|
431 | + } |
|
432 | + } |
|
433 | + return ''; |
|
434 | + } |
|
435 | + |
|
436 | + |
|
437 | + /** |
|
438 | + * _get_bulk_actions |
|
439 | + * This is a wrapper called by WP_List_Table::get_bulk_actions() |
|
440 | + * |
|
441 | + * @access protected |
|
442 | + * @return array bulk_actions |
|
443 | + */ |
|
444 | + protected function _get_bulk_actions(): array |
|
445 | + { |
|
446 | + $actions = []; |
|
447 | + // the _views property should have the bulk_actions, so let's go through and extract them into a properly |
|
448 | + // formatted array for the wp_list_table(); |
|
449 | + foreach ($this->_views as $view => $args) { |
|
450 | + if ($this->_view === $view && isset($args['bulk_action']) && is_array($args['bulk_action'])) { |
|
451 | + // each bulk action will correspond with a admin page route, so we can check whatever the capability is |
|
452 | + // for that page route and skip adding the bulk action if no access for the current logged in user. |
|
453 | + foreach ($args['bulk_action'] as $route => $label) { |
|
454 | + if ($this->_admin_page->check_user_access($route, true)) { |
|
455 | + $actions[ $route ] = $label; |
|
456 | + } |
|
457 | + } |
|
458 | + } |
|
459 | + } |
|
460 | + return $actions; |
|
461 | + } |
|
462 | + |
|
463 | + |
|
464 | + /** |
|
465 | + * Generate the table navigation above or below the table. |
|
466 | + * Overrides the parent table nav in WP_List_Table so we can hide the bulk action div if there are no bulk actions. |
|
467 | + * |
|
468 | + * @throws EE_Error |
|
469 | + * @since 4.9.44.rc.001 |
|
470 | + */ |
|
471 | + public function display_tablenav($which) |
|
472 | + { |
|
473 | + if ('top' === $which) { |
|
474 | + wp_nonce_field('bulk-' . $this->_args['plural']); |
|
475 | + } |
|
476 | + |
|
477 | + ob_start(); |
|
478 | + $this->extra_tablenav($which); |
|
479 | + $ee_tablenav = ob_get_clean(); |
|
480 | + |
|
481 | + ob_start(); |
|
482 | + $this->bulk_actions(); |
|
483 | + $bulkactions = ob_get_clean(); |
|
484 | + |
|
485 | + ?> |
|
486 | 486 | <?php if ($ee_tablenav && $which === 'top') : ?> |
487 | 487 | <div class="tablenav <?php echo esc_attr($which); ?> ee-tablenav"> |
488 | 488 | <?php echo wp_kses($ee_tablenav, AllowedTags::getWithFormTags()); ?> |
@@ -502,484 +502,484 @@ discard block |
||
502 | 502 | </div> |
503 | 503 | <?php endif; ?> |
504 | 504 | <?php |
505 | - if ($which === 'top') { |
|
506 | - echo wp_kses($this->_get_hidden_fields(), AllowedTags::getWithFormTags()); |
|
507 | - } |
|
508 | - } |
|
509 | - |
|
510 | - |
|
511 | - /** |
|
512 | - * _filters |
|
513 | - * This receives the filters array from children _get_table_filters() and assembles the string including the filter |
|
514 | - * button. |
|
515 | - * |
|
516 | - * @access private |
|
517 | - * @return void echos html showing filters |
|
518 | - */ |
|
519 | - private function _filters(): void |
|
520 | - { |
|
521 | - $classname = get_class($this); |
|
522 | - $filters = apply_filters( |
|
523 | - "FHEE__{$classname}__filters", |
|
524 | - $this->_get_table_filters(), |
|
525 | - $this, |
|
526 | - $this->_screen |
|
527 | - ); |
|
528 | - |
|
529 | - if (empty($filters)) { |
|
530 | - return; |
|
531 | - } |
|
532 | - |
|
533 | - $this->admin_list_table_filters->filters( |
|
534 | - $filters, |
|
535 | - $this->get_admin_page()->get_current_page_view_url() |
|
536 | - ); |
|
537 | - } |
|
538 | - |
|
539 | - |
|
540 | - /** |
|
541 | - * Callback for 'list_table_primary_column' WordPress filter |
|
542 | - * If child EE_Admin_List_Table classes set the _primary_column property then that will be set as the primary |
|
543 | - * column when class is instantiated. |
|
544 | - * |
|
545 | - * @param string $column_name |
|
546 | - * @return string |
|
547 | - * @see WP_List_Table::get_primary_column_name |
|
548 | - */ |
|
549 | - public function set_primary_column($column_name) |
|
550 | - { |
|
551 | - return ! empty($this->_primary_column) ? $this->_primary_column : $column_name; |
|
552 | - } |
|
553 | - |
|
554 | - |
|
555 | - /** |
|
556 | - * |
|
557 | - */ |
|
558 | - public function prepare_items() |
|
559 | - { |
|
560 | - $this->_set_column_info(); |
|
561 | - $this->process_bulk_action(); |
|
562 | - |
|
563 | - $this->items = $this->_data; |
|
564 | - $this->set_pagination_args( |
|
565 | - [ |
|
566 | - 'total_items' => $this->_all_data_count, |
|
567 | - 'per_page' => $this->_per_page, |
|
568 | - 'total_pages' => (int) ceil($this->_all_data_count / $this->_per_page), |
|
569 | - ] |
|
570 | - ); |
|
571 | - } |
|
572 | - |
|
573 | - |
|
574 | - /** |
|
575 | - * @param object|array $item |
|
576 | - * @return string html content for the column |
|
577 | - */ |
|
578 | - protected function column_cb($item) |
|
579 | - { |
|
580 | - return ''; |
|
581 | - } |
|
582 | - |
|
583 | - |
|
584 | - /** |
|
585 | - * This column is the default for when there is no defined column method for a registered column. |
|
586 | - * This can be overridden by child classes, but allows for hooking in for custom columns. |
|
587 | - * |
|
588 | - * @param EE_Base_Class $item |
|
589 | - * @param string $column_name The column being called. |
|
590 | - * @return string html content for the column |
|
591 | - */ |
|
592 | - public function column_default($item, $column_name) |
|
593 | - { |
|
594 | - /** |
|
595 | - * Dynamic hook allowing for adding additional column content in this list table. |
|
596 | - * Note that $this->screen->id is in the format |
|
597 | - * {sanitize_title($top_level_menu_label)}_page_{$espresso_admin_page_slug}. So for the messages list |
|
598 | - * table it is: event-espresso_page_espresso_messages. |
|
599 | - * However, take note that if the top level menu label has been translated (i.e. "Event Espresso"). then the |
|
600 | - * hook prefix ("event-espresso") will be different. |
|
601 | - */ |
|
602 | - ob_start(); |
|
603 | - do_action( |
|
604 | - 'AHEE__EE_Admin_List_Table__column_' . $column_name . '__' . $this->screen->id, |
|
605 | - $item, |
|
606 | - $this->_screen |
|
607 | - ); |
|
608 | - $content = ob_get_clean(); |
|
609 | - return $column_name === 'actions' ? $this->actionsModalMenu($content) : $content; |
|
610 | - } |
|
611 | - |
|
612 | - |
|
613 | - /** |
|
614 | - * Get a list of columns. The format is: |
|
615 | - * 'internal-name' => 'Title' |
|
616 | - * |
|
617 | - * @return array |
|
618 | - * @since 3.1.0 |
|
619 | - * @access public |
|
620 | - * @abstract |
|
621 | - */ |
|
622 | - public function get_columns() |
|
623 | - { |
|
624 | - /** |
|
625 | - * Dynamic hook allowing for adding additional columns in this list table. |
|
626 | - * Note that $this->screen->id is in the format |
|
627 | - * {sanitize_title($top_level_menu_label)}_page_{$espresso_admin_page_slug}. So for the messages list |
|
628 | - * table it is: event-espresso_page_espresso_messages. |
|
629 | - * However, take note that if the top level menu label has been translated (i.e. "Event Espresso"). then the |
|
630 | - * hook prefix ("event-espresso") will be different. |
|
631 | - * |
|
632 | - * @var array |
|
633 | - */ |
|
634 | - return apply_filters("FHEE_manage_{$this->screen->id}_columns", $this->_columns, $this->_screen, $this); |
|
635 | - } |
|
636 | - |
|
637 | - |
|
638 | - /** |
|
639 | - * Get an associative array ( id => link ) with the list |
|
640 | - * of views available on this table. |
|
641 | - * |
|
642 | - * @return array |
|
643 | - * @since 3.1.0 |
|
644 | - * @access protected |
|
645 | - */ |
|
646 | - public function get_views() |
|
647 | - { |
|
648 | - return $this->_views; |
|
649 | - } |
|
650 | - |
|
651 | - |
|
652 | - /** |
|
653 | - * Generate the views html. |
|
654 | - */ |
|
655 | - public function display_views() |
|
656 | - { |
|
657 | - $views = $this->get_views(); |
|
658 | - $assembled_views = []; |
|
659 | - |
|
660 | - if (empty($views)) { |
|
661 | - return; |
|
662 | - } |
|
663 | - echo "<ul class='subsubsub'>\n"; |
|
664 | - foreach ($views as $view) { |
|
665 | - $count = ! empty($view['count']) ? absint($view['count']) : 0; |
|
666 | - if (isset($view['slug'], $view['class'], $view['url'], $view['label'])) { |
|
667 | - $filter = "<li"; |
|
668 | - $filter .= $view['class'] ? " class='" . esc_attr($view['class']) . "'" : ''; |
|
669 | - $filter .= ">"; |
|
670 | - $filter .= '<a href="' . esc_url_raw($view['url']) . '">' . esc_html( |
|
671 | - $view['label'] |
|
672 | - ) . '</a>'; |
|
673 | - $filter .= '<span class="count">(' . $count . ')</span>'; |
|
674 | - $filter .= '</li>'; |
|
675 | - $assembled_views[ $view['slug'] ] = $filter; |
|
676 | - } |
|
677 | - } |
|
678 | - |
|
679 | - echo ! empty($assembled_views) |
|
680 | - ? implode("<li style='margin:0 .5rem;'>|</li>", $assembled_views) |
|
681 | - : ''; |
|
682 | - echo "</ul>"; |
|
683 | - } |
|
684 | - |
|
685 | - |
|
686 | - /** |
|
687 | - * Generates content for a single row of the table |
|
688 | - * |
|
689 | - * @param EE_Base_Class $item The current item |
|
690 | - * @since 4.1 |
|
691 | - * @access public |
|
692 | - */ |
|
693 | - public function single_row($item) |
|
694 | - { |
|
695 | - $row_class = $this->_get_row_class($item); |
|
696 | - echo '<tr class="' . esc_attr($row_class) . '">'; |
|
697 | - $this->single_row_columns($item); // already escaped |
|
698 | - echo '</tr>'; |
|
699 | - } |
|
700 | - |
|
701 | - |
|
702 | - /** |
|
703 | - * This simply sets up the row class for the table rows. |
|
704 | - * Allows for easier overriding of child methods for setting up sorting. |
|
705 | - * |
|
706 | - * @param EE_Base_Class $item the current item |
|
707 | - * @return string |
|
708 | - */ |
|
709 | - protected function _get_row_class($item) |
|
710 | - { |
|
711 | - static $row_class = ''; |
|
712 | - $row_class = ($row_class === '' ? 'alternate' : ''); |
|
713 | - |
|
714 | - $new_row_class = $row_class; |
|
715 | - |
|
716 | - if (! empty($this->_ajax_sorting_callback)) { |
|
717 | - $new_row_class .= ' rowsortable'; |
|
718 | - } |
|
719 | - |
|
720 | - return $new_row_class; |
|
721 | - } |
|
722 | - |
|
723 | - |
|
724 | - /** |
|
725 | - * @return array |
|
726 | - */ |
|
727 | - public function get_sortable_columns() |
|
728 | - { |
|
729 | - return (array) $this->_sortable_columns; |
|
730 | - } |
|
731 | - |
|
732 | - |
|
733 | - /** |
|
734 | - * @return string |
|
735 | - */ |
|
736 | - public function get_ajax_sorting_callback() |
|
737 | - { |
|
738 | - return $this->_ajax_sorting_callback; |
|
739 | - } |
|
740 | - |
|
741 | - |
|
742 | - /** |
|
743 | - * @return array |
|
744 | - */ |
|
745 | - public function get_hidden_columns(): array |
|
746 | - { |
|
747 | - $user_id = get_current_user_id(); |
|
748 | - $has_default = get_user_option('default' . $this->screen->id . 'columnshidden', $user_id); |
|
749 | - if (empty($has_default) && ! empty($this->_hidden_columns)) { |
|
750 | - update_user_option($user_id, 'default' . $this->screen->id . 'columnshidden', true); |
|
751 | - update_user_option($user_id, 'manage' . $this->screen->id . 'columnshidden', $this->_hidden_columns, true); |
|
752 | - } |
|
753 | - $ref = 'manage' . $this->screen->id . 'columnshidden'; |
|
754 | - return (array) get_user_option($ref, $user_id); |
|
755 | - } |
|
756 | - |
|
757 | - |
|
758 | - /** |
|
759 | - * Generates the columns for a single row of the table. |
|
760 | - * Overridden from wp_list_table so as to allow us to filter the column content for a given |
|
761 | - * column. |
|
762 | - * |
|
763 | - * @param EE_Base_Class $item The current item |
|
764 | - * @since 3.1.0 |
|
765 | - */ |
|
766 | - public function single_row_columns($item) |
|
767 | - { |
|
768 | - [$columns, $hidden, $sortable, $primary] = $this->get_column_info(); |
|
769 | - |
|
770 | - foreach ($columns as $column_name => $column_display_name) { |
|
771 | - /** |
|
772 | - * With WordPress version 4.3.RC+ WordPress started using the hidden css class to control whether columns |
|
773 | - * are hidden or not instead of using "display:none;". This bit of code provides backward compat. |
|
774 | - */ |
|
775 | - $hidden_class = in_array($column_name, $hidden) ? ' hidden' : ''; |
|
776 | - |
|
777 | - $classes = $column_name . ' column-' . $column_name . $hidden_class; |
|
778 | - if ($primary === $column_name) { |
|
779 | - $classes .= ' has-row-actions column-primary'; |
|
780 | - } |
|
781 | - |
|
782 | - $data = ' data-colname="' . wp_strip_all_tags($column_display_name) . '"'; |
|
783 | - |
|
784 | - $class = 'class="' . esc_attr($classes) . '"'; |
|
785 | - |
|
786 | - $attributes = "$class$data"; |
|
787 | - |
|
788 | - if ($column_name === 'cb') { |
|
789 | - echo '<th scope="row" class="check-column">'; |
|
790 | - echo apply_filters( |
|
791 | - 'FHEE__EE_Admin_List_Table__single_row_columns__column_cb_content', |
|
792 | - $this->column_cb($item), // already escaped |
|
793 | - $item, |
|
794 | - $this |
|
795 | - ); |
|
796 | - echo '</th>'; |
|
797 | - } elseif (method_exists($this, "column_$column_name")) { |
|
798 | - echo "<td $attributes>"; // already escaped |
|
799 | - echo apply_filters( |
|
800 | - 'FHEE__EE_Admin_List_Table__single_row_columns__column_' . $column_name . '__column_content', |
|
801 | - call_user_func([$this, "column_$column_name"], $item), |
|
802 | - $item, |
|
803 | - $this |
|
804 | - ); |
|
805 | - echo wp_kses($this->handle_row_actions($item, $column_name, $primary), AllowedTags::getWithFormTags()); |
|
806 | - echo "</td>"; |
|
807 | - } else { |
|
808 | - echo "<td $attributes>"; // already escaped |
|
809 | - echo apply_filters( |
|
810 | - 'FHEE__EE_Admin_List_Table__single_row_columns__column_default__column_content', |
|
811 | - $this->column_default($item, $column_name), |
|
812 | - $item, |
|
813 | - $column_name, |
|
814 | - $this |
|
815 | - ); |
|
816 | - echo wp_kses($this->handle_row_actions($item, $column_name, $primary), AllowedTags::getWithFormTags()); |
|
817 | - echo "</td>"; |
|
818 | - } |
|
819 | - } |
|
820 | - } |
|
821 | - |
|
822 | - |
|
823 | - /** |
|
824 | - * Extra controls to be displayed between bulk actions and pagination |
|
825 | - * |
|
826 | - * @access public |
|
827 | - * @param string $which |
|
828 | - * @throws EE_Error |
|
829 | - */ |
|
830 | - public function extra_tablenav($which) |
|
831 | - { |
|
832 | - if ($which === 'top') { |
|
833 | - $this->_filters(); |
|
834 | - } elseif ($this->_bottom_buttons) { |
|
835 | - echo '<div class="list-table-bottom-buttons alignleft actions">'; |
|
836 | - foreach ($this->_bottom_buttons as $type => $action) { |
|
837 | - $route = $action['route'] ?? ''; |
|
838 | - $extra_request = $action['extra_request'] ?? []; |
|
839 | - $btn_class = $action['btn_class'] ?? 'button button--secondary'; |
|
840 | - // already escaped |
|
841 | - echo wp_kses( |
|
842 | - $this->_admin_page->get_action_link_or_button( |
|
843 | - $route, |
|
844 | - $type, |
|
845 | - $extra_request, |
|
846 | - $btn_class |
|
847 | - ), |
|
848 | - AllowedTags::getWithFormTags() |
|
849 | - ); |
|
850 | - } |
|
851 | - do_action('AHEE__EE_Admin_List_Table__extra_tablenav__after_bottom_buttons', $this, $this->_screen); |
|
852 | - echo '</div>'; |
|
853 | - } |
|
854 | - } |
|
855 | - |
|
856 | - |
|
857 | - /** |
|
858 | - * Get an associative array ( option_name => option_title ) with the list |
|
859 | - * of bulk actions available on this table. |
|
860 | - * |
|
861 | - * @return array |
|
862 | - * @since 3.1.0 |
|
863 | - * @access protected |
|
864 | - */ |
|
865 | - public function get_bulk_actions() |
|
866 | - { |
|
867 | - return (array) $this->_get_bulk_actions(); |
|
868 | - } |
|
869 | - |
|
870 | - |
|
871 | - /** |
|
872 | - * Processing bulk actions. |
|
873 | - */ |
|
874 | - public function process_bulk_action() |
|
875 | - { |
|
876 | - // this is not used it is handled by the child EE_Admin_Page class (routes). However, including here for |
|
877 | - // reference in case there is a case where it gets used. |
|
878 | - } |
|
879 | - |
|
880 | - |
|
881 | - /** |
|
882 | - * returns the EE admin page this list table is associated with |
|
883 | - * |
|
884 | - * @return EE_Admin_Page |
|
885 | - */ |
|
886 | - public function get_admin_page() |
|
887 | - { |
|
888 | - return $this->_admin_page; |
|
889 | - } |
|
890 | - |
|
891 | - |
|
892 | - /** |
|
893 | - * A "helper" function for all children to provide an html string of |
|
894 | - * actions to output in their content. It is preferable for child classes |
|
895 | - * to use this method for generating their actions content so that it's |
|
896 | - * filterable by plugins |
|
897 | - * |
|
898 | - * @param string $action_container what are the html container |
|
899 | - * elements for this actions string? |
|
900 | - * @param string $action_class What class is for the container |
|
901 | - * element. |
|
902 | - * @param string $action_items The contents for the action items |
|
903 | - * container. This is filtered before |
|
904 | - * returned. |
|
905 | - * @param string $action_id What id (optional) is used for the |
|
906 | - * container element. |
|
907 | - * @param EE_Base_Class $item The object for the column displaying |
|
908 | - * the actions. |
|
909 | - * @return string The assembled action elements container. |
|
910 | - */ |
|
911 | - protected function _action_string( |
|
912 | - $action_items, |
|
913 | - $item, |
|
914 | - $action_container = 'ul', |
|
915 | - $action_class = '', |
|
916 | - $action_id = '' |
|
917 | - ) { |
|
918 | - $action_class = ! empty($action_class) ? ' class="' . esc_attr($action_class) . '"' : ''; |
|
919 | - $action_id = ! empty($action_id) ? ' id="' . esc_attr($action_id) . '"' : ''; |
|
920 | - $open_tag = ! empty($action_container) ? '<' . $action_container . $action_class . $action_id . '>' : ''; |
|
921 | - $close_tag = ! empty($action_container) ? '</' . $action_container . '>' : ''; |
|
922 | - try { |
|
923 | - $content = apply_filters( |
|
924 | - 'FHEE__EE_Admin_List_Table___action_string__action_items', |
|
925 | - $action_items, |
|
926 | - $item, |
|
927 | - $this |
|
928 | - ); |
|
929 | - } catch (Exception $e) { |
|
930 | - if (WP_DEBUG) { |
|
931 | - EE_Error::add_error($e->getMessage(), __FILE__, __FUNCTION__, __LINE__); |
|
932 | - } |
|
933 | - $content = $action_items; |
|
934 | - } |
|
935 | - return "$open_tag$content$close_tag"; |
|
936 | - } |
|
937 | - |
|
938 | - |
|
939 | - /** |
|
940 | - * @return string |
|
941 | - */ |
|
942 | - protected function getReturnUrl() |
|
943 | - { |
|
944 | - $host = $this->_admin_page->get_request()->getServerParam('HTTP_HOST'); |
|
945 | - $uri = $this->_admin_page->get_request()->getServerParam('REQUEST_URI'); |
|
946 | - return urlencode(esc_url_raw("//$host$uri")); |
|
947 | - } |
|
948 | - |
|
949 | - |
|
950 | - /** |
|
951 | - * @param string $id |
|
952 | - * @param string $content |
|
953 | - * @param string $align start (default), center, end |
|
954 | - * @param string $layout row (default) or stack |
|
955 | - * @return string |
|
956 | - * @since 5.0.0.p |
|
957 | - */ |
|
958 | - protected function columnContent( |
|
959 | - string $id, |
|
960 | - string $content, |
|
961 | - string $align = 'start', |
|
962 | - string $layout = 'row' |
|
963 | - ): string { |
|
964 | - if (! isset($this->_columns[ $id ])) { |
|
965 | - throw new DomainException('missing column id'); |
|
966 | - } |
|
967 | - $heading = $id !== 'cb' ? $this->_columns[ $id ] : ''; |
|
968 | - $align = in_array($align, ['start', 'center', 'end']) ? $align : 'start'; |
|
969 | - $align = "ee-responsive-table-cell--$align"; |
|
970 | - $layout = $layout === 'row' ? 'ee-layout-row' : 'ee-layout-stack'; |
|
971 | - |
|
972 | - $html = "<div class='ee-responsive-table-cell ee-responsive-table-cell--column-$id $align $layout'>"; |
|
973 | - $html .= "<div class='ee-responsive-table-cell__heading'>$heading</div>"; |
|
974 | - $html .= "<div class='ee-responsive-table-cell__content $layout'>$content</div>"; |
|
975 | - $html .= "</div>"; |
|
976 | - return $html; |
|
977 | - } |
|
978 | - |
|
979 | - |
|
980 | - protected function actionsModalMenu($actions): string |
|
981 | - { |
|
982 | - return ' |
|
505 | + if ($which === 'top') { |
|
506 | + echo wp_kses($this->_get_hidden_fields(), AllowedTags::getWithFormTags()); |
|
507 | + } |
|
508 | + } |
|
509 | + |
|
510 | + |
|
511 | + /** |
|
512 | + * _filters |
|
513 | + * This receives the filters array from children _get_table_filters() and assembles the string including the filter |
|
514 | + * button. |
|
515 | + * |
|
516 | + * @access private |
|
517 | + * @return void echos html showing filters |
|
518 | + */ |
|
519 | + private function _filters(): void |
|
520 | + { |
|
521 | + $classname = get_class($this); |
|
522 | + $filters = apply_filters( |
|
523 | + "FHEE__{$classname}__filters", |
|
524 | + $this->_get_table_filters(), |
|
525 | + $this, |
|
526 | + $this->_screen |
|
527 | + ); |
|
528 | + |
|
529 | + if (empty($filters)) { |
|
530 | + return; |
|
531 | + } |
|
532 | + |
|
533 | + $this->admin_list_table_filters->filters( |
|
534 | + $filters, |
|
535 | + $this->get_admin_page()->get_current_page_view_url() |
|
536 | + ); |
|
537 | + } |
|
538 | + |
|
539 | + |
|
540 | + /** |
|
541 | + * Callback for 'list_table_primary_column' WordPress filter |
|
542 | + * If child EE_Admin_List_Table classes set the _primary_column property then that will be set as the primary |
|
543 | + * column when class is instantiated. |
|
544 | + * |
|
545 | + * @param string $column_name |
|
546 | + * @return string |
|
547 | + * @see WP_List_Table::get_primary_column_name |
|
548 | + */ |
|
549 | + public function set_primary_column($column_name) |
|
550 | + { |
|
551 | + return ! empty($this->_primary_column) ? $this->_primary_column : $column_name; |
|
552 | + } |
|
553 | + |
|
554 | + |
|
555 | + /** |
|
556 | + * |
|
557 | + */ |
|
558 | + public function prepare_items() |
|
559 | + { |
|
560 | + $this->_set_column_info(); |
|
561 | + $this->process_bulk_action(); |
|
562 | + |
|
563 | + $this->items = $this->_data; |
|
564 | + $this->set_pagination_args( |
|
565 | + [ |
|
566 | + 'total_items' => $this->_all_data_count, |
|
567 | + 'per_page' => $this->_per_page, |
|
568 | + 'total_pages' => (int) ceil($this->_all_data_count / $this->_per_page), |
|
569 | + ] |
|
570 | + ); |
|
571 | + } |
|
572 | + |
|
573 | + |
|
574 | + /** |
|
575 | + * @param object|array $item |
|
576 | + * @return string html content for the column |
|
577 | + */ |
|
578 | + protected function column_cb($item) |
|
579 | + { |
|
580 | + return ''; |
|
581 | + } |
|
582 | + |
|
583 | + |
|
584 | + /** |
|
585 | + * This column is the default for when there is no defined column method for a registered column. |
|
586 | + * This can be overridden by child classes, but allows for hooking in for custom columns. |
|
587 | + * |
|
588 | + * @param EE_Base_Class $item |
|
589 | + * @param string $column_name The column being called. |
|
590 | + * @return string html content for the column |
|
591 | + */ |
|
592 | + public function column_default($item, $column_name) |
|
593 | + { |
|
594 | + /** |
|
595 | + * Dynamic hook allowing for adding additional column content in this list table. |
|
596 | + * Note that $this->screen->id is in the format |
|
597 | + * {sanitize_title($top_level_menu_label)}_page_{$espresso_admin_page_slug}. So for the messages list |
|
598 | + * table it is: event-espresso_page_espresso_messages. |
|
599 | + * However, take note that if the top level menu label has been translated (i.e. "Event Espresso"). then the |
|
600 | + * hook prefix ("event-espresso") will be different. |
|
601 | + */ |
|
602 | + ob_start(); |
|
603 | + do_action( |
|
604 | + 'AHEE__EE_Admin_List_Table__column_' . $column_name . '__' . $this->screen->id, |
|
605 | + $item, |
|
606 | + $this->_screen |
|
607 | + ); |
|
608 | + $content = ob_get_clean(); |
|
609 | + return $column_name === 'actions' ? $this->actionsModalMenu($content) : $content; |
|
610 | + } |
|
611 | + |
|
612 | + |
|
613 | + /** |
|
614 | + * Get a list of columns. The format is: |
|
615 | + * 'internal-name' => 'Title' |
|
616 | + * |
|
617 | + * @return array |
|
618 | + * @since 3.1.0 |
|
619 | + * @access public |
|
620 | + * @abstract |
|
621 | + */ |
|
622 | + public function get_columns() |
|
623 | + { |
|
624 | + /** |
|
625 | + * Dynamic hook allowing for adding additional columns in this list table. |
|
626 | + * Note that $this->screen->id is in the format |
|
627 | + * {sanitize_title($top_level_menu_label)}_page_{$espresso_admin_page_slug}. So for the messages list |
|
628 | + * table it is: event-espresso_page_espresso_messages. |
|
629 | + * However, take note that if the top level menu label has been translated (i.e. "Event Espresso"). then the |
|
630 | + * hook prefix ("event-espresso") will be different. |
|
631 | + * |
|
632 | + * @var array |
|
633 | + */ |
|
634 | + return apply_filters("FHEE_manage_{$this->screen->id}_columns", $this->_columns, $this->_screen, $this); |
|
635 | + } |
|
636 | + |
|
637 | + |
|
638 | + /** |
|
639 | + * Get an associative array ( id => link ) with the list |
|
640 | + * of views available on this table. |
|
641 | + * |
|
642 | + * @return array |
|
643 | + * @since 3.1.0 |
|
644 | + * @access protected |
|
645 | + */ |
|
646 | + public function get_views() |
|
647 | + { |
|
648 | + return $this->_views; |
|
649 | + } |
|
650 | + |
|
651 | + |
|
652 | + /** |
|
653 | + * Generate the views html. |
|
654 | + */ |
|
655 | + public function display_views() |
|
656 | + { |
|
657 | + $views = $this->get_views(); |
|
658 | + $assembled_views = []; |
|
659 | + |
|
660 | + if (empty($views)) { |
|
661 | + return; |
|
662 | + } |
|
663 | + echo "<ul class='subsubsub'>\n"; |
|
664 | + foreach ($views as $view) { |
|
665 | + $count = ! empty($view['count']) ? absint($view['count']) : 0; |
|
666 | + if (isset($view['slug'], $view['class'], $view['url'], $view['label'])) { |
|
667 | + $filter = "<li"; |
|
668 | + $filter .= $view['class'] ? " class='" . esc_attr($view['class']) . "'" : ''; |
|
669 | + $filter .= ">"; |
|
670 | + $filter .= '<a href="' . esc_url_raw($view['url']) . '">' . esc_html( |
|
671 | + $view['label'] |
|
672 | + ) . '</a>'; |
|
673 | + $filter .= '<span class="count">(' . $count . ')</span>'; |
|
674 | + $filter .= '</li>'; |
|
675 | + $assembled_views[ $view['slug'] ] = $filter; |
|
676 | + } |
|
677 | + } |
|
678 | + |
|
679 | + echo ! empty($assembled_views) |
|
680 | + ? implode("<li style='margin:0 .5rem;'>|</li>", $assembled_views) |
|
681 | + : ''; |
|
682 | + echo "</ul>"; |
|
683 | + } |
|
684 | + |
|
685 | + |
|
686 | + /** |
|
687 | + * Generates content for a single row of the table |
|
688 | + * |
|
689 | + * @param EE_Base_Class $item The current item |
|
690 | + * @since 4.1 |
|
691 | + * @access public |
|
692 | + */ |
|
693 | + public function single_row($item) |
|
694 | + { |
|
695 | + $row_class = $this->_get_row_class($item); |
|
696 | + echo '<tr class="' . esc_attr($row_class) . '">'; |
|
697 | + $this->single_row_columns($item); // already escaped |
|
698 | + echo '</tr>'; |
|
699 | + } |
|
700 | + |
|
701 | + |
|
702 | + /** |
|
703 | + * This simply sets up the row class for the table rows. |
|
704 | + * Allows for easier overriding of child methods for setting up sorting. |
|
705 | + * |
|
706 | + * @param EE_Base_Class $item the current item |
|
707 | + * @return string |
|
708 | + */ |
|
709 | + protected function _get_row_class($item) |
|
710 | + { |
|
711 | + static $row_class = ''; |
|
712 | + $row_class = ($row_class === '' ? 'alternate' : ''); |
|
713 | + |
|
714 | + $new_row_class = $row_class; |
|
715 | + |
|
716 | + if (! empty($this->_ajax_sorting_callback)) { |
|
717 | + $new_row_class .= ' rowsortable'; |
|
718 | + } |
|
719 | + |
|
720 | + return $new_row_class; |
|
721 | + } |
|
722 | + |
|
723 | + |
|
724 | + /** |
|
725 | + * @return array |
|
726 | + */ |
|
727 | + public function get_sortable_columns() |
|
728 | + { |
|
729 | + return (array) $this->_sortable_columns; |
|
730 | + } |
|
731 | + |
|
732 | + |
|
733 | + /** |
|
734 | + * @return string |
|
735 | + */ |
|
736 | + public function get_ajax_sorting_callback() |
|
737 | + { |
|
738 | + return $this->_ajax_sorting_callback; |
|
739 | + } |
|
740 | + |
|
741 | + |
|
742 | + /** |
|
743 | + * @return array |
|
744 | + */ |
|
745 | + public function get_hidden_columns(): array |
|
746 | + { |
|
747 | + $user_id = get_current_user_id(); |
|
748 | + $has_default = get_user_option('default' . $this->screen->id . 'columnshidden', $user_id); |
|
749 | + if (empty($has_default) && ! empty($this->_hidden_columns)) { |
|
750 | + update_user_option($user_id, 'default' . $this->screen->id . 'columnshidden', true); |
|
751 | + update_user_option($user_id, 'manage' . $this->screen->id . 'columnshidden', $this->_hidden_columns, true); |
|
752 | + } |
|
753 | + $ref = 'manage' . $this->screen->id . 'columnshidden'; |
|
754 | + return (array) get_user_option($ref, $user_id); |
|
755 | + } |
|
756 | + |
|
757 | + |
|
758 | + /** |
|
759 | + * Generates the columns for a single row of the table. |
|
760 | + * Overridden from wp_list_table so as to allow us to filter the column content for a given |
|
761 | + * column. |
|
762 | + * |
|
763 | + * @param EE_Base_Class $item The current item |
|
764 | + * @since 3.1.0 |
|
765 | + */ |
|
766 | + public function single_row_columns($item) |
|
767 | + { |
|
768 | + [$columns, $hidden, $sortable, $primary] = $this->get_column_info(); |
|
769 | + |
|
770 | + foreach ($columns as $column_name => $column_display_name) { |
|
771 | + /** |
|
772 | + * With WordPress version 4.3.RC+ WordPress started using the hidden css class to control whether columns |
|
773 | + * are hidden or not instead of using "display:none;". This bit of code provides backward compat. |
|
774 | + */ |
|
775 | + $hidden_class = in_array($column_name, $hidden) ? ' hidden' : ''; |
|
776 | + |
|
777 | + $classes = $column_name . ' column-' . $column_name . $hidden_class; |
|
778 | + if ($primary === $column_name) { |
|
779 | + $classes .= ' has-row-actions column-primary'; |
|
780 | + } |
|
781 | + |
|
782 | + $data = ' data-colname="' . wp_strip_all_tags($column_display_name) . '"'; |
|
783 | + |
|
784 | + $class = 'class="' . esc_attr($classes) . '"'; |
|
785 | + |
|
786 | + $attributes = "$class$data"; |
|
787 | + |
|
788 | + if ($column_name === 'cb') { |
|
789 | + echo '<th scope="row" class="check-column">'; |
|
790 | + echo apply_filters( |
|
791 | + 'FHEE__EE_Admin_List_Table__single_row_columns__column_cb_content', |
|
792 | + $this->column_cb($item), // already escaped |
|
793 | + $item, |
|
794 | + $this |
|
795 | + ); |
|
796 | + echo '</th>'; |
|
797 | + } elseif (method_exists($this, "column_$column_name")) { |
|
798 | + echo "<td $attributes>"; // already escaped |
|
799 | + echo apply_filters( |
|
800 | + 'FHEE__EE_Admin_List_Table__single_row_columns__column_' . $column_name . '__column_content', |
|
801 | + call_user_func([$this, "column_$column_name"], $item), |
|
802 | + $item, |
|
803 | + $this |
|
804 | + ); |
|
805 | + echo wp_kses($this->handle_row_actions($item, $column_name, $primary), AllowedTags::getWithFormTags()); |
|
806 | + echo "</td>"; |
|
807 | + } else { |
|
808 | + echo "<td $attributes>"; // already escaped |
|
809 | + echo apply_filters( |
|
810 | + 'FHEE__EE_Admin_List_Table__single_row_columns__column_default__column_content', |
|
811 | + $this->column_default($item, $column_name), |
|
812 | + $item, |
|
813 | + $column_name, |
|
814 | + $this |
|
815 | + ); |
|
816 | + echo wp_kses($this->handle_row_actions($item, $column_name, $primary), AllowedTags::getWithFormTags()); |
|
817 | + echo "</td>"; |
|
818 | + } |
|
819 | + } |
|
820 | + } |
|
821 | + |
|
822 | + |
|
823 | + /** |
|
824 | + * Extra controls to be displayed between bulk actions and pagination |
|
825 | + * |
|
826 | + * @access public |
|
827 | + * @param string $which |
|
828 | + * @throws EE_Error |
|
829 | + */ |
|
830 | + public function extra_tablenav($which) |
|
831 | + { |
|
832 | + if ($which === 'top') { |
|
833 | + $this->_filters(); |
|
834 | + } elseif ($this->_bottom_buttons) { |
|
835 | + echo '<div class="list-table-bottom-buttons alignleft actions">'; |
|
836 | + foreach ($this->_bottom_buttons as $type => $action) { |
|
837 | + $route = $action['route'] ?? ''; |
|
838 | + $extra_request = $action['extra_request'] ?? []; |
|
839 | + $btn_class = $action['btn_class'] ?? 'button button--secondary'; |
|
840 | + // already escaped |
|
841 | + echo wp_kses( |
|
842 | + $this->_admin_page->get_action_link_or_button( |
|
843 | + $route, |
|
844 | + $type, |
|
845 | + $extra_request, |
|
846 | + $btn_class |
|
847 | + ), |
|
848 | + AllowedTags::getWithFormTags() |
|
849 | + ); |
|
850 | + } |
|
851 | + do_action('AHEE__EE_Admin_List_Table__extra_tablenav__after_bottom_buttons', $this, $this->_screen); |
|
852 | + echo '</div>'; |
|
853 | + } |
|
854 | + } |
|
855 | + |
|
856 | + |
|
857 | + /** |
|
858 | + * Get an associative array ( option_name => option_title ) with the list |
|
859 | + * of bulk actions available on this table. |
|
860 | + * |
|
861 | + * @return array |
|
862 | + * @since 3.1.0 |
|
863 | + * @access protected |
|
864 | + */ |
|
865 | + public function get_bulk_actions() |
|
866 | + { |
|
867 | + return (array) $this->_get_bulk_actions(); |
|
868 | + } |
|
869 | + |
|
870 | + |
|
871 | + /** |
|
872 | + * Processing bulk actions. |
|
873 | + */ |
|
874 | + public function process_bulk_action() |
|
875 | + { |
|
876 | + // this is not used it is handled by the child EE_Admin_Page class (routes). However, including here for |
|
877 | + // reference in case there is a case where it gets used. |
|
878 | + } |
|
879 | + |
|
880 | + |
|
881 | + /** |
|
882 | + * returns the EE admin page this list table is associated with |
|
883 | + * |
|
884 | + * @return EE_Admin_Page |
|
885 | + */ |
|
886 | + public function get_admin_page() |
|
887 | + { |
|
888 | + return $this->_admin_page; |
|
889 | + } |
|
890 | + |
|
891 | + |
|
892 | + /** |
|
893 | + * A "helper" function for all children to provide an html string of |
|
894 | + * actions to output in their content. It is preferable for child classes |
|
895 | + * to use this method for generating their actions content so that it's |
|
896 | + * filterable by plugins |
|
897 | + * |
|
898 | + * @param string $action_container what are the html container |
|
899 | + * elements for this actions string? |
|
900 | + * @param string $action_class What class is for the container |
|
901 | + * element. |
|
902 | + * @param string $action_items The contents for the action items |
|
903 | + * container. This is filtered before |
|
904 | + * returned. |
|
905 | + * @param string $action_id What id (optional) is used for the |
|
906 | + * container element. |
|
907 | + * @param EE_Base_Class $item The object for the column displaying |
|
908 | + * the actions. |
|
909 | + * @return string The assembled action elements container. |
|
910 | + */ |
|
911 | + protected function _action_string( |
|
912 | + $action_items, |
|
913 | + $item, |
|
914 | + $action_container = 'ul', |
|
915 | + $action_class = '', |
|
916 | + $action_id = '' |
|
917 | + ) { |
|
918 | + $action_class = ! empty($action_class) ? ' class="' . esc_attr($action_class) . '"' : ''; |
|
919 | + $action_id = ! empty($action_id) ? ' id="' . esc_attr($action_id) . '"' : ''; |
|
920 | + $open_tag = ! empty($action_container) ? '<' . $action_container . $action_class . $action_id . '>' : ''; |
|
921 | + $close_tag = ! empty($action_container) ? '</' . $action_container . '>' : ''; |
|
922 | + try { |
|
923 | + $content = apply_filters( |
|
924 | + 'FHEE__EE_Admin_List_Table___action_string__action_items', |
|
925 | + $action_items, |
|
926 | + $item, |
|
927 | + $this |
|
928 | + ); |
|
929 | + } catch (Exception $e) { |
|
930 | + if (WP_DEBUG) { |
|
931 | + EE_Error::add_error($e->getMessage(), __FILE__, __FUNCTION__, __LINE__); |
|
932 | + } |
|
933 | + $content = $action_items; |
|
934 | + } |
|
935 | + return "$open_tag$content$close_tag"; |
|
936 | + } |
|
937 | + |
|
938 | + |
|
939 | + /** |
|
940 | + * @return string |
|
941 | + */ |
|
942 | + protected function getReturnUrl() |
|
943 | + { |
|
944 | + $host = $this->_admin_page->get_request()->getServerParam('HTTP_HOST'); |
|
945 | + $uri = $this->_admin_page->get_request()->getServerParam('REQUEST_URI'); |
|
946 | + return urlencode(esc_url_raw("//$host$uri")); |
|
947 | + } |
|
948 | + |
|
949 | + |
|
950 | + /** |
|
951 | + * @param string $id |
|
952 | + * @param string $content |
|
953 | + * @param string $align start (default), center, end |
|
954 | + * @param string $layout row (default) or stack |
|
955 | + * @return string |
|
956 | + * @since 5.0.0.p |
|
957 | + */ |
|
958 | + protected function columnContent( |
|
959 | + string $id, |
|
960 | + string $content, |
|
961 | + string $align = 'start', |
|
962 | + string $layout = 'row' |
|
963 | + ): string { |
|
964 | + if (! isset($this->_columns[ $id ])) { |
|
965 | + throw new DomainException('missing column id'); |
|
966 | + } |
|
967 | + $heading = $id !== 'cb' ? $this->_columns[ $id ] : ''; |
|
968 | + $align = in_array($align, ['start', 'center', 'end']) ? $align : 'start'; |
|
969 | + $align = "ee-responsive-table-cell--$align"; |
|
970 | + $layout = $layout === 'row' ? 'ee-layout-row' : 'ee-layout-stack'; |
|
971 | + |
|
972 | + $html = "<div class='ee-responsive-table-cell ee-responsive-table-cell--column-$id $align $layout'>"; |
|
973 | + $html .= "<div class='ee-responsive-table-cell__heading'>$heading</div>"; |
|
974 | + $html .= "<div class='ee-responsive-table-cell__content $layout'>$content</div>"; |
|
975 | + $html .= "</div>"; |
|
976 | + return $html; |
|
977 | + } |
|
978 | + |
|
979 | + |
|
980 | + protected function actionsModalMenu($actions): string |
|
981 | + { |
|
982 | + return ' |
|
983 | 983 | <div class="ee-modal-menu"> |
984 | 984 | <button class="ee-modal-menu__button button button--secondary button--icon-only ee-aria-tooltip" |
985 | 985 | aria-label="' . esc_attr__('list table actions menu', 'event_espresso') . '" |
@@ -991,44 +991,44 @@ discard block |
||
991 | 991 | ' . $actions . ' |
992 | 992 | </div> |
993 | 993 | </div>'; |
994 | - } |
|
994 | + } |
|
995 | 995 | |
996 | 996 | |
997 | - public function actionsColumnHeader(): string |
|
998 | - { |
|
999 | - return ' |
|
997 | + public function actionsColumnHeader(): string |
|
998 | + { |
|
999 | + return ' |
|
1000 | 1000 | <span class="ee-actions-column-header-wrap"> |
1001 | 1001 | <span class="dashicons dashicons-screenoptions"></span> |
1002 | 1002 | <span class="ee-actions-column-header">' . esc_html__('Actions', 'event_espresso') . '</span> |
1003 | 1003 | </span>'; |
1004 | - } |
|
1005 | - |
|
1006 | - |
|
1007 | - protected function getActionLink(string $url, string $display_text, string $label, $class = ''): string |
|
1008 | - { |
|
1009 | - $class = ! empty($class) ? "$class ee-list-table-action" : 'ee-list-table-action'; |
|
1010 | - $class = ! empty($label) ? "$class ee-aria-tooltip" : $class; |
|
1011 | - $label = ! empty($label) ? " aria-label='$label'" : ''; |
|
1012 | - return "<a href='$url' class='$class'$label>$display_text</a>"; |
|
1013 | - } |
|
1014 | - |
|
1015 | - |
|
1016 | - /** |
|
1017 | - * Override the search box method of WP List Table to include a reset button |
|
1018 | - * |
|
1019 | - * @param string $text The 'submit' button label. |
|
1020 | - * @param string $input_id ID attribute value for the search input field. |
|
1021 | - */ |
|
1022 | - public function search_box($text, $input_id) |
|
1023 | - { |
|
1024 | - if (empty($_REQUEST['s']) && ! $this->has_items()) { |
|
1025 | - return; |
|
1026 | - } |
|
1027 | - |
|
1028 | - $this->admin_list_table_filters->searchBox( |
|
1029 | - $text, |
|
1030 | - $input_id, |
|
1031 | - $this->get_admin_page()->get_current_page_view_url() |
|
1032 | - ); |
|
1033 | - } |
|
1004 | + } |
|
1005 | + |
|
1006 | + |
|
1007 | + protected function getActionLink(string $url, string $display_text, string $label, $class = ''): string |
|
1008 | + { |
|
1009 | + $class = ! empty($class) ? "$class ee-list-table-action" : 'ee-list-table-action'; |
|
1010 | + $class = ! empty($label) ? "$class ee-aria-tooltip" : $class; |
|
1011 | + $label = ! empty($label) ? " aria-label='$label'" : ''; |
|
1012 | + return "<a href='$url' class='$class'$label>$display_text</a>"; |
|
1013 | + } |
|
1014 | + |
|
1015 | + |
|
1016 | + /** |
|
1017 | + * Override the search box method of WP List Table to include a reset button |
|
1018 | + * |
|
1019 | + * @param string $text The 'submit' button label. |
|
1020 | + * @param string $input_id ID attribute value for the search input field. |
|
1021 | + */ |
|
1022 | + public function search_box($text, $input_id) |
|
1023 | + { |
|
1024 | + if (empty($_REQUEST['s']) && ! $this->has_items()) { |
|
1025 | + return; |
|
1026 | + } |
|
1027 | + |
|
1028 | + $this->admin_list_table_filters->searchBox( |
|
1029 | + $text, |
|
1030 | + $input_id, |
|
1031 | + $this->get_admin_page()->get_current_page_view_url() |
|
1032 | + ); |
|
1033 | + } |
|
1034 | 1034 | } |
@@ -5,8 +5,8 @@ discard block |
||
5 | 5 | use EventEspresso\core\services\request\RequestInterface; |
6 | 6 | use EventEspresso\core\services\request\sanitizers\AllowedTags; |
7 | 7 | |
8 | -if (! class_exists('WP_List_Table')) { |
|
9 | - require_once ABSPATH . 'wp-admin/includes/class-wp-list-table.php'; |
|
8 | +if ( ! class_exists('WP_List_Table')) { |
|
9 | + require_once ABSPATH.'wp-admin/includes/class-wp-list-table.php'; |
|
10 | 10 | } |
11 | 11 | |
12 | 12 | |
@@ -236,13 +236,13 @@ discard block |
||
236 | 236 | $this->_view = $this->_admin_page->get_view(); |
237 | 237 | $this->_views = $this->_admin_page->get_list_table_view_RLs(); |
238 | 238 | $this->_current_page = $this->get_pagenum(); |
239 | - $this->_screen = $this->_admin_page->get_current_page() . '_' . $this->_admin_page->get_current_view(); |
|
239 | + $this->_screen = $this->_admin_page->get_current_page().'_'.$this->_admin_page->get_current_view(); |
|
240 | 240 | $this->_yes_no = [ |
241 | 241 | esc_html__('No', 'event_espresso'), |
242 | 242 | esc_html__('Yes', 'event_espresso'), |
243 | 243 | ]; |
244 | 244 | |
245 | - $this->_per_page = $this->get_items_per_page($this->_screen . '_per_page'); |
|
245 | + $this->_per_page = $this->get_items_per_page($this->_screen.'_per_page'); |
|
246 | 246 | |
247 | 247 | $this->admin_list_table_filters = $filters instanceof AdminListTableFilters |
248 | 248 | ? $filters |
@@ -329,14 +329,14 @@ discard block |
||
329 | 329 | $action = $this->request->getRequestParam('action', $action); |
330 | 330 | // if action is STILL empty, then we set it to default |
331 | 331 | $action = empty($action) || $action === '-1' ? 'default' : $action; |
332 | - $field = '<input type="hidden" name="page" value="' . esc_attr($page) . '" />' . "\n"; |
|
333 | - $field .= '<input type="hidden" name="route" value="' . esc_attr($action) . '" />' . "\n"; |
|
334 | - $field .= '<input type="hidden" name="perpage" value="' . esc_attr($this->_per_page) . '" />' . "\n"; |
|
332 | + $field = '<input type="hidden" name="page" value="'.esc_attr($page).'" />'."\n"; |
|
333 | + $field .= '<input type="hidden" name="route" value="'.esc_attr($action).'" />'."\n"; |
|
334 | + $field .= '<input type="hidden" name="perpage" value="'.esc_attr($this->_per_page).'" />'."\n"; |
|
335 | 335 | |
336 | 336 | $bulk_actions = $this->_get_bulk_actions(); |
337 | 337 | foreach ($bulk_actions as $bulk_action => $label) { |
338 | - $field .= '<input type="hidden" name="' . $bulk_action . '_nonce"' |
|
339 | - . ' value="' . wp_create_nonce($bulk_action . '_nonce') . '" />' . "\n"; |
|
338 | + $field .= '<input type="hidden" name="'.$bulk_action.'_nonce"' |
|
339 | + . ' value="'.wp_create_nonce($bulk_action.'_nonce').'" />'."\n"; |
|
340 | 340 | } |
341 | 341 | |
342 | 342 | return $field; |
@@ -388,11 +388,11 @@ discard block |
||
388 | 388 | |
389 | 389 | $data = (array) $data; |
390 | 390 | |
391 | - if (! isset($data[1])) { |
|
391 | + if ( ! isset($data[1])) { |
|
392 | 392 | $_data[1] = false; |
393 | 393 | } |
394 | 394 | |
395 | - $sortable[ $id ] = $_data; |
|
395 | + $sortable[$id] = $_data; |
|
396 | 396 | } |
397 | 397 | $primary = $this->get_primary_column_name(); |
398 | 398 | $this->_column_headers = [$columns, $hidden, $sortable, $primary]; |
@@ -452,7 +452,7 @@ discard block |
||
452 | 452 | // for that page route and skip adding the bulk action if no access for the current logged in user. |
453 | 453 | foreach ($args['bulk_action'] as $route => $label) { |
454 | 454 | if ($this->_admin_page->check_user_access($route, true)) { |
455 | - $actions[ $route ] = $label; |
|
455 | + $actions[$route] = $label; |
|
456 | 456 | } |
457 | 457 | } |
458 | 458 | } |
@@ -471,7 +471,7 @@ discard block |
||
471 | 471 | public function display_tablenav($which) |
472 | 472 | { |
473 | 473 | if ('top' === $which) { |
474 | - wp_nonce_field('bulk-' . $this->_args['plural']); |
|
474 | + wp_nonce_field('bulk-'.$this->_args['plural']); |
|
475 | 475 | } |
476 | 476 | |
477 | 477 | ob_start(); |
@@ -601,7 +601,7 @@ discard block |
||
601 | 601 | */ |
602 | 602 | ob_start(); |
603 | 603 | do_action( |
604 | - 'AHEE__EE_Admin_List_Table__column_' . $column_name . '__' . $this->screen->id, |
|
604 | + 'AHEE__EE_Admin_List_Table__column_'.$column_name.'__'.$this->screen->id, |
|
605 | 605 | $item, |
606 | 606 | $this->_screen |
607 | 607 | ); |
@@ -664,15 +664,15 @@ discard block |
||
664 | 664 | foreach ($views as $view) { |
665 | 665 | $count = ! empty($view['count']) ? absint($view['count']) : 0; |
666 | 666 | if (isset($view['slug'], $view['class'], $view['url'], $view['label'])) { |
667 | - $filter = "<li"; |
|
668 | - $filter .= $view['class'] ? " class='" . esc_attr($view['class']) . "'" : ''; |
|
667 | + $filter = "<li"; |
|
668 | + $filter .= $view['class'] ? " class='".esc_attr($view['class'])."'" : ''; |
|
669 | 669 | $filter .= ">"; |
670 | - $filter .= '<a href="' . esc_url_raw($view['url']) . '">' . esc_html( |
|
670 | + $filter .= '<a href="'.esc_url_raw($view['url']).'">'.esc_html( |
|
671 | 671 | $view['label'] |
672 | - ) . '</a>'; |
|
673 | - $filter .= '<span class="count">(' . $count . ')</span>'; |
|
672 | + ).'</a>'; |
|
673 | + $filter .= '<span class="count">('.$count.')</span>'; |
|
674 | 674 | $filter .= '</li>'; |
675 | - $assembled_views[ $view['slug'] ] = $filter; |
|
675 | + $assembled_views[$view['slug']] = $filter; |
|
676 | 676 | } |
677 | 677 | } |
678 | 678 | |
@@ -693,7 +693,7 @@ discard block |
||
693 | 693 | public function single_row($item) |
694 | 694 | { |
695 | 695 | $row_class = $this->_get_row_class($item); |
696 | - echo '<tr class="' . esc_attr($row_class) . '">'; |
|
696 | + echo '<tr class="'.esc_attr($row_class).'">'; |
|
697 | 697 | $this->single_row_columns($item); // already escaped |
698 | 698 | echo '</tr>'; |
699 | 699 | } |
@@ -713,7 +713,7 @@ discard block |
||
713 | 713 | |
714 | 714 | $new_row_class = $row_class; |
715 | 715 | |
716 | - if (! empty($this->_ajax_sorting_callback)) { |
|
716 | + if ( ! empty($this->_ajax_sorting_callback)) { |
|
717 | 717 | $new_row_class .= ' rowsortable'; |
718 | 718 | } |
719 | 719 | |
@@ -745,12 +745,12 @@ discard block |
||
745 | 745 | public function get_hidden_columns(): array |
746 | 746 | { |
747 | 747 | $user_id = get_current_user_id(); |
748 | - $has_default = get_user_option('default' . $this->screen->id . 'columnshidden', $user_id); |
|
748 | + $has_default = get_user_option('default'.$this->screen->id.'columnshidden', $user_id); |
|
749 | 749 | if (empty($has_default) && ! empty($this->_hidden_columns)) { |
750 | - update_user_option($user_id, 'default' . $this->screen->id . 'columnshidden', true); |
|
751 | - update_user_option($user_id, 'manage' . $this->screen->id . 'columnshidden', $this->_hidden_columns, true); |
|
750 | + update_user_option($user_id, 'default'.$this->screen->id.'columnshidden', true); |
|
751 | + update_user_option($user_id, 'manage'.$this->screen->id.'columnshidden', $this->_hidden_columns, true); |
|
752 | 752 | } |
753 | - $ref = 'manage' . $this->screen->id . 'columnshidden'; |
|
753 | + $ref = 'manage'.$this->screen->id.'columnshidden'; |
|
754 | 754 | return (array) get_user_option($ref, $user_id); |
755 | 755 | } |
756 | 756 | |
@@ -774,14 +774,14 @@ discard block |
||
774 | 774 | */ |
775 | 775 | $hidden_class = in_array($column_name, $hidden) ? ' hidden' : ''; |
776 | 776 | |
777 | - $classes = $column_name . ' column-' . $column_name . $hidden_class; |
|
777 | + $classes = $column_name.' column-'.$column_name.$hidden_class; |
|
778 | 778 | if ($primary === $column_name) { |
779 | 779 | $classes .= ' has-row-actions column-primary'; |
780 | 780 | } |
781 | 781 | |
782 | - $data = ' data-colname="' . wp_strip_all_tags($column_display_name) . '"'; |
|
782 | + $data = ' data-colname="'.wp_strip_all_tags($column_display_name).'"'; |
|
783 | 783 | |
784 | - $class = 'class="' . esc_attr($classes) . '"'; |
|
784 | + $class = 'class="'.esc_attr($classes).'"'; |
|
785 | 785 | |
786 | 786 | $attributes = "$class$data"; |
787 | 787 | |
@@ -797,7 +797,7 @@ discard block |
||
797 | 797 | } elseif (method_exists($this, "column_$column_name")) { |
798 | 798 | echo "<td $attributes>"; // already escaped |
799 | 799 | echo apply_filters( |
800 | - 'FHEE__EE_Admin_List_Table__single_row_columns__column_' . $column_name . '__column_content', |
|
800 | + 'FHEE__EE_Admin_List_Table__single_row_columns__column_'.$column_name.'__column_content', |
|
801 | 801 | call_user_func([$this, "column_$column_name"], $item), |
802 | 802 | $item, |
803 | 803 | $this |
@@ -915,10 +915,10 @@ discard block |
||
915 | 915 | $action_class = '', |
916 | 916 | $action_id = '' |
917 | 917 | ) { |
918 | - $action_class = ! empty($action_class) ? ' class="' . esc_attr($action_class) . '"' : ''; |
|
919 | - $action_id = ! empty($action_id) ? ' id="' . esc_attr($action_id) . '"' : ''; |
|
920 | - $open_tag = ! empty($action_container) ? '<' . $action_container . $action_class . $action_id . '>' : ''; |
|
921 | - $close_tag = ! empty($action_container) ? '</' . $action_container . '>' : ''; |
|
918 | + $action_class = ! empty($action_class) ? ' class="'.esc_attr($action_class).'"' : ''; |
|
919 | + $action_id = ! empty($action_id) ? ' id="'.esc_attr($action_id).'"' : ''; |
|
920 | + $open_tag = ! empty($action_container) ? '<'.$action_container.$action_class.$action_id.'>' : ''; |
|
921 | + $close_tag = ! empty($action_container) ? '</'.$action_container.'>' : ''; |
|
922 | 922 | try { |
923 | 923 | $content = apply_filters( |
924 | 924 | 'FHEE__EE_Admin_List_Table___action_string__action_items', |
@@ -961,10 +961,10 @@ discard block |
||
961 | 961 | string $align = 'start', |
962 | 962 | string $layout = 'row' |
963 | 963 | ): string { |
964 | - if (! isset($this->_columns[ $id ])) { |
|
964 | + if ( ! isset($this->_columns[$id])) { |
|
965 | 965 | throw new DomainException('missing column id'); |
966 | 966 | } |
967 | - $heading = $id !== 'cb' ? $this->_columns[ $id ] : ''; |
|
967 | + $heading = $id !== 'cb' ? $this->_columns[$id] : ''; |
|
968 | 968 | $align = in_array($align, ['start', 'center', 'end']) ? $align : 'start'; |
969 | 969 | $align = "ee-responsive-table-cell--$align"; |
970 | 970 | $layout = $layout === 'row' ? 'ee-layout-row' : 'ee-layout-stack'; |
@@ -982,13 +982,13 @@ discard block |
||
982 | 982 | return ' |
983 | 983 | <div class="ee-modal-menu"> |
984 | 984 | <button class="ee-modal-menu__button button button--secondary button--icon-only ee-aria-tooltip" |
985 | - aria-label="' . esc_attr__('list table actions menu', 'event_espresso') . '" |
|
985 | + aria-label="' . esc_attr__('list table actions menu', 'event_espresso').'" |
|
986 | 986 | > |
987 | 987 | <span class="dashicons dashicons-menu"></span> |
988 | 988 | </button> |
989 | 989 | <div class="ee-modal-menu__content ee-admin-container"> |
990 | 990 | <span class="ee-modal-menu__close dashicons dashicons-no"></span> |
991 | - ' . $actions . ' |
|
991 | + ' . $actions.' |
|
992 | 992 | </div> |
993 | 993 | </div>'; |
994 | 994 | } |
@@ -999,7 +999,7 @@ discard block |
||
999 | 999 | return ' |
1000 | 1000 | <span class="ee-actions-column-header-wrap"> |
1001 | 1001 | <span class="dashicons dashicons-screenoptions"></span> |
1002 | - <span class="ee-actions-column-header">' . esc_html__('Actions', 'event_espresso') . '</span> |
|
1002 | + <span class="ee-actions-column-header">' . esc_html__('Actions', 'event_espresso').'</span> |
|
1003 | 1003 | </span>'; |
1004 | 1004 | } |
1005 | 1005 |