-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathoxy-prefetch.php
More file actions
executable file
·1696 lines (1501 loc) · 74.5 KB
/
Copy pathoxy-prefetch.php
File metadata and controls
executable file
·1696 lines (1501 loc) · 74.5 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
<?php
/**
* Plugin Name: Oxyplug Prefetch & Prerender
* Plugin URI: https://www.oxyplug.com/products/oxy-prefetch
* Description: Faster loading next pages by prerendering/prefetching all links a user hovers or addresses you prefer. It improves UX and Core Web Vitals score.
* Version: 3.1.2
* Author: Oxyplug
* Author URI: https://www.oxyplug.com
* Text Domain: oxy-prefetch
* Domain Path: /lang/
* Requires at least: 5.3
* Requires PHP: 7.4
* Tested up to: 7.1
* License: GPL v2 or later
* License URI: https://www.gnu.org/licenses/gpl-2.0.html
*
* Copyright 2025 OxyPlug
*/
if (!function_exists('str_starts_with')) {
/**
* Polyfill for PHP < 8.0.
*
* @param string $haystack
* @param string $needle
* @return bool
*/
function str_starts_with($haystack, $needle)
{
return $needle === '' || strpos($haystack, $needle) === 0;
}
}
class OxyPrefetch
{
public $wpdb;
public array $already_added = array(
'prefetch' => array(),
'prerender' => array()
);
public array $script_immediate = array();
public array $script_moderate = array();
/**
* Guards against re-entering the save handler when wp_update_post() fires save_post.
* @var bool
*/
private bool $is_saving = false;
const OXY_PREFETCH_VERSION = '3.1.1';
const OXY_PREFETCHES_NUMBER_DEFAULT = 4;
const OXY_PREFETCHES_NUMBER_MAX = 50;
const OXY_PREFETCHES_NUMBER_MIN = 1;
const OXY_PREFETCH_PRERENDER_NUMBER_DEFAULT = 3;
const OXY_PREFETCH_PRERENDER_NUMBER_MAX = 10;
const OXY_PREFETCH_PRERENDER_NUMBER_MIN = 1;
const OXY_PREFETCHES_NUMBER_STATUS_DEFAULT = 'true';
const OXY_PREFETCHES_HOVER_STATUS_DEFAULT = 'true';
const OXY_PREFETCH_PRERENDER_NUMBER_STATUS_DEFAULT = 'false';
const OXY_PREFETCH_PRERENDER_HOVER_STATUS_DEFAULT = 'false';
const OXY_PREFETCH_PRERENDER_HREF_EXCLUSION_STATUS_DEFAULT = 'false';
const OXY_PREFETCH_PRERENDER_EXCLUSION_DEFAULT = array(
'href' => array('')
);
// Eagerness (hover/document rules). Chrome guidance: "start conservative".
const OXY_PREFETCH_EAGERNESS_DEFAULT = 'moderate';
const OXY_PREFETCH_EAGERNESS_VALUES = array('conservative', 'moderate', 'eager');
// No-Vary-Search: lets one entry match URLs that differ only by these params.
const OXY_PREFETCH_NO_VARY_SEARCH_STATUS_DEFAULT = 'true';
const OXY_PREFETCH_NO_VARY_SEARCH_PARAMS_DEFAULT = 'utm_source utm_medium utm_campaign utm_term utm_content gclid fbclid msclkid';
public function __construct()
{
global $wpdb;
$this->wpdb = $wpdb;
// Lang
add_action('plugins_loaded', array($this, 'load_plugin_textdomain'));
// Activation
register_activation_hook(__FILE__, array($this, 'oxy_prefetch_activate'));
// Menu
add_action('admin_menu', array($this, 'add_menu'));
add_action('admin_head', function () {
// Load only in specific pages
$screen = get_current_screen();
if ($screen && in_array($screen->base, array('tools_page_oxy-prefetch-settings', 'post'))) {
$component_path = plugins_url('assets/js/dist/', __FILE__);
$components = array(
'tools_page_oxy-prefetch-settings' => array('switch', 'outlined-text-field', 'icon', 'icon-button', 'outlined-button', 'filled-button'),
'post' => array('switch', 'outlined-text-field', 'icon', 'icon-button', 'outlined-button')
);
$components = wp_json_encode($components[$screen->base]);
?>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Oxygen:wght@300;400;700&display=swap" rel="stylesheet">
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
<script type="module">
// Load MD3 components
(async function () {
const OXY_PREFETCH_VERSION = '<?php echo static::OXY_PREFETCH_VERSION ?>'
const components = '<?php echo $components ?>'
const component_path = '<?php echo $component_path ?>'
for (const component of JSON.parse(components)) {
await import(`${component_path}${component}.js?ver=${OXY_PREFETCH_VERSION}`);
}
})();
</script>
<?php }
});
// Assets
add_action('admin_enqueue_scripts', array($this, 'add_admin_assets'));
add_action('enqueue_block_editor_assets', array($this, 'add_gutenberg_assets'));
// Prefetch
add_action('wp_ajax_save_prefetch_settings', array($this, 'save_prefetch_settings'));
add_action('save_post', array($this, 'save_prefetch_static_links'), 10, 1);
add_action('rest_api_init', array($this, 'add_rest_api'));
// Prerender
add_action('wp_ajax_dismiss_prerender_notice', array($this, 'dismiss_prerender_notice'));
// Integrate with WordPress core Speculative Loading (WP >= 6.8)
add_action('init', array($this, 'integrate_with_core_speculative_loading'));
// Prerender + analytics caveat / core-active dismissible notice
add_action('wp_ajax_dismiss_core_notice', array($this, 'dismiss_core_notice'));
// Add Prefetch & Prerender
add_action('wp_footer', array($this, 'add_speculation_rules_script'), 0);
// Metabox
add_action('add_meta_boxes', array($this, 'create_metabox'), 10);
// Notices
add_action('admin_notices', array($this, 'admin_notices'));
add_action('wp_ajax_oxy_prefetch_admin_notices', array($this, 'oxy_prefetch_admin_notices'));
add_filter('post_updated_messages', array($this, 'post_published'));
// Settings
add_filter('plugin_action_links', array($this, 'add_settings'), 10, 3);
}
/**
* @return void
*/
public function load_plugin_textdomain()
{
load_plugin_textdomain('oxy-prefetch', false, basename(dirname(__FILE__)) . '/lang/');
}
/**
* @return void
*/
public function oxy_prefetch_activate()
{
if (self::OXY_PREFETCH_VERSION != get_option('oxy_prefetch_version')) {
update_option('oxy_prefetch_version', self::OXY_PREFETCH_VERSION, false);
}
}
/**
* @return void
*/
public function add_menu()
{
add_submenu_page(
'tools.php',
'Oxyplug Prefetch & Prerender',
'Oxyplug Prefetch & Prerender',
'manage_options',
'oxy-prefetch-settings',
array($this, 'oxy_prefetch_settings')
);
}
/**
* @return void
*/
public function oxy_prefetch_settings()
{
$oxy_prefetches_number_status = get_option('oxy_prefetches_number_status', self::OXY_PREFETCHES_NUMBER_STATUS_DEFAULT) == 'true';
$oxy_prefetches_number = (int)(get_option('oxy_prefetches_number', self::OXY_PREFETCHES_NUMBER_DEFAULT));
$oxy_prefetch_hover_status = get_option('oxy_prefetch_hover_status', self::OXY_PREFETCHES_HOVER_STATUS_DEFAULT) == 'true';
$oxy_prefetch_prerender_number_status = get_option('oxy_prefetch_prerender_number_status', self::OXY_PREFETCH_PRERENDER_NUMBER_STATUS_DEFAULT) == 'true';
$oxy_prefetch_prerender_number = (int)(get_option('oxy_prefetch_prerender_number', self::OXY_PREFETCH_PRERENDER_NUMBER_DEFAULT));
$oxy_prefetch_prerender_hover_status = get_option('oxy_prefetch_prerender_hover_status', self::OXY_PREFETCH_PRERENDER_HOVER_STATUS_DEFAULT) == 'true';
$oxy_prefetch_prerender_href_exclusion_status = get_option('oxy_prefetch_prerender_href_exclusion_status', self::OXY_PREFETCH_PRERENDER_HREF_EXCLUSION_STATUS_DEFAULT) == 'true';
$oxy_prefetch_prerender_match = get_option('oxy_prefetch_prerender_match', self::OXY_PREFETCH_PRERENDER_EXCLUSION_DEFAULT);
$oxy_prefetch_hover_eagerness = $this->get_eagerness('prefetch');
$oxy_prefetch_prerender_hover_eagerness = $this->get_eagerness('prerender');
$oxy_prefetch_no_vary_search_status = get_option('oxy_prefetch_no_vary_search_status', self::OXY_PREFETCH_NO_VARY_SEARCH_STATUS_DEFAULT) == 'true';
$oxy_prefetch_no_vary_search_params = get_option('oxy_prefetch_no_vary_search_params', self::OXY_PREFETCH_NO_VARY_SEARCH_PARAMS_DEFAULT);
$oxy_prefetch_eagerness_options = array(
'conservative' => __('Conservative — on pointerdown / click (lowest risk)', 'oxy-prefetch'),
'moderate' => __('Moderate — on hover (~200ms)', 'oxy-prefetch'),
'eager' => __('Eager — as soon as the rule matches (highest risk)', 'oxy-prefetch'),
);
?>
<div class="oxy-prefetch-admin-page">
<section class="oxy-prefetch-admin-head">
<h1 class="oxy-prefetch-head-title">
<span
class="oxy-prefetch-brand-highlight"><?php esc_html_e('Oxyplug Prefetch & Prerender', 'oxy-prefetch') ?></span>
<span>|</span>
<span><?php esc_html_e('Settings', 'oxy-prefetch') ?></span>
</h1>
<div class="oxy-prefetch-need-help">
<svg width="36" height="36" viewBox="0 0 36 36" fill="none" xmlns="http://www.w3.org/2000/svg">
<path
d="M7.59161 31.5676L8.1794 30.7586L7.59161 31.5676ZM5.93237 29.9084L6.74139 29.3206L5.93237 29.9084ZM30.0676 29.9084L29.2586 29.3206L30.0676 29.9084ZM28.4084 31.5676L27.8206 30.7586L28.4084 31.5676ZM28.4084 4.43237L28.9962 3.62336L28.4084 4.43237ZM30.0676 6.09161L29.2586 6.6794L30.0676 6.09161ZM7.59161 4.43237L8.1794 5.24139L7.59161 4.43237ZM5.93237 6.09161L6.74139 6.6794L5.93237 6.09161ZM19.7192 9.89296L19.8756 10.8807L19.7192 9.89296ZM17.3727 9.89296L17.2163 10.8807L17.3727 9.89296ZM12 23C11.4477 23 11 23.4477 11 24C11 24.5523 11.4477 25 12 25V23ZM24 25C24.5523 25 25 24.5523 25 24C25 23.4477 24.5523 23 24 23V25ZM12 17C11.4477 17 11 17.4477 11 18C11 18.5523 11.4477 19 12 19V17ZM16.5 19C17.0523 19 17.5 18.5523 17.5 18C17.5 17.4477 17.0523 17 16.5 17V19ZM30.5 16.5V19.5H32.5V16.5H30.5ZM5.5 19.5V16.5H3.5V19.5H5.5ZM18 32C15.1654 32 13.1198 31.9986 11.5336 31.8268C9.9661 31.6569 8.96626 31.3303 8.1794 30.7586L7.00383 32.3766C8.18845 33.2373 9.58051 33.6269 11.3182 33.8151C13.0371 34.0014 15.21 34 18 34V32ZM3.5 19.5C3.5 22.29 3.49863 24.4629 3.68486 26.1818C3.87313 27.9195 4.26267 29.3116 5.12336 30.4962L6.74139 29.3206C6.1697 28.5337 5.84306 27.5339 5.67323 25.9664C5.50137 24.3802 5.5 22.3346 5.5 19.5H3.5ZM8.1794 30.7586C7.62758 30.3577 7.14231 29.8724 6.74139 29.3206L5.12336 30.4962C5.64763 31.2178 6.28222 31.8524 7.00383 32.3766L8.1794 30.7586ZM30.5 19.5C30.5 22.3346 30.4986 24.3802 30.3268 25.9664C30.1569 27.5339 29.8303 28.5337 29.2586 29.3206L30.8766 30.4962C31.7373 29.3116 32.1269 27.9195 32.3151 26.1818C32.5014 24.4629 32.5 22.29 32.5 19.5H30.5ZM18 34C20.79 34 22.9629 34.0014 24.6818 33.8151C26.4195 33.6269 27.8115 33.2373 28.9962 32.3766L27.8206 30.7586C27.0337 31.3303 26.0339 31.6569 24.4664 31.8268C22.8802 31.9986 20.8346 32 18 32V34ZM29.2586 29.3206C28.8577 29.8724 28.3724 30.3577 27.8206 30.7586L28.9962 32.3766C29.7178 31.8524 30.3524 31.2178 30.8766 30.4962L29.2586 29.3206ZM32.5 16.5C32.5 13.71 32.5014 11.5371 32.3151 9.81818C32.1269 8.08051 31.7373 6.68845 30.8766 5.50383L29.2586 6.6794C29.8303 7.46626 30.1569 8.4661 30.3268 10.0336C30.4986 11.6198 30.5 13.6654 30.5 16.5H32.5ZM27.8206 5.24139C28.3724 5.64231 28.8577 6.12758 29.2586 6.6794L30.8766 5.50383C30.3524 4.78222 29.7178 4.14763 28.9962 3.62336L27.8206 5.24139ZM5.5 16.5C5.5 13.6654 5.50137 11.6198 5.67323 10.0336C5.84306 8.4661 6.1697 7.46626 6.74139 6.6794L5.12336 5.50383C4.26267 6.68845 3.87313 8.08051 3.68486 9.81818C3.49863 11.5371 3.5 13.71 3.5 16.5H5.5ZM7.00383 3.62336C6.28222 4.14763 5.64763 4.78222 5.12336 5.50383L6.74139 6.6794C7.14231 6.12758 7.62758 5.64231 8.1794 5.24139L7.00383 3.62336ZM19.5628 8.90528C18.8891 9.01198 18.2028 9.01198 17.5291 8.90528L17.2163 10.8807C18.0972 11.0202 18.9947 11.0202 19.8756 10.8807L19.5628 8.90528ZM12 25H24V23H12V25ZM12 19H16.5V17H12V19ZM26.9539 3.26967C25.0951 5.12711 23.7338 6.46779 22.5558 7.39555C21.3926 8.31159 20.4881 8.75872 19.5628 8.90528L19.8756 10.8807C21.2687 10.66 22.4884 9.99435 23.7932 8.9668C25.0831 7.95097 26.5334 6.51727 28.3676 4.68439L26.9539 3.26967ZM18 4C20.4907 4 22.3761 4.00071 23.8821 4.11906C25.3848 4.23715 26.4116 4.46712 27.2105 4.86993L28.111 3.08413C26.9722 2.50991 25.6443 2.25137 24.0388 2.1252C22.4366 1.99929 20.4605 2 18 2V4ZM27.2105 4.86993C27.4269 4.97906 27.6289 5.1021 27.8206 5.24139L28.9962 3.62336C28.7158 3.41966 28.4216 3.24078 28.111 3.08413L27.2105 4.86993ZM8.40124 4.3614C10.3389 6.29902 11.8529 7.81034 13.1857 8.87708C14.5333 9.95562 15.7832 10.6537 17.2163 10.8807L17.5291 8.90528C16.5773 8.75451 15.6476 8.28574 14.4355 7.31562C13.2086 6.33371 11.7829 4.91456 9.81542 2.94716L8.40124 4.3614ZM18 2C15.8443 2 14.0633 1.99964 12.5843 2.08338C11.1063 2.16707 9.85915 2.33736 8.78216 2.70897L9.4345 4.59959C10.2537 4.31692 11.2865 4.16007 12.6974 4.08019C14.1073 4.00036 15.824 4 18 4V2ZM8.78216 2.70897C8.1318 2.93337 7.54439 3.23061 7.00383 3.62336L8.1794 5.24139C8.54517 4.97564 8.95294 4.76575 9.4345 4.59959L8.78216 2.70897Z"
fill="#2D2D2D"></path>
</svg>
<div>
<span><?php esc_html_e('Need Help Or Have Questions?', 'oxy-prefetch') ?></span>
<a class="oxy-prefetch-a" href="https://www.oxyplug.com/docs/oxy-prefetch/" target="_blank">
<?php esc_html_e('Check our documentation.', 'oxy-prefetch') ?>
</a>
</div>
</div>
</section>
<div class="oxy-prefetch-in-row">
<div class="oxy-prefetch-card">
<h2>
<?php esc_html_e('Prefetch', 'oxy-prefetch') ?>
<i class="dashicons dashicons-editor-help oxy-prefetch-has-tooltip"
data-tooltip="<?php esc_attr_e('Prefetches only the document of the next page.', 'oxy-prefetch') ?>"
data-href="https://www.oxyplug.com/docs/oxy-prefetch/settings/?utm_source=plugin-settings&utm_medium=wordpress&utm_campaign=oxy-prefetch#prefetch-settings"
data-href-text="<?php esc_attr_e('Learn More', 'oxy-prefetch'); ?>"></i>
</h2>
<div class="oxy-prefetch-switch">
<div class="oxy-prefetch-switch-wrap text-color-changer">
<md-switch id="oxy-prefetches-number-status"
icons
name="oxy_prefetches_number_status" <?php if ($oxy_prefetches_number_status): ?> selected <?php endif; ?>></md-switch>
<span <?php if ($oxy_prefetches_number_status): ?> class="active" <?php endif; ?>>
<?php esc_html_e('Number of prefetches (immediate)', 'oxy-prefetch') ?>
</span>
</div>
<md-outlined-text-field class="oxy-prefetch-max-width has-clear-button"
name="oxy_prefetches_number"
value="<?php echo esc_attr($oxy_prefetches_number) ?>"
label="<?php esc_attr_e('The number of links to be prefetched on a category page', 'oxy-prefetch'); ?>"
type="number"
min="1"
max="50"
<?php if (!$oxy_prefetches_number_status): ?>disabled<?php endif; ?>>
<md-icon-button toggle slot="trailing-icon" type="button">
<md-icon>cancel</md-icon>
</md-icon-button>
</md-outlined-text-field>
</div>
<div class="oxy-prefetch-switch">
<div class="oxy-prefetch-switch-wrap text-color-changer">
<md-switch id="oxy-prefetch-hover-status"
icons
name="oxy_prefetch_hover_status" <?php if ($oxy_prefetch_hover_status): ?> selected <?php endif; ?>></md-switch>
<span <?php if ($oxy_prefetch_hover_status): ?> class="active" <?php endif; ?>>
<?php esc_html_e('Prefetch links on mouse hover', 'oxy-prefetch') ?>
</span>
</div>
<div class="oxy-prefetch-eagerness">
<label for="oxy-prefetch-hover-eagerness"><?php esc_html_e('Eagerness', 'oxy-prefetch') ?></label>
<select id="oxy-prefetch-hover-eagerness" name="oxy_prefetch_hover_eagerness" <?php if (!$oxy_prefetch_hover_status): ?>disabled<?php endif; ?>>
<?php foreach ($oxy_prefetch_eagerness_options as $value => $label): ?>
<option value="<?php echo esc_attr($value) ?>" <?php selected($oxy_prefetch_hover_eagerness, $value) ?>><?php echo esc_html($label) ?></option>
<?php endforeach; ?>
</select>
</div>
</div>
</div>
<div class="oxy-prefetch-card">
<h2>
<?php esc_html_e('Prerender', 'oxy-prefetch') ?>
<i class="dashicons dashicons-editor-help oxy-prefetch-has-tooltip"
data-tooltip="<?php esc_attr_e('Prerenders the next page completely like an invisible tab.', 'oxy-prefetch') ?>"
data-href="https://www.oxyplug.com/docs/oxy-prefetch/settings/?utm_source=plugin-settings&utm_medium=wordpress&utm_campaign=oxy-prefetch#prerender-settings"
data-href-text="<?php esc_attr_e('Learn More', 'oxy-prefetch'); ?>"></i>
</h2>
<p class="oxy-prefetch-note oxy-prefetch-caveat">
<?php esc_html_e('Prerendering runs page scripts in advance. Ensure your analytics/ads support the Prerender2 spec (document.prerendering) to avoid inflated counts.', 'oxy-prefetch') ?>
</p>
<div class="oxy-prefetch-switch">
<div class="oxy-prefetch-switch-wrap text-color-changer">
<md-switch id="oxy-prefetch-prerender-status"
icons
name="oxy_prefetch_prerender_number_status" <?php if ($oxy_prefetch_prerender_number_status): ?> selected <?php endif; ?>></md-switch>
<span <?php if ($oxy_prefetch_prerender_number_status): ?> class="active" <?php endif; ?>>
<?php esc_html_e('Number of prerenders (immediate)', 'oxy-prefetch') ?>
</span>
</div>
<md-outlined-text-field class="oxy-prefetch-max-width has-clear-button"
name="oxy_prefetch_prerender_number"
value="<?php echo esc_attr($oxy_prefetch_prerender_number) ?>"
label="<?php esc_attr_e('The number of links to be prerendered on a category page', 'oxy-prefetch'); ?>"
type="number"
min="1"
max="10"
<?php if (!$oxy_prefetch_prerender_number_status): ?>disabled<?php endif; ?>>
<md-icon-button toggle slot="trailing-icon" type="button">
<md-icon>cancel</md-icon>
</md-icon-button>
</md-outlined-text-field>
</div>
<div class="oxy-prefetch-switch">
<div class="oxy-prefetch-switch-wrap text-color-changer">
<md-switch id="oxy-prefetch-prerender-hover-status"
icons
name="oxy_prefetch_prerender_hover_status" <?php if ($oxy_prefetch_prerender_hover_status): ?> selected <?php endif; ?>></md-switch>
<span <?php if ($oxy_prefetch_prerender_hover_status): ?> class="active" <?php endif; ?>>
<?php esc_html_e('Prerender links on mouse hover', 'oxy-prefetch') ?>
</span>
</div>
<div class="oxy-prefetch-eagerness">
<label for="oxy-prefetch-prerender-hover-eagerness"><?php esc_html_e('Eagerness', 'oxy-prefetch') ?></label>
<select id="oxy-prefetch-prerender-hover-eagerness" name="oxy_prefetch_prerender_hover_eagerness" <?php if (!$oxy_prefetch_prerender_hover_status): ?>disabled<?php endif; ?>>
<?php foreach ($oxy_prefetch_eagerness_options as $value => $label): ?>
<option value="<?php echo esc_attr($value) ?>" <?php selected($oxy_prefetch_prerender_hover_eagerness, $value) ?>><?php echo esc_html($label) ?></option>
<?php endforeach; ?>
</select>
</div>
</div>
<input type="hidden" name="oxy_prefetch_settings_nonce"
value="<?php echo esc_attr(wp_create_nonce('save_prefetch_settings')); ?>"/>
</div>
</div>
<div class="oxy-prefetch-in-row">
<div class="oxy-prefetch-card">
<h2>
<?php esc_html_e('Exclusion', 'oxy-prefetch') ?>
<small class="oxy-prefetch-smaller"><?php esc_html_e('(Only for moderate)', 'oxy-prefetch') ?></small>
<i class="dashicons dashicons-editor-help oxy-prefetch-has-tooltip"
data-tooltip="<?php esc_attr_e('Exclude page(s) from prefetching and prerendering by providing a path (using RegEx is allowed).', 'oxy-prefetch') ?>"
data-href="https://www.oxyplug.com/docs/oxy-prefetch/settings/?utm_source=plugin-settings&utm_medium=wordpress&utm_campaign=oxy-prefetch#exclusion-settings"
data-href-text="<?php esc_attr_e('Learn More', 'oxy-prefetch'); ?>"></i>
</h2>
<div class="oxy-prefetch-switch">
<div class="oxy-prefetch-switch-wrap text-color-changer">
<md-switch id="oxy-prefetch-prerender-href-exclusion-status"
icons
name="oxy_prefetch_prerender_href_exclusion_status" <?php if ($oxy_prefetch_prerender_href_exclusion_status): ?> selected <?php endif; ?>></md-switch>
<span <?php if ($oxy_prefetch_prerender_href_exclusion_status): ?> class="active" <?php endif; ?>>
<?php esc_html_e('href exclusion (RegEx allowed)', 'oxy-prefetch') ?>
</span>
</div>
<ul class="oxy-prefetch-note">
<li><?php esc_html_e('Exclude links by specifying their paths:', 'oxy-prefetch') ?></li>
<li><?php esc_html_e('/logout will exclude logout', 'oxy-prefetch') ?></li>
<li><?php esc_html_e("/(page1|page2)/ will exclude all URLs that begin with 'page1' or 'page2'", 'oxy-prefetch') ?></li>
<li><?php esc_html_e("/custom_pages/* will exclude all URLs that begin with 'custom_pages' where the * at the end matches anything that follows.", 'oxy-prefetch') ?></li>
</ul>
<?php foreach ($oxy_prefetch_prerender_match['href'] as $index => $href): ?>
<div class="oxy-prefetch-each-exclusion-url">
<md-outlined-text-field class="oxy-prefetch-max-width has-clear-button"
name="oxy_prefetch_prerender_matches[href][]"
value="<?php echo esc_attr($href) ?>"
label="<?php esc_attr_e('Path', 'oxy-prefetch') ?>"
placeholder="/logout"
type="text"
<?php if (!$oxy_prefetch_prerender_href_exclusion_status): ?>disabled<?php endif; ?>>
<md-icon-button toggle slot="trailing-icon" type="button">
<md-icon>cancel</md-icon>
</md-icon-button>
</md-outlined-text-field>
<?php if ($index == 0): ?>
<md-icon-button class="oxy-prefetch-remove-exclusion"
toggle
slot="trailing-icon"
type="button"
style="display:none">
<md-icon>delete</md-icon>
</md-icon-button>
<?php else: ?>
<md-icon-button class="oxy-prefetch-remove-exclusion"
toggle
slot="trailing-icon"
type="button"
<?php if (!$oxy_prefetch_prerender_href_exclusion_status): ?>disabled<?php endif; ?>>
<md-icon>delete</md-icon>
</md-icon-button>
<?php endif; ?>
</div>
<?php endforeach; ?>
<md-outlined-button class="oxy-prefetch-add-exclusion"
<?php if (!$oxy_prefetch_prerender_href_exclusion_status): ?>disabled<?php endif; ?>>
<?php esc_html_e('Add More', 'oxy-prefetch') ?>
</md-outlined-button>
</div>
</div>
</div>
<div class="oxy-prefetch-in-row">
<div class="oxy-prefetch-card">
<h2>
<?php esc_html_e('No-Vary-Search', 'oxy-prefetch') ?>
<small class="oxy-prefetch-smaller"><?php esc_html_e('(Only for moderate)', 'oxy-prefetch') ?></small>
<i class="dashicons dashicons-editor-help oxy-prefetch-has-tooltip"
data-tooltip="<?php esc_attr_e('Treats URLs that differ only by the listed query parameters as the same page, so a cached prefetch/prerender still matches.', 'oxy-prefetch') ?>"
data-href="https://developer.chrome.com/docs/web-platform/prerender-pages#no-vary-search"
data-href-text="<?php esc_attr_e('Learn More', 'oxy-prefetch'); ?>"></i>
</h2>
<div class="oxy-prefetch-switch">
<div class="oxy-prefetch-switch-wrap text-color-changer">
<md-switch id="oxy-prefetch-no-vary-search-status"
icons
name="oxy_prefetch_no_vary_search_status" <?php if ($oxy_prefetch_no_vary_search_status): ?> selected <?php endif; ?>></md-switch>
<span <?php if ($oxy_prefetch_no_vary_search_status): ?> class="active" <?php endif; ?>>
<?php esc_html_e('Ignore the query parameters below when matching', 'oxy-prefetch') ?>
</span>
</div>
<ul class="oxy-prefetch-note">
<li><?php esc_html_e('Space- or comma-separated parameter names (e.g. tracking and sort params).', 'oxy-prefetch') ?></li>
</ul>
<md-outlined-text-field class="oxy-prefetch-max-width has-clear-button"
name="oxy_prefetch_no_vary_search_params"
value="<?php echo esc_attr($oxy_prefetch_no_vary_search_params) ?>"
label="<?php esc_attr_e('Query parameters to ignore', 'oxy-prefetch') ?>"
type="text"
<?php if (!$oxy_prefetch_no_vary_search_status): ?>disabled<?php endif; ?>>
<md-icon-button toggle slot="trailing-icon" type="button">
<md-icon>cancel</md-icon>
</md-icon-button>
</md-outlined-text-field>
</div>
</div>
</div>
<md-filled-button id="oxy-prefetch-settings-save" class="oxy-prefetch-has-loading" type="button">
<?php esc_html_e('Save', 'oxy-prefetch'); ?>
</md-filled-button>
<div class="oxy-prefetch-spinner-wrap">
<div class="oxy-prefetch-spinner"></div>
<p><?php esc_html_e('Saving...Please wait.', 'oxy-prefetch'); ?></p>
</div>
</div>
<?php
}
/**
* @return void
*/
public function add_admin_assets($hook)
{
// Load only on the settings page and the post/page/product edit screens.
if (!in_array($hook, array('tools_page_oxy-prefetch-settings', 'post.php', 'post-new.php'), true)) {
return;
}
wp_register_script('oxy-prefetch-admin-script', plugins_url('assets/js/admin-script.js', __FILE__), array('jquery'), self::OXY_PREFETCH_VERSION);
wp_enqueue_script('oxy-prefetch-admin-script');
wp_register_style('oxy-prefetch-admin-style', plugins_url('assets/css/admin-style.css', __FILE__), array(), self::OXY_PREFETCH_VERSION);
wp_enqueue_style('oxy-prefetch-admin-style');
wp_localize_script(
'oxy-prefetch-admin-script',
'oxy_prefetch_defines',
array(
'trans' => array(
'number_between' => __('The number must be between %d and %d.', 'oxy-prefetch'),
'success' => __('Success!', 'oxy-prefetch'),
'failure' => __('Failure!', 'oxy-prefetch'),
'warning' => __('Warning!', 'oxy-prefetch'),
'info' => __('Info', 'oxy-prefetch'),
'path' => __('Path', 'oxy-prefetch'),
)
)
);
}
/**
* @return void
*/
public function add_gutenberg_assets()
{
wp_enqueue_script(
'oxy-prefetch-gutenberg-script',
plugins_url('assets/js/gutenberg-script.js', __FILE__),
array('wp-hooks', 'wp-blocks', 'wp-element', 'wp-editor', 'wp-data'),
filemtime(plugin_dir_path(__FILE__) . 'assets/js/gutenberg-script.js'),
true
);
}
/**
* @param $pre_count
* @param $type
* @return void
*/
private function make_speculation_rules($pre_count, $type)
{
global $wp;
global $wp_query;
for ($p = 0; $p < $pre_count; $p++) {
if (isset($wp_query->posts[$p]->ID)) {
$permalink = get_permalink($wp_query->posts[$p]->ID);
if ($permalink != home_url($wp->request) . '/') {
if (!isset($this->already_added[$type][$permalink])) {
if (!$this->is_excluded_by_default($permalink) && !$this->is_excluded_by_user($permalink)) {
$this->script_immediate[$type][] = $permalink;
}
$this->already_added[$type][$permalink] = 1;
}
}
}
}
}
/**
* Integrate with WordPress core Speculative Loading (shipped in WP 6.8).
*
* Core emits its own <script type="speculationrules"> block, so without this
* the page would ship two competing rule sets. We feed our default path
* exclusions into core's rules, and when any of our own speculative features
* are enabled we take over output by suppressing core's block.
*
* @return void
*/
public function integrate_with_core_speculative_loading()
{
if (!function_exists('wp_get_speculation_rules')) {
return;
}
// Keep state-changing links safe even when core is the one emitting rules.
add_filter('wp_speculation_rules_href_exclude_paths', array($this, 'add_core_speculation_exclusions'), 10, 1);
// Avoid double output: if we manage any rules ourselves, disable core's.
if ($this->is_any_speculation_feature_enabled()) {
add_filter('wp_speculation_rules_configuration', '__return_null');
}
}
/**
* Merge our default path exclusions into core's exclude-paths list.
*
* @param mixed $paths
* @return array
*/
public function add_core_speculation_exclusions($paths): array
{
$paths = is_array($paths) ? $paths : array();
return array_values(array_unique(array_merge($paths, $this->get_url_exclusions_default())));
}
/**
* @return bool
*/
private function is_any_speculation_feature_enabled(): bool
{
$flags = array(
get_option('oxy_prefetches_number_status', self::OXY_PREFETCHES_NUMBER_STATUS_DEFAULT),
get_option('oxy_prefetch_hover_status', self::OXY_PREFETCHES_HOVER_STATUS_DEFAULT),
get_option('oxy_prefetch_prerender_number_status', self::OXY_PREFETCH_PRERENDER_NUMBER_STATUS_DEFAULT),
get_option('oxy_prefetch_prerender_hover_status', self::OXY_PREFETCH_PRERENDER_HOVER_STATUS_DEFAULT),
);
return in_array('true', $flags, true);
}
/**
* @return void
*/
public function add_speculation_rules_script()
{
$this->add_prefetch_script_immediate();
$this->add_prerender_script_immediate();
$this->add_prefetch_script_moderate();
$this->add_prerender_script_moderate();
$this->add_to_page();
}
/**
* @return void
*/
private function add_to_page()
{
/**
* Prefetch and Prerender immediately
*/
if (count($this->script_immediate)) {
// Prerender
if (isset($this->script_immediate['prerender'])) {
$this->script_immediate['prerender'] = array(
array(
'source' => 'list',
'urls' => $this->script_immediate['prerender'],
'eagerness' => 'immediate'
)
);
}
// Prefetch
if (isset($this->script_immediate['prefetch'])) {
$this->script_immediate['prefetch'] = array(
array(
'source' => 'list',
'urls' => $this->script_immediate['prefetch'],
'eagerness' => 'immediate'
)
);
}
/**
* Filter the immediate (list-source) speculation rules before output.
* Returning an empty array suppresses the block — useful for sites that
* prefer delivering rules via the Speculation-Rules HTTP header.
*/
$immediate = apply_filters('oxy_prefetch_immediate_rules', $this->script_immediate);
if (!empty($immediate)) {
echo
'<script type="speculationrules">'
. wp_json_encode($immediate, JSON_UNESCAPED_SLASHES) .
'</script>';
}
}
/**
* Prefetch and Prerender on mouse hover
*/
if (count($this->script_moderate)) {
/**
* Filter the moderate (document-source) speculation rules before output.
*/
$moderate = apply_filters('oxy_prefetch_moderate_rules', $this->script_moderate);
if (!empty($moderate)) {
echo
'<script type="speculationrules">'
. wp_json_encode($moderate, JSON_UNESCAPED_SLASHES) .
'</script>';
}
}
}
/**
* @return void
*/
private function add_prefetch_script_immediate()
{
global $wp;
// Prefetch depending on the oxy_prefetches_number
$oxy_prefetches_number_status = get_option('oxy_prefetches_number_status', self::OXY_PREFETCHES_NUMBER_STATUS_DEFAULT) == 'true';
if ($oxy_prefetches_number_status) {
global $wp_query;
if ($wp_query && $wp_query->posts) {
$oxy_prefetches_number = get_option('oxy_prefetches_number', self::OXY_PREFETCHES_NUMBER_DEFAULT);
$posts_count = count($wp_query->posts);
if ($posts_count < $oxy_prefetches_number) {
$oxy_prefetches_number = $posts_count;
}
$this->make_speculation_rules($oxy_prefetches_number, 'prefetch');
}
}
// Prefetch depending on the oxy_static_prefetch
$current_url = home_url($wp->request);
$post_id = url_to_postid($current_url);
$prefetch_status = get_post_meta($post_id, '_oxy_prefetch_status', true);
if ($prefetch_status) {
$prefetch_urls = get_post_meta($post_id, '_oxy_prefetch_url');
foreach ($prefetch_urls as $prefetch_url) {
if (!isset($this->already_added['prefetch'][$prefetch_url])) {
if (!$this->is_excluded_by_default($prefetch_url)) {
$this->script_immediate['prefetch'][] = $prefetch_url;
}
$this->already_added['prefetch'][$prefetch_url] = 1;
}
}
}
}
/**
* @return void
*/
private function add_prerender_script_immediate()
{
global $wp;
/**
* Prerender depending on the oxy_prefetch_prerender_number
*/
$oxy_prefetch_prerender_number_status = get_option('oxy_prefetch_prerender_number_status', self::OXY_PREFETCH_PRERENDER_NUMBER_STATUS_DEFAULT) == 'true';
if ($oxy_prefetch_prerender_number_status) {
global $wp_query;
if ($wp_query && $wp_query->posts) {
$oxy_prefetch_prerender_number = get_option('oxy_prefetch_prerender_number', self::OXY_PREFETCH_PRERENDER_NUMBER_DEFAULT);
$posts_count = count($wp_query->posts);
if ($posts_count < $oxy_prefetch_prerender_number) {
$oxy_prefetch_prerender_number = $posts_count;
}
$this->make_speculation_rules($oxy_prefetch_prerender_number, 'prerender');
}
}
/**
* Prerender depending on the oxy_static_prerender
*/
$current_url = home_url($wp->request);
$post_id = url_to_postid($current_url);
$prerender_status = get_post_meta($post_id, '_oxy_prefetch_prerender_status', true);
if ($prerender_status) {
$prerender_urls = get_post_meta($post_id, '_oxy_prefetch_prerender_url');
foreach ($prerender_urls as $prerender_url) {
if (!isset($this->already_added['prerender'][$prerender_url])) {
if (!$this->is_excluded_by_default($prerender_url)) {
$this->script_immediate['prerender'][] = $prerender_url;
}
$this->already_added['prerender'][$prerender_url] = 1;
}
}
}
}
/**
* @return void
*/
private function add_prefetch_script_moderate()
{
$oxy_prefetch_hover_status = get_option('oxy_prefetch_hover_status', self::OXY_PREFETCHES_HOVER_STATUS_DEFAULT) == 'true';
if ($oxy_prefetch_hover_status) {
$this->script_moderate['prefetch'] = array($this->build_document_rule('prefetch'));
}
}
/**
* Prerender on mouse hover
* @return void
*/
private function add_prerender_script_moderate()
{
$oxy_prefetch_prerender_hover_status = get_option('oxy_prefetch_prerender_hover_status', self::OXY_PREFETCH_PRERENDER_HOVER_STATUS_DEFAULT) == 'true';
if ($oxy_prefetch_prerender_hover_status) {
$this->script_moderate['prerender'] = array($this->build_document_rule('prerender'));
}
}
/**
* Build a document-source ("moderate") speculation rule for the given type.
*
* Includes default path/query exclusions, CSS opt-out (selector_matches),
* user href exclusions, a configurable eagerness and No-Vary-Search support.
*
* @param string $type 'prefetch' | 'prerender'
* @return array
*/
private function build_document_rule(string $type): array
{
// Base: every same-origin link.
$where_and = array(
array('href_matches' => '/*'),
);
// Default path exclusions (login, admin, cart/checkout/account, ...).
foreach ($this->get_url_exclusions_default() as $exclusion) {
$where_and[] = array('not' => array('href_matches' => $exclusion));
}
// Default state-changing query exclusions (add-to-cart, _wpnonce, ...).
foreach ($this->get_query_string_exclusions_default() as $key) {
$where_and[] = array('not' => array('href_matches' => '/*\\?*' . $key . '=*'));
}
// CSS opt-out: honour .no-prefetch/.no-prerender and rel="nofollow".
foreach ($this->get_selector_exclusions($type) as $selector) {
$where_and[] = array('not' => array('selector_matches' => $selector));
}
// User-defined href exclusions.
if (get_option('oxy_prefetch_prerender_href_exclusion_status') == 'true') {
$user_match = get_option('oxy_prefetch_prerender_match', self::OXY_PREFETCH_PRERENDER_EXCLUSION_DEFAULT);
if (!empty($user_match['href'][0])) {
foreach ($user_match['href'] as $href) {
$where_and[] = array('not' => array('href_matches' => $href));
}
}
}
$rule = array(
'source' => 'document',
'where' => array('and' => $where_and),
'eagerness' => $this->get_eagerness($type),
);
// No-Vary-Search: match URLs that differ only by tracking/sort params.
$no_vary_search = $this->get_no_vary_search_value();
if ($no_vary_search !== '') {
$rule['expects_no_vary_search'] = $no_vary_search;
}
return $rule;
}
/**
* Resolve the configured eagerness for a rule type, falling back to default.
*
* @param string $type 'prefetch' | 'prerender'
* @return string
*/
private function get_eagerness(string $type): string
{
$option = $type === 'prerender' ? 'oxy_prefetch_prerender_hover_eagerness' : 'oxy_prefetch_hover_eagerness';
$value = get_option($option, self::OXY_PREFETCH_EAGERNESS_DEFAULT);
return in_array($value, self::OXY_PREFETCH_EAGERNESS_VALUES, true) ? $value : self::OXY_PREFETCH_EAGERNESS_DEFAULT;
}
/**
* @param mixed $value
* @return string
*/
private function sanitize_eagerness($value): string
{
$value = sanitize_text_field((string)$value);
return in_array($value, self::OXY_PREFETCH_EAGERNESS_VALUES, true) ? $value : self::OXY_PREFETCH_EAGERNESS_DEFAULT;
}
/**
* CSS selectors that opt a link out of speculation.
*
* @param string $type 'prefetch' | 'prerender'
* @return string[]
*/
private function get_selector_exclusions(string $type): array
{
$class = $type === 'prerender' ? '.no-prerender' : '.no-prefetch';
$selectors = array($class . ', .no-speculation, a[rel~="nofollow"]');
return apply_filters('oxy_prefetch_selector_exclusions', $selectors, $type);
}
/**
* Build the No-Vary-Search header value (e.g. params=("utm_source" ...)).
*
* @return string Empty string when disabled or no params configured.
*/
private function get_no_vary_search_value(): string
{
if (get_option('oxy_prefetch_no_vary_search_status', self::OXY_PREFETCH_NO_VARY_SEARCH_STATUS_DEFAULT) != 'true') {
return '';
}
$raw = (string)get_option('oxy_prefetch_no_vary_search_params', self::OXY_PREFETCH_NO_VARY_SEARCH_PARAMS_DEFAULT);
$params = preg_split('/[\s,]+/', trim($raw), -1, PREG_SPLIT_NO_EMPTY);
if (empty($params)) {
return '';
}
$quoted = array();
foreach ($params as $param) {
$quoted[] = '"' . $param . '"';
}
return 'params=(' . implode(' ', $quoted) . ')';
}
/**
* @return void
*/
public function dismiss_prerender_notice()
{
try {
if (is_admin() && isset($_POST['oxy_prefetch_dismiss_prerender_notice_nonce'])) {
if (!current_user_can('manage_options')) {
wp_send_json_error(array('message' => __('Permission denied.', 'oxy-prefetch')), 403);
}
if (wp_verify_nonce($_POST['oxy_prefetch_dismiss_prerender_notice_nonce'], 'dismiss_prerender_notice')) {
update_option('oxy_prefetch_prerender_notice_dismissed', 'true', false);
wp_send_json_success(array('message' => __('Successfully Saved.', 'oxy-prefetch')), 200);
}
wp_send_json_error(array('message' => __('Wrong Nonce! Refresh the page.', 'oxy-prefetch')), 500);
}
} catch (Exception $e) {
wp_send_json_error(array('message' => $e->getMessage()), 500);
}
wp_send_json_error(array('message' => __('Error!', 'oxy-prefetch')), 500);
}
/**
* @return void
*/
public function dismiss_core_notice()
{
try {
if (is_admin() && isset($_POST['oxy_prefetch_dismiss_core_notice_nonce'])) {
if (!current_user_can('manage_options')) {
wp_send_json_error(array('message' => __('Permission denied.', 'oxy-prefetch')), 403);
}
if (wp_verify_nonce($_POST['oxy_prefetch_dismiss_core_notice_nonce'], 'dismiss_core_notice')) {
update_option('oxy_prefetch_core_notice_dismissed', 'true', false);
wp_send_json_success(array('message' => __('Successfully Saved.', 'oxy-prefetch')), 200);
}
wp_send_json_error(array('message' => __('Wrong Nonce! Refresh the page.', 'oxy-prefetch')), 500);
}
} catch (Exception $e) {
wp_send_json_error(array('message' => $e->getMessage()), 500);
}
wp_send_json_error(array('message' => __('Error!', 'oxy-prefetch')), 500);
}
/**
* @return void
*/
public function save_prefetch_settings()
{
try {
if (is_admin() && isset($_POST['oxy_prefetch_settings_nonce'])) {
if (!current_user_can('manage_options')) {
wp_send_json_error(array('message' => __('Permission denied.', 'oxy-prefetch')), 403);
}
if (wp_verify_nonce($_POST['oxy_prefetch_settings_nonce'], 'save_prefetch_settings')) {
// Prefetches Number Status
$oxy_prefetches_number_status = isset($_POST['oxy_prefetches_number_status']) ? 'true' : 'false';
// Prefetches Number
if ($oxy_prefetches_number_status == 'true') {
$oxy_prefetches_number = (int)($_POST['oxy_prefetches_number'] ?? 0);
if ($oxy_prefetches_number > self::OXY_PREFETCHES_NUMBER_MAX) {
$message = esc_html(sprintf(__('Max number of prefetches is %d.', 'oxy-prefetch'), self::OXY_PREFETCHES_NUMBER_MAX));
wp_send_json_error(array('message' => $message), 422);
}
if ($oxy_prefetches_number < self::OXY_PREFETCHES_NUMBER_MIN) {
$message = esc_html(sprintf(__('Min number of prefetches is %d.', 'oxy-prefetch'), self::OXY_PREFETCHES_NUMBER_MIN));
wp_send_json_error(array('message' => $message), 422);
}
} else {
$oxy_prefetches_number = (int)(get_option('oxy_prefetches_number', self::OXY_PREFETCHES_NUMBER_DEFAULT));
}
// Prefetch Hover Status
$oxy_prefetch_hover_status = isset($_POST['oxy_prefetch_hover_status']) ? 'true' : 'false';
// Prerender Number Status
$oxy_prefetch_prerender_number_status = isset($_POST['oxy_prefetch_prerender_number_status']) ? 'true' : 'false';
// Prerender Number
if ($oxy_prefetch_prerender_number_status == 'true') {
$oxy_prefetch_prerender_number = (int)($_POST['oxy_prefetch_prerender_number'] ?? 0);
if ($oxy_prefetch_prerender_number > self::OXY_PREFETCH_PRERENDER_NUMBER_MAX) {
$message = esc_html(sprintf(__('Max number of prerenders is %d.', 'oxy-prefetch'), self::OXY_PREFETCH_PRERENDER_NUMBER_MAX));
wp_send_json_error(array('message' => $message), 422);
}
if ($oxy_prefetch_prerender_number < self::OXY_PREFETCH_PRERENDER_NUMBER_MIN) {
$message = esc_html(sprintf(__('Min number of prerenders is %d.', 'oxy-prefetch'), self::OXY_PREFETCH_PRERENDER_NUMBER_MIN));
wp_send_json_error(array('message' => $message), 422);
}
} else {
$oxy_prefetch_prerender_number = (int)(get_option('oxy_prefetch_prerender_number', self::OXY_PREFETCH_PRERENDER_NUMBER_DEFAULT));