PluginProbe ʕ •ᴥ•ʔ
Admin and Site Enhancements (ASE) / 3.4.0
Admin and Site Enhancements (ASE) v3.4.0
9.1.0 9.0.2 9.0.1 9.0.0 8.9.2 8.9.1 8.9.0 8.8.8 8.8.7 8.8.6 8.8.5 8.8.4 8.8.3 8.8.2 8.8.1 8.8.0 8.7.3 8.7.2 8.7.1 8.2.1 8.2.2 8.2.3 8.3.0 8.3.1 8.3.2 8.4.0 8.4.1 8.4.2 8.5.0 8.5.1 8.5.2 8.6.0 8.6.1 8.6.2 8.7.0 5.0.1 5.0.2 5.0.2.1 5.0.2.2 5.0.2.3 5.0.2.4 5.1.0 5.2.0 5.2.1 5.2.10 5.2.11 5.2.2 5.2.3 5.2.4 5.2.5 5.2.6 5.2.7 5.2.8 5.2.9 5.3.0 5.3.1 5.3.2 5.4.0 5.4.1 5.5.0 5.5.1 5.5.2 5.6.0 5.6.1 5.6.2 5.7.0 5.7.1 5.8.0 5.8.1 6.0.0 6.0.3 6.0.4 6.0.5 6.0.5.1 6.0.6 6.0.7 6.0.8.1 6.1.0 6.1.3 6.2.0 6.2.1 6.2.2 6.2.3 6.2.4 6.2.5 6.2.6 6.2.7 6.3.0 6.3.1 6.3.2 6.4.0 6.5.0 6.5.1 6.6.0 6.7.0 6.8.0 6.8.2 6.8.3 6.9.0 6.9.1 6.9.10 6.9.11 6.9.12 6.9.13.1 6.9.13.2 6.9.2 6.9.3 6.9.4 6.9.5 6.9.6 6.9.7 6.9.8 6.9.9 7.0.0 7.0.2 7.0.2.1 7.0.2.2 7.0.2.3 7.0.3 7.1.0 7.1.1 7.1.2 7.1.3 7.1.4 7.1.5 7.2.0 7.2.1 7.3.0 7.3.1 7.3.2 7.3.3 7.4.0 7.4.2 7.4.4 7.4.5 7.4.6 7.4.7 7.4.8 7.5.0 7.5.1 7.5.2 7.5.3 7.5.4 7.6.0 7.6.1 7.6.1.1 7.6.10 7.6.11 7.6.2 7.6.3 7.6.4 7.6.5 7.6.6 7.6.7 7.6.7.1 7.6.8 7.6.9 7.7.0 7.8.0 7.8.1 7.8.10 7.8.11 7.8.12 7.8.13 7.8.14 7.8.15 7.8.16 7.8.17 7.8.18 7.8.2 7.8.3 7.8.4 7.8.5 7.8.5.1 7.8.6 7.8.7 7.8.8 7.8.9 7.9.0 7.9.1 7.9.10 7.9.11 7.9.2 7.9.3 7.9.4 7.9.5 7.9.6 7.9.7 7.9.8 7.9.9 8.0.0 8.0.1 8.0.2 8.0.3 8.0.4 8.0.5 8.0.6 8.0.7 8.0.8 8.1.0 8.1.1 8.1.2 8.1.3 8.1.4 8.2.0 trunk 1.0.0 1.1.0 1.2.0 1.3.0 1.4.0 1.5.0 1.6.0 1.7.0 1.8.0 1.9.0 2.0.0 2.1.0 2.2.0 2.3.0 2.4.0 2.5.0 2.6.0 2.7.0 2.8.0 2.8.1 2.8.2 2.8.3 2.9.0 3.0.0 3.0.1 3.0.2 3.0.3 3.0.4 3.0.5 3.0.6 3.1.0 3.2.0 3.3.0 3.4.0 3.5.0 3.6.1 3.7.0 3.8.0 3.9.0 3.9.1 3.9.2 4.0.0 4.0.1 4.1.0 4.2.0 4.2.1 4.2.2 4.3.0 4.3.1 4.4.0 4.5.0 4.6.0 4.7.0 4.7.1 4.7.2 4.7.3 4.7.4 4.8.0 4.8.1 4.8.2 4.8.3 4.9.0 4.9.1 4.9.2 4.9.3 5.0.0
admin-site-enhancements / bootstrap.php
admin-site-enhancements Last commit date
assets 3 years ago classes 3 years ago vendor 3 years ago LICENSE.md 3 years ago README.md 3 years ago admin-site-enhancements.php 3 years ago bootstrap.php 3 years ago settings.php 3 years ago
bootstrap.php
384 lines
1 <?php
2
3 // We're using the singleton design pattern
4 // https://code.tutsplus.com/articles/design-patterns-in-wordpress-the-singleton-pattern--wp-31621
5 // https://carlalexander.ca/singletons-in-wordpress/
6 // https://torquemag.io/2016/11/singletons-wordpress-good-evil/
7
8 /**
9 * Main class of the plugin used to add functionalities
10 *
11 * @since 1.0.0
12 */
13 class Admin_Site_Enhancements {
14
15 // Refers to a single instance of this class
16 private static $instance = null;
17
18 /**
19 * Creates or returns a single instance of this class
20 *
21 * @return Admin_Site_Enhancements a single instance of this class
22 * @since 1.0.0
23 */
24 public static function get_instance() {
25
26 if ( null == self::$instance ) {
27
28 self::$instance = new self;
29
30 }
31
32 return self::$instance;
33
34 }
35
36 /**
37 * Initialize plugin functionalities
38 */
39 private function __construct() {
40
41 // Setup admin menu, admin page, settings, settings sections, sections fields, admin scripts, plugin action links, etc.
42
43 // Register admin menu and add the settings page.
44 add_action( 'admin_menu', 'asenha_register_admin_menu' );
45
46 // Register plugin settings
47
48 // Instantiate object for registration of settings section and fields
49 $settings = new ASENHA\Classes\Settings_Sections_Fields;
50
51 add_action( 'admin_init', [ $settings, 'register_sections_fields' ] );
52
53 // Suppress all notices on the plugin's main page. Then add notification for successful settings update.
54 add_action( 'admin_notices', 'asenha_suppress_notices', 5 );
55 add_action( 'all_admin_notices', 'asenha_suppress_generic_notices', 5 );
56
57 // Enqueue admin scripts and styles only on the plugin's main page
58 add_action( 'admin_enqueue_scripts', 'asenha_admin_scripts' );
59
60 // Add action links in plugins page
61 add_filter( 'plugin_action_links_' . ASENHA_SLUG . '/' . ASENHA_SLUG . '.php', 'asenha_plugin_action_links' );
62
63 // Update footer text
64 add_filter( 'admin_footer_text', 'asenha_footer_text' );
65
66 // ===== Activate features based on settings =====
67
68 // Get all WP Enhancements options, default to empty array in case it's not been created yet
69 $options = get_option( ASENHA_SLUG_U, array() );
70
71 // ===== CONTENT MANAGEMENT =====
72
73 // Instantiate object for Content Management features
74 $content_management = new ASENHA\Classes\Content_Management;
75
76 // Content Management >> Enable Page and Post Duplication
77 if ( array_key_exists( 'enable_duplication', $options ) && $options['enable_duplication'] ) {
78 add_action( 'admin_action_asenha_enable_duplication', [ $content_management, 'asenha_enable_duplication' ] );
79 add_filter( 'page_row_actions', [ $content_management, 'add_duplication_action_link' ], 10, 2 );
80 add_filter( 'post_row_actions', [ $content_management, 'add_duplication_action_link' ], 10, 2 );
81 }
82
83 // Content Management >> Enable Media Replacement
84 if ( array_key_exists( 'enable_media_replacement', $options ) && $options['enable_media_replacement'] ) {
85 add_filter( 'media_row_actions', [ $content_management, 'modify_media_list_table_edit_link' ], 10, 2 );
86 add_filter( 'attachment_fields_to_edit', [ $content_management, 'add_media_replacement_button' ] );
87 add_action( 'edit_attachment', [ $content_management, 'replace_media' ] );
88 add_filter( 'post_updated_messages', [ $content_management, 'attachment_updated_custom_message' ] );
89 }
90
91 // Content Management >> Enable SVG Upload
92 if ( array_key_exists( 'enable_svg_upload', $options ) && $options['enable_svg_upload'] && array_key_exists( 'enable_svg_upload_for', $options ) && isset( $options['enable_svg_upload_for'] ) ) {
93
94 global $roles_svg_upload_enabled;
95
96 $enable_svg_upload = $options['enable_svg_upload'];
97 $for_roles = $options['enable_svg_upload_for'];
98
99 // User has role(s). Do further checks.
100 if ( isset( $for_roles ) && ( count( $for_roles ) > 0 ) ) {
101
102 // Assemble single-dimensional array of roles for which SVG upload would be enabled
103 $roles_svg_upload_enabled = array();
104 foreach( $for_roles as $role_slug => $svg_upload_enabled ) {
105 if ( $svg_upload_enabled ) {
106 $roles_svg_upload_enabled[] = $role_slug;
107 }
108 }
109
110 }
111
112 add_filter( 'upload_mimes', [ $content_management, 'add_svg_mime' ] );
113 add_filter( 'wp_check_filetype_and_ext', [ $content_management, 'confirm_file_type_is_svg' ], 10, 4 );
114 add_filter( 'wp_handle_upload_prefilter', [ $content_management, 'sanitize_and_maybe_allow_svg_upload' ] );
115 add_filter( 'wp_generate_attachment_metadata', [ $content_management, 'generate_svg_metadata' ], 10, 3 );
116 add_action( 'wp_ajax_svg_get_attachment_url', [ $content_management, 'get_svg_attachment_url' ] );
117 add_filter( 'wp_prepare_attachment_for_js', [ $content_management, 'get_svg_url_in_media_library' ] );
118 }
119
120 // Content Management >> Enable Auto-Publishing of Posts with Missed Schedules
121 if ( array_key_exists( 'enable_missed_schedule_posts_auto_publish', $options ) && $options['enable_missed_schedule_posts_auto_publish'] ) {
122 add_action( 'wp_head', [ $content_management, 'publish_missed_schedule_posts' ] );
123 add_action( 'admin_head', [ $content_management, 'publish_missed_schedule_posts' ] );
124 }
125
126 // Content Management >> Enhance List Tables
127 if ( array_key_exists( 'enhance_list_tables', $options ) && $options['enhance_list_tables'] ) {
128
129 // Show Featured Image Column
130 if ( array_key_exists( 'show_featured_image_column', $options ) && $options['show_featured_image_column'] ) {
131 add_action( 'admin_init', [ $content_management, 'show_featured_image_column' ] );
132 }
133
134 // Show Excerpt Column
135 if ( array_key_exists( 'show_excerpt_column', $options ) && $options['show_excerpt_column'] ) {
136 add_action( 'admin_init', [ $content_management, 'show_excerpt_column' ] );
137 }
138
139 // Show ID Column
140 if ( array_key_exists( 'show_id_column', $options ) && $options['show_id_column'] ) {
141 add_action( 'admin_init', [ $content_management, 'show_id_column' ] );
142 }
143
144 // Hide Comments Column
145 if ( array_key_exists( 'hide_comments_column', $options ) && $options['hide_comments_column'] ) {
146 add_action( 'admin_init', [ $content_management, 'hide_comments_column' ] );
147 }
148
149 // Hide Post Tags Column
150 if ( array_key_exists( 'hide_post_tags_column', $options ) && $options['hide_post_tags_column'] ) {
151 add_action( 'admin_init', [ $content_management, 'hide_post_tags_column' ] );
152 }
153
154 // Show Custom Taxonomy Filters
155 if ( array_key_exists( 'show_custom_taxonomy_filters', $options ) && $options['show_custom_taxonomy_filters'] ) {
156 add_action( 'restrict_manage_posts', [ $content_management, 'show_custom_taxonomy_filters' ] );
157 }
158
159 }
160
161 // ===== ADMIN INTERFACE =====
162
163 // Instantiate object for Admin Interface features
164 $admin_interface = new ASENHA\Classes\Admin_Interface;
165
166 // Admin Interface >> Hide Admin Notices
167 if ( array_key_exists( 'hide_admin_notices', $options ) && $options['hide_admin_notices'] ) {
168 add_action( 'all_admin_notices', [ $admin_interface, 'admin_notices_wrapper' ] );
169 add_action( 'admin_bar_menu', [ $admin_interface, 'admin_notices_menu' ] );
170 add_action( 'admin_enqueue_scripts', [ $admin_interface, 'admin_notices_menu_inline_css' ] ); // wp-admin
171 }
172
173 // Admin Interface >> Hide Admin Bar
174 if ( array_key_exists( 'hide_admin_bar', $options ) && $options['hide_admin_bar'] && array_key_exists( 'hide_admin_bar_for', $options ) && isset( $options['hide_admin_bar_for'] ) ) {
175 add_filter( 'show_admin_bar', [ $admin_interface, 'hide_admin_bar_for_roles' ] );
176 }
177
178 // Admin Interface >> View Admin as Role
179 if ( array_key_exists( 'view_admin_as_role', $options ) && $options['view_admin_as_role'] ) {
180 add_action( 'admin_bar_menu', [ $admin_interface, 'view_admin_as_admin_bar_menu' ], 8 ); // Priority 8 so it is next to username section
181 add_action( 'init', [ $admin_interface, 'role_switcher_to_view_admin_as' ] );
182 add_action( 'wp_die_handler', [ $admin_interface, 'custom_error_page_on_switch_failure' ] );
183 }
184
185 // Admin Interface >> Hide or Modify Elements
186 if ( array_key_exists( 'hide_modify_elements', $options ) && $options['hide_modify_elements'] ) {
187 add_filter( 'admin_bar_menu', [ $admin_interface, 'modify_admin_bar_menu' ], 5 ); // priority 5 to execute earlier than the normal 10
188 }
189
190 // Admin Interface >> Customize Admin Menu
191
192 if ( array_key_exists( 'customize_admin_menu', $options ) && $options['customize_admin_menu'] ) {
193 // add_action( 'wp_ajax_save_custom_menu_order', [ $admin_interface, 'save_custom_menu_order' ] );
194 // add_action( 'wp_ajax_save_hidden_menu_items', [ $admin_interface, 'save_hidden_menu_items' ] );
195 if ( array_key_exists( 'custom_menu_order', $options ) ) {
196 add_filter( 'custom_menu_order', '__return_true' );
197 add_filter( 'menu_order', [ $admin_interface, 'render_custom_menu_order' ] );
198 }
199 if ( array_key_exists( 'custom_menu_titles', $options ) ) {
200 add_action( 'admin_menu', [ $admin_interface, 'apply_custom_menu_item_titles' ], 1000 );
201 }
202 if ( array_key_exists( 'custom_menu_hidden', $options ) ) {
203 add_action( 'admin_menu', [ $admin_interface, 'hide_menu_items' ], 1001 );
204 add_action( 'admin_menu', [ $admin_interface, 'add_hidden_menu_toggle' ], 1002 );
205 add_action( 'admin_enqueue_scripts', [ $admin_interface, 'enqueue_toggle_hidden_menu_script' ] );
206 }
207 }
208
209 // ===== DISABLE COMPONENTS ======
210
211 // Instantiate object for Disable Components features
212 $disable_components = new ASENHA\Classes\Disable_Components;
213
214 // Disable Components >> Disable Gutenberg
215 if ( array_key_exists( 'disable_gutenberg', $options ) && $options['disable_gutenberg'] ) {
216 if ( array_key_exists( 'disable_gutenberg_for', $options ) && ! empty( $options['disable_gutenberg_for'] ) ) {
217 add_action( 'admin_init', [ $disable_components, 'disable_gutenberg_for_post_types_admin' ] );
218 if ( array_key_exists( 'disable_gutenberg_frontend_styles', $options ) && $options['disable_gutenberg_frontend_styles'] ) {
219 add_action( 'wp_enqueue_scripts', [ $disable_components, 'disable_gutenberg_for_post_types_frontend' ], 100 );
220 }
221 }
222 }
223
224 // Disable Components >> Disable Comments
225 if ( array_key_exists( 'disable_comments', $options ) && $options['disable_comments'] ) {
226 if ( array_key_exists( 'disable_comments_for', $options ) && ! empty( $options['disable_comments_for'] ) ) {
227 add_action( 'do_meta_boxes', [ $disable_components, 'disable_comments_for_post_types_edit' ] ); // also work with 'init', 'admin_init', 'wp_loaded' hooks
228 add_filter( 'comments_array', [ $disable_components, 'hide_existing_comments_on_frontend' ], 10, 2 ); // hide comments
229 add_filter( 'comments_open', [ $disable_components, 'close_commenting_on_frontend' ] ); // close commenting
230 }
231 }
232
233 // Disable Components >> Disable REST API
234 if ( array_key_exists( 'disable_rest_api', $options ) && $options['disable_rest_api'] ) {
235 if ( version_compare( get_bloginfo('version'), '4.7', '>=' ) ) {
236 add_filter( 'rest_authentication_errors', [ $disable_components, 'disable_rest_api' ] );
237 } else {
238 // REST API 1.x
239 add_filter( 'json_enabled', '__return_false' );
240 add_filter( 'json_jsonp_enabled', '__return_false' );
241 // REST API 2.x
242 add_filter( 'rest_enabled', '__return_false' );
243 add_filter( 'rest_jsonp_enabled', '__return_false' );
244 }
245 remove_action('wp_head', 'rest_output_link_wp_head', 10 ); // Disable REST API links in HTML <head>
246 remove_action( 'template_redirect', 'rest_output_link_header', 11, 0 ); // Disable REST API link in HTTP headers
247 remove_action( 'xmlrpc_rsd_apis', 'rest_output_rsd' ); // Remove REST API URL from the WP RSD endpoint.
248 }
249
250 // Disable Components >> Disable Feeds
251 if ( array_key_exists( 'disable_feeds', $options ) && $options['disable_feeds'] ) {
252 remove_action( 'wp_head', 'feed_links', 2 ); // Remove feed links in <head>
253 remove_action( 'wp_head', 'feed_links_extra', 3 ); // Remove feed links in <head>
254 remove_action( 'do_feed_rdf', 'do_feed_rdf', 10, 0 );
255 remove_action( 'do_feed_rss', 'do_feed_rss', 10, 0 );
256 remove_action( 'do_feed_rss2', 'do_feed_rss2', 10, 1 );
257 remove_action( 'do_feed_atom', 'do_feed_atom', 10, 1 );
258 }
259
260 // ===== SECURITY =====
261
262 // Instantiate object for Security features
263 $security = new ASENHA\Classes\Security;
264
265 // Security >> Change Login URL
266 if ( array_key_exists( 'change_login_url', $options ) && $options['change_login_url'] ) {
267 if ( array_key_exists( 'custom_login_slug', $options ) && ! empty( $options['custom_login_slug'] ) ) {
268 add_action( 'init', [ $security, 'redirect_on_custom_login_url' ] );
269 add_action( 'login_head', [ $security, 'redirect_on_default_login_urls' ] );
270 add_action( 'wp_login_failed', [ $security, 'redirect_to_custom_login_url_on_login_fail' ] );
271 add_action( 'wp_logout', [ $security, 'redirect_to_custom_login_url_on_logout_success' ] );
272 }
273 }
274
275 // Security >> Limit Login Attempts
276 if ( array_key_exists( 'limit_login_attempts', $options ) && $options['limit_login_attempts'] ) {
277 add_filter( 'authenticate', [ $security, 'maybe_allow_login' ], 999, 3 ); // Very low priority so it is processed last
278 add_action( 'login_enqueue_scripts', [ $security, 'maybe_hide_login_form' ] );
279 add_action( 'wp_login_failed', [ $security, 'log_failed_login' ], 5 ); // Higher priority than one in Change Login URL
280 add_action( 'wp_login_errors', [ $security, 'login_error_handler' ], 999, 2 );
281 add_filter( 'login_message', [ $security, 'add_failed_login_message' ] );
282 add_action( 'wp_login', [ $security, 'clear_failed_login_log' ] );
283 }
284
285 // Security >> Obfuscate Author Slugs
286 if ( array_key_exists( 'obfuscate_author_slugs', $options ) && $options['obfuscate_author_slugs'] ) {
287 add_action( 'pre_get_posts', [ $security, 'alter_author_query' ], 10 );
288 add_filter( 'author_link', [ $security, 'alter_author_link' ], 10, 3 );
289 add_filter( 'rest_prepare_user', [ $security, 'alter_json_users' ], 10, 3 );
290 }
291
292 // Security >> Disable XML-RPC
293 if ( array_key_exists( 'disable_xmlrpc', $options ) && $options['disable_xmlrpc'] ) {
294 add_filter( 'xmlrpc_enabled', '__return_false' );
295 add_filter( 'wp_xmlrpc_server_class', [ $security, 'maybe_disable_xmlrpc' ] );
296 }
297
298 // ===== UTILITIES ======
299
300 // Instantiate object for Utilities features
301 $utilities = new ASENHA\Classes\Utilities;
302
303 // Utilities >> Enable Login Logout
304
305 if ( array_key_exists( 'enable_login_logout_menu', $options ) && $options['enable_login_logout_menu'] ) {
306 add_action( 'admin_head-nav-menus.php', [ $utilities, 'add_login_logout_metabox' ] );
307 add_filter( 'wp_setup_nav_menu_item', [ $utilities, 'set_login_logout_menu_item_dynamic_url' ] );
308 add_filter( 'wp_nav_menu_objects', [ $utilities, 'maybe_remove_login_or_logout_menu_item' ] );
309 }
310
311 // Utilities >> Redirect After Login
312
313 if ( array_key_exists( 'redirect_after_login', $options ) && $options['redirect_after_login'] ) {
314 if ( array_key_exists( 'redirect_after_login_to_slug', $options ) && ! empty( $options['redirect_after_login_to_slug'] ) ) {
315 if ( array_key_exists( 'redirect_after_login_for', $options ) && ! empty( $options['redirect_after_login_for'] ) ) {
316 add_filter( 'wp_login', [ $utilities, 'redirect_for_roles_after_login' ], 5, 2 );
317 }
318 }
319 }
320
321 // Utilities >> Redirect After Logout
322
323 if ( array_key_exists( 'redirect_after_logout', $options ) && $options['redirect_after_logout'] ) {
324 if ( array_key_exists( 'redirect_after_logout_to_slug', $options ) && ! empty( $options['redirect_after_logout_to_slug'] ) ) {
325 if ( array_key_exists( 'redirect_after_logout_for', $options ) && ! empty( $options['redirect_after_logout_for'] ) ) {
326 add_action( 'wp_logout', [ $utilities, 'redirect_after_logout' ], 5, 1 ); // load earlier than Change Login URL add_action
327 }
328 }
329 }
330
331 // Utilities >> Redirect 404 to Homepage
332
333 if ( array_key_exists( 'redirect_404_to_homepage', $options ) && $options['redirect_404_to_homepage'] ) {
334 add_filter( 'wp', [ $utilities, 'redirect_404_to_homepage' ] );
335 }
336
337 // Utilities >> Enable Custom Admin / Frontend CSS
338
339 if ( array_key_exists( 'enable_custom_admin_css', $options ) && $options['enable_custom_admin_css'] ) {
340 add_filter( 'admin_enqueue_scripts', [ $utilities, 'custom_admin_css' ] );
341 }
342
343 if ( array_key_exists( 'enable_custom_frontend_css', $options ) && $options['enable_custom_frontend_css'] ) {
344 add_filter( 'wp_enqueue_scripts', [ $utilities, 'custom_frontend_css' ] );
345 }
346
347 // Utilities >> Create and Edit ads.txt
348
349 if ( array_key_exists( 'manage_ads_appads_txt', $options ) && $options['manage_ads_appads_txt'] ) {
350 add_action( 'init', [ $utilities, 'show_ads_appads_txt_content' ] );
351 }
352
353 // Utilities >> Insert <head>, <body> and <footer> code
354
355 if ( array_key_exists( 'insert_head_body_footer_code', $options ) && $options['insert_head_body_footer_code'] ) {
356
357 if ( isset( $options['head_code_priority'] ) ) {
358 add_action( 'wp_head', [ $utilities, 'insert_head_code' ], $options['head_code_priority'] );
359 } else {
360 add_action( 'wp_head', [ $utilities, 'insert_head_code' ], 10 );
361 }
362
363 if ( function_exists( 'wp_body_open' ) && version_compare( get_bloginfo( 'version' ), '5.2', '>=' ) ) {
364
365 if ( isset( $options['body_code_priority'] ) ) {
366 add_action( 'wp_body_open', [ $utilities, 'insert_body_code' ], $options['body_code_priority'] );
367 } else {
368 add_action( 'wp_body_open', [ $utilities, 'insert_body_code' ], 10 );
369 }
370 }
371
372 if ( isset( $options['footer_code_priority'] ) ) {
373 add_action( 'wp_footer', [ $utilities, 'insert_footer_code' ], $options['footer_code_priority'] );
374 } else {
375 add_action( 'wp_footer', [ $utilities, 'insert_footer_code' ], 10 );
376 }
377
378 }
379
380 }
381
382 }
383
384 Admin_Site_Enhancements::get_instance();