PluginProbe
Adminify – White Label, Admin Menu Editor, Login Customizer / 4.3.1
Adminify – White Label, Admin Menu Editor, Login Customizer v4.3.1
4.3.1 4.3.0 4.2.26 4.2.25 4.2.24 4.2.23 4.2.22 4.2.21 4.2.20 4.2.19 4.2.18 4.2.17 4.2.16 4.2.15 4.2.14 4.2.13 4.2.12 4.2.11 4.2.10 4.2.9 4.2.8 4.2.7 4.2.6 4.2.5 4.1.17 All 164 releases
adminify / Inc / Classes / Tweaks.php

Tweaks.php in Adminify – White Label, Admin Menu Editor, Login Customizer 4.3.1, at Inc/Classes/Tweaks.php

1,071 lines 32.3 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace PXLBSAdminify\Inc\Classes;
4
5 use PXLBSAdminify\Inc\Utils;
6 use PXLBSAdminify\Inc\Admin\AdminSettings;
7 use PXLBSAdminify\Inc\Admin\AdminSettingsModel;
8
9 // no direct access allowed
10 if (!defined('ABSPATH')) {
11 exit;
12 }
13
14 /**
15 * @package WP Adminify
16 * @author: Jewel Theme<support@jeweltheme.com>
17 */
18
19 class Tweaks extends AdminSettingsModel
20 {
21
22 public $redirect_status = 301;
23 private $performance;
24 private $security_head;
25 private $security_feed;
26 private $security_rest_api;
27 private $security_posts;
28 private $security_media;
29 private $custom_gravatar;
30
31 public function __construct()
32 {
33 $this->options = (array) AdminSettings::get_instance()->get();
34 $this->performance = $this->options['performance'];
35 $this->security_head = $this->options['security_head'];
36 $this->security_feed = $this->options['security_feed'];
37 $this->security_rest_api = $this->options['security_rest_api'];
38 $this->security_posts = $this->options['post_archives'];
39 $this->security_media = $this->options['media_attachments'];
40 $this->custom_gravatar = $this->options['custom_gravatar'];
41
42
43
44 if (!empty($this->security_head['enable_security_head'])) {
45 $this->security_head();
46 }
47
48 $this->security_feed();
49
50 if (!empty($this->security_rest_api['security_rest_api_enable'])) {
51 $this->security_rest_api();
52 }
53
54 if (!empty($this->security_posts['post_archives_enable'])) {
55 $this->security_post_archives();
56 }
57
58 $this->security_attachments();
59
60 if(!empty($this->performance['performance_enable'])){
61 $this->performances();
62 }
63
64 // Add Custom Default Gravatar Image
65 if (!empty($this->custom_gravatar) && array_key_exists('enable', $this->custom_gravatar)) {
66 // Add Custom Default Gravatar Image
67 add_filter('avatar_defaults', [$this, 'add_custom_gravatar_image'], 99);
68 // ...and serve it from this site rather than through gravatar.com.
69 add_filter('get_avatar_data', [$this, 'serve_custom_gravatar_locally'], 99);
70 }
71
72 // If Admin bar Editor Plugin not Installed
73 if (! class_exists('\JewelTheme\AdminBarEditor\AdminBarEditor')) {
74 if (!empty($this->options['white_label']['wordpress']['remove_howdy_msg']) || !empty($this->options['white_label']['wordpress']['change_howdy_text'])) {
75 // Change Howdy Text
76 // add_action('admin_bar_menu', [$this, 'remove_from_admin_bar'], 999);
77 // add_action('admin_bar_menu', [$this, 'clear_node_title'], 999);
78 add_filter('admin_bar_menu', [$this, 'change_howdy_text'], 9999);
79 }
80 }
81
82
83 // Remove Admin Bar Logo
84 if(!empty($this->options['white_label']['wordpress']['admin_bar_cleanup'])){
85 add_action("wp_before_admin_bar_render", [$this, "admin_bar_cleanup"], 0);
86 }
87
88 }
89
90
91 /**
92 * Security: Post & Archives
93 *
94 * @return void
95 */
96 public function security_post_archives(){
97 $post_archives_data = $this->security_posts['post_archives_data'];
98
99 // tag and category hooks
100 if (!empty($post_archives_data) && in_array('last_modified_date', $post_archives_data)) {
101 add_filter('the_content', [$this, 'last_updated_date'], 10, 1);
102 add_filter('wp_head', [$this, 'last_updated_date_style']);
103 }
104
105 /** Remove Capital P Dangit */
106 if (!empty($post_archives_data) && in_array('capital_p_dangit', $post_archives_data)) {
107 remove_filter('the_title', 'capital_P_dangit', 11);
108 remove_filter('the_content', 'capital_P_dangit', 11);
109 remove_filter('comment_text', 'capital_P_dangit', 31);
110 }
111
112 // Remove date archives
113 if (!empty($post_archives_data) && (
114 in_array('archives_date', $post_archives_data) ||
115 in_array('archives_author', $post_archives_data) ||
116 in_array('archives_tag', $post_archives_data) ||
117 in_array('archives_category', $post_archives_data) ||
118 in_array('archives_postformat', $post_archives_data) ||
119 in_array('archives_search', $post_archives_data)
120 )) {
121 add_action('template_redirect', [$this, 'redirect_to_home']);
122 }
123
124 // // Remove Author archives
125 // if (!empty($post_archives_data) && in_array('archives_author', $post_archives_data)) {
126 // if (is_author()) {
127 // add_action('template_redirect', [$this, 'redirect']);
128 // }
129 // }
130
131
132 // // Remove tag archives
133 // if (!empty($post_archives_data) && in_array('archives_tag', $post_archives_data)) {
134 // if (is_tag()) {
135 // add_action('template_redirect', [$this, 'redirect']);
136 // }
137 // }
138
139 // // Remove category archives
140 // if (!empty($post_archives_data) && in_array('archives_category', $post_archives_data)) {
141 // if (is_category()) {
142 // add_action('template_redirect', [$this, 'redirect']);
143 // }
144 // }
145
146 // // Remove archives post formats
147 // if (!empty($post_archives_data) && in_array('archives_postformat', $post_archives_data)) {
148 // if (is_tax('post_format')) {
149 // add_action('template_redirect', [$this, 'redirect']);
150 // }
151 // }
152
153 // // Remove search page
154 // if (!empty($post_archives_data) && in_array('archives_search', $post_archives_data)) {
155 // if (is_search()) {
156 // add_action('template_redirect', [$this, 'redirect']);
157 // }
158 // }
159
160 }
161
162 public function url_redirection(){
163 global $wp_query;
164 $wp_query->set_404();
165 wp_safe_redirect(esc_url(home_url()), 301);
166 exit;
167 }
168
169 public function redirect_to_home(){
170 $post_archives_data = $this->security_posts['post_archives_data'];
171
172 // Remove Author archives
173 if (!empty($post_archives_data) && in_array('archives_author', $post_archives_data)) {
174 if (is_author()) {
175 $this->url_redirection();
176 }
177 }
178
179
180 // Remove tag archives
181 if (!empty($post_archives_data) && in_array('archives_tag', $post_archives_data)) {
182 if (is_tag()) {
183 $this->url_redirection();
184 }
185 }
186
187 // Remove category archives
188 if (!empty($post_archives_data) && in_array('archives_category', $post_archives_data)) {
189 if (is_category()) {
190 $this->url_redirection();
191 }
192 }
193
194 // Remove archives post formats
195 if (!empty($post_archives_data) && in_array('archives_postformat', $post_archives_data)) {
196 if (is_tax('post_format')) {
197 $this->url_redirection();
198 }
199 }
200
201 // Remove search page
202 if (!empty($post_archives_data) && in_array('archives_search', $post_archives_data)) {
203 if (is_search()) {
204 $this->url_redirection();
205 }
206 }
207 }
208
209
210 /**
211 * Security: Attachments
212 *
213 * @return void
214 */
215 public function security_attachments(){
216
217 // Add Featured Image or Post Thumbnail to RSS Feed
218 if (!empty($this->security_media['thumbnails_rss_feed'])) {
219 add_filter('the_excerpt_rss', [$this, 'rss_post_thumbnail']);
220 add_filter('the_content_feed', [$this, 'rss_post_thumbnail']);
221 }
222
223 }
224
225 /**
226 * Disable REST API
227 *
228 * @return void
229 */
230 public function security_rest_api(){
231 $this->security_rest_api = $this->security_rest_api['security_rest_api_data'];
232
233 /** Disable REST API */
234 if (!empty($this->security_rest_api) && in_array('rest_api', $this->security_rest_api)) {
235
236 // All REST API Hooks
237 if (version_compare(get_bloginfo('version'), '4.7', '>=')) {
238 add_filter('rest_authentication_errors', [$this, 'disable_rest_api']);
239 } else {
240 // Filters for WP-API version 1.x
241 add_filter('json_enabled', '__return_false');
242 add_filter('json_jsonp_enabled', '__return_false');
243
244 // Filters for WP-API version 2.x
245 add_filter('rest_enabled', '__return_false');
246 add_filter('rest_jsonp_enabled', '__return_false');
247 }
248
249 remove_action('wp_head', 'rest_output_link_wp_head', 10); // Disable REST API links in the HTML <head> tag
250 remove_action('wp_head', 'wp_oembed_add_discovery_links'); // Remove oEmbed discovery links.
251 remove_action('template_redirect', 'rest_output_link_header', 11, 0); // Disable the REST API link in HTTP headers.
252 remove_action('xmlrpc_rsd_apis', 'rest_output_rsd'); // Remove the REST API URL from the WordPress RSD endpoint.
253 }
254
255
256 // Remove X-Powered-By
257 if (!empty($this->security_rest_api) && in_array('powered', $this->security_rest_api)) {
258 // add_action('wp', [$this, 'remove_powered']); // OLD way
259
260 // Hook into 'send_headers' to remove the "X-Powered-By" header
261 add_action('send_headers', [$this, 'remove_powered']);
262 }
263 }
264
265
266 public function disable_rest_api(){
267 if (!is_user_logged_in()) {
268 return new \WP_Error(
269 'rest_api_authentication_required',
270 __('The REST API has been restricted to authenticated users.', 'adminify'),
271 [
272 'status' => rest_authorization_required_code()
273 ]
274 );
275 }
276 }
277
278
279 /**
280 * Security Head
281 *
282 * @return void
283 */
284 public function security_head(){
285
286 $this->security_head = $this->security_head['security_head_data'];
287
288 // Disable XML-RPC
289 if (!empty($this->security_head) && in_array('xmlrpc', $this->security_head)) {
290 // add_filter('xmlrpc_enabled', '__return_false');
291 add_filter('wp_xmlrpc_server_class', [$this, 'adminify_disable_wp_xmlrpc']);
292 }
293
294 // Remove WordPress Version Number
295 if (!empty($this->security_head) && in_array('generator_wp_version', $this->security_head)) {
296 remove_action('wp_head', 'wp_generator'); // Remove WordPress Generator Version
297 add_filter('the_generator', '__return_false'); // Remove Generator Name From Rss Feeds.
298 }
299
300 // Remove Revolution Slider generator version
301 if (!empty($this->security_head) && in_array('revslider_generator', $this->security_head)) {
302 add_filter('revslider_meta_generator', '__return_empty_string');
303 }
304
305 // Remove woocommerce generator version
306 if (!empty($this->security_head) && in_array('wc_generator', $this->security_head)) {
307 remove_action('wp_head', 'wc_generator_tag');
308 }
309
310 // Remove wpml meta generator tag
311 if (!empty($this->security_head) && in_array('wpml_generator', $this->security_head)) {
312 add_action('wp_head', [$this, 'remove_wpml_generator'], 0);
313 }
314
315 // Remove wpbakery visual_composer meta generator tag
316 if (!empty($this->security_head) && in_array('js_composer_generator', $this->security_head)) {
317 if (class_exists('Vc_Manager')) {
318 remove_action('wp_head', [visual_composer(), 'addMetaData'], 1);
319 }
320 }
321
322 // Remove Yoast SEO meta generator tag
323 if (!empty($this->security_head) && in_array('yoast_generator', $this->security_head)) {
324 add_filter('wpseo_debug_markers', '__return_false');
325 }
326
327 // REMOVE wlwmanifest.xml.
328 if (!empty($this->security_head) && in_array('wlwmanifest', $this->security_head)) {
329 remove_action('wp_head', 'wlwmanifest_link');
330 }
331
332 // Remove Really Simple Discovery Link.
333 if (!empty($this->security_head) && in_array('rsd', $this->security_head)) {
334 remove_action('wp_head', 'rsd_link');
335 }
336
337 // Remove Shortlink Url
338 if (!empty($this->security_head) && in_array('shortlink', $this->security_head)) {
339 remove_action('wp_head', 'wp_shortlink_wp_head');
340 remove_action('template_redirect', 'wp_shortlink_header', 100, 0);
341 }
342
343 /** Remove Version Query Strings from Scripts/Styles */
344 if (!empty($this->security_head) && in_array('canonical', $this->security_head)) {
345 remove_action('embed_head', 'rel_canonical');
346
347 // Function to remove the canonical URL
348 //
349
350 // Hook the function to wp_head
351 add_action('wp_head', [$this, 'remove_wp_canonical_url'] , 1);
352 // Yoast SEO Canonical URL
353 if (Utils::is_plugin_active('wordpress-seo/wp-seo.php')) {
354 add_filter('wpseo_canonical', '__return_false');
355 }
356 }
357
358
359 /* Disable Self Pings */
360 if (!empty($this->security_head) && in_array('self_ping', $this->security_head)) {
361 add_action('pre_ping', [$this, 'disable_self_ping']);
362 }
363
364 }
365
366 /**
367 * Disable XMLRPC file
368 *
369 * @return void
370 */
371 public function adminify_disable_wp_xmlrpc($data)
372 {
373 http_response_code(403);
374 }
375
376 /**
377 * Security Feed Links
378 *
379 * @return void
380 */
381 public function security_feed(){
382
383 // Remove Feed Links
384 if (!empty($this->security_feed)) {
385 remove_action('wp_head', 'feed_links_extra', 3); // Remove Every Extra Links to Rss Feeds.
386 remove_action('wp_head', 'feed_links', 2); // Remove Head link <head/>
387 remove_action('do_feed_rdf', 'do_feed_rdf', 10, 0);
388 remove_action('do_feed_rss', 'do_feed_rss', 10, 0);
389 remove_action('do_feed_rss2', 'do_feed_rss2', 10, 1);
390 remove_action('do_feed_atom', 'do_feed_atom', 10, 1);
391
392 // Redirect to Home
393 add_action('do_feed', [$this, 'redirect'], 1);
394 add_action('do_feed_rdf', [$this, 'redirect'], 1);
395 add_action('do_feed_rss', [$this, 'redirect'], 1);
396 add_action('do_feed_rss2', [$this, 'redirect'], 1);
397 add_action('do_feed_atom', [$this, 'redirect'], 1);
398
399 }
400 }
401
402
403
404 /*
405 * Change Howdy Text
406 */
407 public function change_howdy_text($wp_admin_bar)
408 {
409 // Remove Howdy Message entirely
410 if (!empty($this->options['white_label']['wordpress']['remove_howdy_msg'])) {
411
412 // Remove the entire "My Account" section and rebuild it later.
413 remove_action('admin_bar_menu', 'wp_admin_bar_my_account_item', 7);
414
415 $current_user = wp_get_current_user();
416 $user_id = get_current_user_id();
417 $profile_url = get_edit_profile_url($user_id);
418
419 $avatar = get_avatar($user_id, 26); // size 26x26 pixels
420 $display_name = $current_user->display_name;
421 $class = $avatar ? 'with-avatar' : 'no-avatar';
422 $wp_admin_bar->add_menu(array(
423 'id' => 'my-account',
424 'parent' => 'top-secondary',
425 'title' => $display_name . $avatar,
426 'href' => $profile_url,
427 'meta' => array(
428 'class' => $class,
429 ),
430 ));
431 }
432
433 // Change Howdy Text
434 if (!empty($this->options['white_label']['wordpress']['change_howdy_text'])) {
435
436 // Get the current user information
437 $my_account = $wp_admin_bar->get_node('my-account');
438
439 if (isset($my_account->title)) {
440
441 // Replace the "Howdy" text with "Welcome"
442 $changed_howdy_text = str_replace('Howdy', Utils::kses_custom($this->options['white_label']['wordpress']['change_howdy_text']), $my_account->title);
443
444 // Update the node with the new title
445 $wp_admin_bar->add_node([
446 'id' => 'my-account',
447 'parent' => 'top-secondary',
448 'title' => $changed_howdy_text,
449 ]);
450 }
451
452 }
453 }
454
455 /**
456 * Remove Canonical URL
457 *
458 * @return void
459 */
460 public function remove_wp_canonical_url()
461 {
462 remove_action('wp_head', 'rel_canonical');
463 }
464
465 /**
466 * Removes admin bar logo from Admin Toolbar
467 */
468 public function admin_bar_cleanup()
469 {
470 global $wp_admin_bar;
471 //TODO: Check for Network wide site "my-sites"
472
473 if (in_array('wp_logo', $this->options['white_label']['wordpress']['admin_bar_cleanup'])) {
474 $wp_admin_bar->remove_menu('wp-logo');
475 }
476 if (in_array('site_name', $this->options['white_label']['wordpress']['admin_bar_cleanup'])) {
477 $wp_admin_bar->remove_menu('site-name');
478 }
479 if (in_array('comments', $this->options['white_label']['wordpress']['admin_bar_cleanup'])) {
480 $wp_admin_bar->remove_menu('comments');
481 }
482 // if (in_array('menu_toggle', $this->options['white_label']['wordpress']['admin_bar_cleanup'])) {
483 // $wp_admin_bar->remove_menu('menu-toggle');
484 // }
485 }
486
487
488
489 // Clear the node titles
490 // This will only work if the node is using a :before element for the icon
491 public function clear_node_title($wp_admin_bar)
492 {
493 $all_toolbar_nodes = $wp_admin_bar->get_nodes();
494 // Create an array of node ID's we'd like to remove
495 $clear_titles = [
496 'site-name',
497 'customize',
498 ];
499
500 foreach ($all_toolbar_nodes as $node) {
501
502 // Run an if check to see if a node is in the array to clear_titles
503 if (in_array($node->id, $clear_titles)) {
504 // use the same node's properties
505 $args = $node;
506
507 // make the node title a blank string
508 $args->title = '';
509
510 // update the Toolbar node
511 $wp_admin_bar->add_node($args);
512 }
513 }
514 }
515
516 // Remove items from the admin bar
517 public function remove_from_admin_bar($wp_admin_bar)
518 {
519 /*
520 * Placing items in here will only remove them from admin bar
521 * when viewing the fronte end of the site
522 */
523 if (!is_admin()) {
524 // Example of removing item generated by plugin. Full ID is #wp-admin-bar-si_menu
525 $wp_admin_bar->remove_node('si_menu');
526
527 // WordPress Core Items (uncomment to remove)
528 $wp_admin_bar->remove_node('updates');
529 $wp_admin_bar->remove_node('comments');
530 $wp_admin_bar->remove_node('new-content');
531 // $wp_admin_bar->remove_node('wp-logo');
532 // $wp_admin_bar->remove_node('site-name');
533 $wp_admin_bar->remove_node('my-account');
534 // $wp_admin_bar->remove_node('search');
535 // $wp_admin_bar->remove_node('customize');
536 }
537
538 /*
539 * Items placed outside the if statement will remove it from both the frontend
540 * and backend of the site
541 */
542 $wp_admin_bar->remove_node('wp-logo');
543 }
544
545 /**
546 * The avatar images an administrator configured in the plugin settings.
547 *
548 * Keyed by URL, because that is the identifier WordPress stores in the
549 * `avatar_default` option and hands back to `get_avatar()` later.
550 *
551 * @return array<string,string> Avatar URL => label.
552 */
553 private function custom_gravatar_images()
554 {
555 $images = [];
556
557 if ( empty( $this->custom_gravatar['image'] ) || ! is_array( $this->custom_gravatar['image'] ) ) {
558 return $images;
559 }
560
561 foreach ( $this->custom_gravatar['image'] as $value ) {
562 if ( empty( $value['avatar_image']['url'] ) ) {
563 continue;
564 }
565
566 $avatar_url = esc_url_raw( $value['avatar_image']['url'] );
567 $images[ $avatar_url ] = ! empty( $value['avatar_name'] )
568 ? sanitize_text_field( $value['avatar_name'] )
569 : __( 'Custom Gravatar', 'adminify' );
570 }
571
572 return $images;
573 }
574
575 // Custom Avatars
576 public function add_custom_gravatar_image($avatar_defaults)
577 {
578 // Register the avatar images configured by the administrator in the plugin settings.
579 return array_merge( (array) $avatar_defaults, $this->custom_gravatar_images() );
580 }
581
582 /**
583 * Serve a custom default avatar from this site instead of through gravatar.com.
584 *
585 * Core hands the chosen default to Gravatar as the `d=` query arg, which means
586 * gravatar.com has to fetch the image from THIS server before it can serve it
587 * back. That only works when the URL is publicly resolvable: on a local install,
588 * a staging site behind HTTP auth, or an intranet, Gravatar cannot reach it and
589 * every avatar that falls back to the default comes out broken.
590 *
591 * Gravatar precedence is preserved: a user who genuinely has a Gravatar still
592 * gets theirs, because the custom image is only substituted once
593 * email_has_gravatar() has established there is nothing to fall back FROM. That
594 * keeps "Default Avatar" meaning what WordPress says it means.
595 *
596 * @param array $args Avatar data, after processing.
597 * @return array
598 */
599 public function serve_custom_gravatar_locally( $args )
600 {
601 if ( empty( $args['default'] ) || ! is_string( $args['default'] ) ) {
602 return $args;
603 }
604
605 $images = $this->custom_gravatar_images();
606
607 if ( ! isset( $images[ $args['default'] ] ) ) {
608 return $args;
609 }
610
611 // `force_default` means the caller asked for the default image specifically -
612 // the radio list on Settings > Discussion renders every option that way - so
613 // there is nothing to look up.
614 if ( empty( $args['force_default'] ) && $this->email_has_gravatar( $args['url'] ) ) {
615 return $args;
616 }
617
618 // `found_avatar` is deliberately untouched: it only decides whether
619 // get_avatar() adds the `avatar-default` class, which is correct here.
620 $args['url'] = $args['default'];
621
622 return $args;
623 }
624
625 /**
626 * Whether the address behind a gravatar.com URL actually has an avatar there.
627 *
628 * `d=404` is Gravatar's documented way of asking the question: instead of serving
629 * a fallback image it answers 404 when the address is unknown. The answer is
630 * cached per hash, so a busy comment thread costs one request per new address
631 * rather than one per avatar rendered.
632 *
633 * The hash is read back out of the URL core just built rather than recomputed,
634 * which avoids re-implementing its resolution of user IDs, comments, posts,
635 * WP_User objects and raw hashes - and means a URL another plugin has already
636 * pointed somewhere else is left alone.
637 *
638 * @param string $avatar_url The avatar URL core built.
639 * @return bool True when the address has a Gravatar, or when it is not safe to say.
640 */
641 private function email_has_gravatar( $avatar_url )
642 {
643 if ( empty( $avatar_url ) || ! is_string( $avatar_url ) ) {
644 return true;
645 }
646
647 $path = wp_parse_url( $avatar_url, PHP_URL_PATH );
648 $hash = $path ? basename( $path ) : '';
649
650 // SHA-256 in current core (hash('sha256', ...) in get_avatar_data), MD5 in
651 // older releases. Anything else is not a gravatar.com avatar URL - another
652 // plugin has already pointed it elsewhere - and is none of our business.
653 if ( ! preg_match( '/^[a-f0-9]{32}$|^[a-f0-9]{64}$/i', $hash ) ) {
654 return true;
655 }
656
657 $cache_key = 'adminify_has_gravatar_' . $hash;
658 $cached = get_transient( $cache_key );
659
660 if ( false !== $cached ) {
661 return '1' === $cached;
662 }
663
664 $response = wp_remote_head(
665 'https://secure.gravatar.com/avatar/' . $hash . '?d=404&s=1',
666 array( 'timeout' => 3 )
667 );
668
669 if ( is_wp_error( $response ) ) {
670 // Offline, blocked, or too slow. Show the custom image rather than a URL
671 // gravatar.com may not be able to resolve either, and ask again soon -
672 // a temporary outage should not pin a real Gravatar out of view for a week.
673 set_transient( $cache_key, '0', 15 * MINUTE_IN_SECONDS );
674 return false;
675 }
676
677 $has_gravatar = 200 === (int) wp_remote_retrieve_response_code( $response );
678
679 set_transient( $cache_key, $has_gravatar ? '1' : '0', WEEK_IN_SECONDS );
680
681 return $has_gravatar;
682 }
683
684 // Check Last Login Column
685 public function last_login_column_info( $user_login )
686 {
687 $user = get_user_by( 'login', $user_login );
688 // by username
689 update_user_meta( $user->ID, 'adminify_last_login_on', time() );
690 }
691
692
693 // Remove WPML Generator
694 public function remove_wpml_generator()
695 {
696 if (!empty($GLOBALS['sitepress'])) {
697 remove_action(current_filter(), [$GLOBALS['sitepress'], 'meta_generator_tag']);
698 }
699 }
700
701
702 /**
703 * Disable WP emojicons from TinyMCE
704 *
705 * @access public
706 * @since 1.0.0
707 * @return void
708 */
709 public function disable_emojicons_tinymce($plugins)
710 {
711 if (is_array($plugins)) {
712 return array_diff($plugins, ['wpemoji']);
713 } else {
714 return [];
715 }
716 }
717
718 /**
719 * Disable WP emojicons from TinyMCE
720 *
721 * @access public
722 * @since 1.0.0
723 * @return void
724 */
725 public function remove_dns_prefetch( $urls, $relation_type ) {
726 if ('dns-prefetch' == $relation_type) {
727 // Strip out any URLs referencing the WordPress.org emoji location
728 $emoji_svg_url_base = 'https://s.w.org/images/core/emoji/';
729 foreach ($urls as $key => $url) {
730 if (is_string($url) && false !== strpos($url, $emoji_svg_url_base)) {
731 unset($urls[$key]);
732 }
733 }
734 }
735 return $urls;
736 }
737
738 public function remove_powered()
739 {
740 if (function_exists('header_remove')) {
741 header_remove('X-Powered-By');
742 }
743 }
744
745
746
747 /**
748 * Remove all rewrite rules related to embeds.
749 *
750 * @param array $rules WordPress rewrite rules.
751 * @return array Rewrite rules without embeds rules.
752 */
753 public function disable_embeds_rewrites($rules)
754 {
755 foreach ($rules as $rule => $rewrite) {
756 if (false !== strpos($rewrite, 'embed=true')) {
757 unset($rules[$rule]);
758 }
759 }
760
761 return $rules;
762 }
763
764 // Redirect 403
765 public function redirect_to_403($url = false)
766 {
767 status_header(403); // Send an HTTP 403 Forbidden status header
768 die('403 Forbidden'); // End execution and display a 403 Forbidden message
769 }
770
771 // Redirect function
772 public function redirect($url = false)
773 {
774 if ($url) {
775 $target = $url;
776 } else {
777 $target = esc_url(home_url());
778 }
779
780 $target = apply_filters('pxlbsadminify_redirect_target', $target);
781 $status = apply_filters('pxlbsadminify_redirect_status', $this->redirect_status);
782
783 wp_safe_redirect($target, $status);
784 exit;
785 }
786
787
788 /* Add Featured Image or Post Thumbnail to RSS Feed */
789 public function rss_post_thumbnail($content)
790 {
791 global $post;
792 if (has_post_thumbnail($post->ID)) {
793 $content = '<p>' . get_the_post_thumbnail($post->ID) .
794 '</p>' . get_the_content();
795 }
796 return $content;
797 }
798
799 // Display Last Updated Date of Your Posts
800 public function last_updated_date($content)
801 {
802 if (!is_single()) {
803 return $content;
804 }
805
806 $u_time = get_the_time('U');
807 $u_modified_time = get_the_modified_time('U');
808
809 if ($u_modified_time >= $u_time + 86400) {
810 $custom_content = sprintf(
811 '<div class="wp-adminify-last-updated"><strong><span>%1$s</span></strong><span>%2$s %3$s</span></div>',
812 esc_html__('Last Updated on', 'adminify'),
813 esc_html(get_the_modified_time('F jS, Y')),
814 esc_html(get_the_modified_time('h:i a'))
815 );
816 return $custom_content . $content;
817 }
818
819 return $content;
820 }
821
822 public function last_updated_date_style()
823 {
824 echo '<style>.wp-adminify-last-updated{ border: 1px dashed red; padding: 5px 10px;}</style>';
825 }
826
827
828 // Remove Default Image Links typeremove_image_link
829 public function security_attachment_imagelink()
830 {
831 $image_set = get_option('image_default_link_type');
832
833 if ($image_set !== 'none') {
834 update_option('image_default_link_type', 'none');
835 }
836 }
837
838
839 /* Disable Self Pings */
840 public function disable_self_ping(&$links)
841 {
842 $home = esc_url( home_url() );
843
844 // Additional URLs and explode into an array.
845 $extra_urls = (!empty($this->options['self_ping_sites'])) ? $this->options['self_ping_sites'] : '';
846 $extra_urls = explode(PHP_EOL, $extra_urls);
847
848 if ( is_array( $extra_urls ) ) {
849 $url_array = $extra_urls;
850 } else {
851 $url_array = array();
852 }
853
854 foreach ( $links as $l => $link ) {
855 if ( 0 === strpos( $link, $home ) ) {
856 unset( $links[ $l ] );
857 }
858 foreach ( $url_array as $url ) {
859 $url = trim( $url );
860 if ( 0 === strpos( $link, $url ) && '' !== $url ) {
861 unset( $links[ $l ] );
862 }
863 }
864 }
865
866 }
867
868
869 /** Remove Dashicons from Admin Bar for non logged in users **/
870 public function remove_dashicons()
871 {
872 global $pagenow;
873
874 if (!is_user_logged_in()) {
875
876 // This retrieves the /path/file.php?param=val part of the URL
877 $current_request_uri = isset($_SERVER['REQUEST_URI']) ? sanitize_text_field(wp_unslash($_SERVER['REQUEST_URI'])) : '';
878
879 // for homepage
880 if (empty($current_request_uri)) {
881 wp_dequeue_style('dashicons');
882 wp_deregister_style('dashicons');
883 } else {
884 // Exclude the login page, where Dashicons assets are required for proper styling.
885 if (false !== strpos($current_request_uri, 'wp-login.php') || 'wp-login.php' === $pagenow) {
886 // Do nothing on wp-login.php
887 } elseif (false !== strpos($current_request_uri, 'protected-page=view')) {
888 // Exclude the password protection form.
889 // Do nothing on protected-page=view.
890 } else {
891 // Dequeue Dashicons from contents e.g., yoursite.com/content-url/. Not for wp-login.php,
892 wp_dequeue_style('dashicons');
893 wp_deregister_style('dashicons');
894 }
895 }
896 }
897 }
898
899
900 /** Remove Query Strings from Scripts/Styles **/
901 public function remove_script_versions($src)
902 {
903 if( !empty($src) ) {
904 $parts = explode('?ver', $src);
905 return $parts[0];
906 }
907 }
908
909 /** Browser Cache Expires & GZIP Compression **/
910 public function htaccess()
911 {
912 // We get the main WordPress .htaccess filepath.
913 $ruta_htaccess = get_home_path() . '.htaccess'; // https://codex.wordpress.org/Function_Reference/get_home_path !
914
915 $lineas = [];
916 $lineas[] = '<IfModule mod_expires.c>';
917 $lineas[] = '# Activar caducidad de contenido';
918 $lineas[] = 'ExpiresActive On';
919 $lineas[] = '# Directiva de caducidad por defecto';
920 $lineas[] = 'ExpiresDefault "access plus 1 month"';
921 $lineas[] = '# Para el favicon';
922 $lineas[] = 'ExpiresByType image/x-icon "access plus 1 year"';
923 $lineas[] = '# Imagenes';
924 $lineas[] = 'ExpiresByType image/gif "access plus 1 month"';
925 $lineas[] = 'ExpiresByType image/png "access plus 1 month"';
926 $lineas[] = 'ExpiresByType image/jpg "access plus 1 month"';
927 $lineas[] = 'ExpiresByType image/jpeg "access plus 1 month"';
928 $lineas[] = '# CSS';
929 $lineas[] = 'ExpiresByType text/css "access 1 month"';
930 $lineas[] = '# Javascript';
931 $lineas[] = 'ExpiresByType application/javascript "access plus 1 year"';
932 $lineas[] = '</IfModule>';
933 $lineas[] = '<IfModule mod_deflate.c>';
934 $lineas[] = '# Activar compresión de contenidos estáticos';
935 $lineas[] = 'AddOutputFilterByType DEFLATE text/plain text/html';
936 $lineas[] = 'AddOutputFilterByType DEFLATE text/xml application/xml application/xhtml+xml application/xml-dtd';
937 $lineas[] = 'AddOutputFilterByType DEFLATE application/rdf+xml application/rss+xml application/atom+xml image/svg+xml';
938 $lineas[] = 'AddOutputFilterByType DEFLATE text/css text/javascript application/javascript application/x-javascript';
939 $lineas[] = 'AddOutputFilterByType DEFLATE font/otf font/opentype application/font-otf application/x-font-otf';
940 $lineas[] = 'AddOutputFilterByType DEFLATE font/ttf font/truetype application/font-ttf application/x-font-ttf';
941 $lineas[] = '</IfModule>';
942
943 insert_with_markers($ruta_htaccess, 'Adminify by Jewel Theme', $lineas); // https://developer.wordpress.org/reference/functions/insert_with_markers/ !
944 }
945
946
947 /**
948 * Performance Cleanup
949 *
950 * @access public
951 * @since 1.0.0
952 * @return void
953 */
954 public function performances()
955 {
956 $performance_data = $this->performance['performance_data'];
957
958 // Remove jQuery Migrate
959
960 // Remove Dashicons from Frontend
961 if (!empty($performance_data) && in_array('dashicons', $performance_data)) {
962 add_action('wp_print_styles', [$this, 'remove_dashicons'], 100);
963 }
964
965 /** Remove Version Query Strings from Scripts/Styles */
966 if (!empty($performance_data) && in_array('version_strings', $performance_data)) {
967 if(!is_admin()){
968 add_filter('script_loader_src', [$this, 'remove_script_versions'], 15, 1);
969 add_filter('style_loader_src', [$this, 'remove_script_versions'], 15, 1);
970 }
971 }
972
973
974 // Remove Emoji Styles and Scripts
975 if (!empty($performance_data) && in_array('emoji', $performance_data)) {
976 remove_action('wp_head', 'print_emoji_detection_script', 7); // Remove Emoji's Styles and Scripts.
977 remove_action('embed_head', 'print_emoji_detection_script');
978 remove_action('embeded_head', 'print_emoji_detection_script');
979 remove_action('admin_print_scripts', 'print_emoji_detection_script'); // Remove Emoji's Styles and Scripts.
980 remove_action('wp_print_styles', 'print_emoji_styles'); // Remove Emoji's Styles and Scripts.
981 remove_action('admin_print_styles', 'print_emoji_styles'); // Remove Emoji's Styles and Scripts.
982 remove_filter('wp_mail', 'wp_staticize_emoji_for_email');
983 remove_filter('the_content_feed', 'wp_staticize_emoji');
984 remove_filter('comment_text_rss', 'wp_staticize_emoji');
985 add_filter('option_use_smilies', '__return_false');
986 add_filter('emoji_svg_url', '__return_false');
987 add_action('admin_init', [$this, 'remove_admin_emojis']);
988 add_filter('tiny_mce_plugins', [$this, 'disable_emojicons_tinymce']);
989 add_filter('wp_resource_hints', [$this, 'remove_dns_prefetch'], 10, 2);
990 }
991
992
993
994 add_action('wp_default_scripts', [$this, 'remove_wp_default_scripts'], 9999);
995
996 /** Secure method for Defer Parsing of JavaScript moving ALL JS from Header to Footer */
997 if (in_array('defer_parsing_js_footer', $performance_data)) {
998 add_filter('script_loader_tag', [$this, 'defer_parsing_of_js'], 10, 2);
999 }
1000
1001 /** Browser Cache Expires & GZIP Compression */
1002 if (in_array('cache_gzip_compression', $performance_data)) {
1003 register_activation_hook(__FILE__, [$this, 'htaccess']);
1004 }
1005
1006
1007 // Remove Gravatar Query Strings
1008 if (!empty($performance_data) && in_array('gravatar_query_strings', $performance_data)) {
1009 add_filter('get_avatar_url', [$this, 'remove_avatar_query_string']);
1010 }
1011 }
1012
1013 /* Remove Gravatar Query Strings */
1014 public function remove_avatar_query_string($url)
1015 {
1016 $url_parts = explode('?', $url);
1017 return $url_parts[0];
1018 }
1019
1020
1021 public function remove_admin_emojis()
1022 {
1023 remove_action('admin_print_scripts', 'print_emoji_detection_script');
1024 remove_action('admin_print_styles', 'print_emoji_styles');
1025 }
1026
1027
1028 /** Secure method for Defer Parsing of JavaScript moving ALL JS from Header to Footer **/
1029 public function defer_parsing_of_js($tag, $handle)
1030 {
1031 $skip = apply_filters('pxlbsadminify_defer_skip', false, $tag, $handle);
1032
1033 if ($skip) {
1034 return $tag;
1035 }
1036
1037 if (is_admin()) {
1038 return $tag;
1039 }
1040 if (strpos($tag, '/wp-includes/js/jquery/jquery')) {
1041 return $tag;
1042 }
1043 if (isset($_SERVER['HTTP_USER_AGENT']) && strpos(sanitize_text_field(wp_unslash($_SERVER['HTTP_USER_AGENT'])), 'MSIE 9.') !== false) {
1044 return $tag;
1045 } else {
1046 return str_replace(' src', ' defer src', $tag);
1047 }
1048 }
1049
1050 /**
1051 * Remove jQuery Migrate Script
1052 *
1053 * @param [type] $scripts
1054 *
1055 * @return void
1056 */
1057 public function remove_wp_default_scripts($scripts)
1058 {
1059 // Frontend
1060 if (!is_admin() && in_array('jquery_migrate_front', $this->performance['performance_data'])) {
1061 $scripts->registered["jquery"]->deps = array_diff($scripts->registered["jquery"]->deps, ["jquery-migrate"]);
1062 }
1063
1064 // Backend
1065 if (is_admin() && in_array('jquery_migrate_back', $this->performance['performance_data'])) {
1066 $scripts->registered["jquery"]->deps = array_diff($scripts->registered["jquery"]->deps, ["jquery-migrate"]);
1067 }
1068
1069 }
1070 }
1071