OMGF | GDPR/DSVGO Compliant, Faster Google Fonts. Easy. - Version 5.0.0

Version Description

  • The Better, Bigger, Faster, Stronger, Cooler, Awesomer Edition | March 4th, 2022 =
  • Added: Parse entire HTML document for Google Fonts stylesheets (instead of just wp_head())
  • Added: Merged both Optimization Modes option into one automatically running option: - A first scan is done upon Save & Optimize, - A quick check is done on pageload, to see if other Google Fonts are found than the ones already found, and if so, they're downloaded and replaced on-the-fly.
  • Enhanced: The Download API is replaced for an easier, leaner and faster alternative and no longer uses the WordPress API. - If the first request fails, a mirror is used to retry the request, before throwing an error. - Fixes rest_no_route errors in some configurations.
  • Enhanced: The Task Manager now offers a quick overview of downloaded stylesheets and their status, along with simple management tasks, e.g. cache flush, configure stylesheet and/or remove. - When cache is marked as stale, it's now possible to refresh the cache and maintain your stylesheet configuration.
  • Added: Resource hints enqueued in wp_resource_hints() are now properly removed.
  • Fixed: Smart Slider 3 compatibility.
  • Several bugfixes, UX improvements and code optimizations.
Download this release

Release Info

Developer DaanvandenBergh
Plugin Icon 128x128 OMGF | GDPR/DSVGO Compliant, Faster Google Fonts. Easy.
Version 5.0.0
Comparing to
See all releases

Code changes from version 4.6.0 to 5.0.0

assets/css/omgf-admin.css CHANGED
@@ -9,8 +9,8 @@
9
  *
10
  * @package : OMGF
11
  * @author : Daan van den Bergh
12
- * @copyright: (c) 2021 Daan van den Bergh
13
- * @url : https://daan.dev
14
  * * * * * * * * * * * * * * * * * * * */
15
  /**
16
  * General
@@ -50,108 +50,46 @@
50
  .omgf form .dashicons {
51
  line-height: 15px;
52
  }
53
- .omgf form .omgf-manual-optimization-mode .pro-con-container,
54
- .omgf form .omgf-automatic-optimization-mode .pro-con-container {
55
- display: flex;
56
- justify-content: center;
57
- }
58
- .omgf form .omgf-manual-optimization-mode .pro-con-container .pros,
59
- .omgf form .omgf-automatic-optimization-mode .pro-con-container .pros,
60
- .omgf form .omgf-manual-optimization-mode .pro-con-container .cons,
61
- .omgf form .omgf-automatic-optimization-mode .pro-con-container .cons {
62
- width: 50%;
63
- }
64
- .omgf form .omgf-manual-optimization-mode .pro-con-container .pros .pros-list,
65
- .omgf form .omgf-automatic-optimization-mode .pro-con-container .pros .pros-list,
66
- .omgf form .omgf-manual-optimization-mode .pro-con-container .cons .pros-list,
67
- .omgf form .omgf-automatic-optimization-mode .pro-con-container .cons .pros-list,
68
- .omgf form .omgf-manual-optimization-mode .pro-con-container .pros .cons-list,
69
- .omgf form .omgf-automatic-optimization-mode .pro-con-container .pros .cons-list,
70
- .omgf form .omgf-manual-optimization-mode .pro-con-container .cons .cons-list,
71
- .omgf form .omgf-automatic-optimization-mode .pro-con-container .cons .cons-list {
72
- list-style: none;
73
- margin-left: 0;
74
- padding-left: 0;
75
- }
76
- .omgf form .omgf-manual-optimization-mode .pro-con-container .pros .pros-list li,
77
- .omgf form .omgf-automatic-optimization-mode .pro-con-container .pros .pros-list li,
78
- .omgf form .omgf-manual-optimization-mode .pro-con-container .cons .pros-list li,
79
- .omgf form .omgf-automatic-optimization-mode .pro-con-container .cons .pros-list li,
80
- .omgf form .omgf-manual-optimization-mode .pro-con-container .pros .cons-list li,
81
- .omgf form .omgf-automatic-optimization-mode .pro-con-container .pros .cons-list li,
82
- .omgf form .omgf-manual-optimization-mode .pro-con-container .cons .cons-list li,
83
- .omgf form .omgf-automatic-optimization-mode .pro-con-container .cons .cons-list li {
84
- padding-left: 1.5em;
85
- text-indent: -2em;
86
- line-height: 18px;
87
- }
88
- .omgf form .omgf-manual-optimization-mode .pro-con-container .pros .pros-list li:before,
89
- .omgf form .omgf-automatic-optimization-mode .pro-con-container .pros .pros-list li:before,
90
- .omgf form .omgf-manual-optimization-mode .pro-con-container .cons .pros-list li:before,
91
- .omgf form .omgf-automatic-optimization-mode .pro-con-container .cons .pros-list li:before,
92
- .omgf form .omgf-manual-optimization-mode .pro-con-container .pros .cons-list li:before,
93
- .omgf form .omgf-automatic-optimization-mode .pro-con-container .pros .cons-list li:before,
94
- .omgf form .omgf-manual-optimization-mode .pro-con-container .cons .cons-list li:before,
95
- .omgf form .omgf-automatic-optimization-mode .pro-con-container .cons .cons-list li:before {
96
- font-family: 'dashicons';
97
- font-size: 18px;
98
- vertical-align: middle;
99
- margin-right: 0.5em;
100
- }
101
- .omgf form .omgf-manual-optimization-mode .pro-con-container .pros .pros-list li:before,
102
- .omgf form .omgf-automatic-optimization-mode .pro-con-container .pros .pros-list li:before,
103
- .omgf form .omgf-manual-optimization-mode .pro-con-container .cons .pros-list li:before,
104
- .omgf form .omgf-automatic-optimization-mode .pro-con-container .cons .pros-list li:before {
105
- content: "\f147";
106
- color: #2ECC40;
107
- }
108
- .omgf form .omgf-manual-optimization-mode .pro-con-container .pros .cons-list li:before,
109
- .omgf form .omgf-automatic-optimization-mode .pro-con-container .pros .cons-list li:before,
110
- .omgf form .omgf-manual-optimization-mode .pro-con-container .cons .cons-list li:before,
111
- .omgf form .omgf-automatic-optimization-mode .pro-con-container .cons .cons-list li:before {
112
- content: "\f158";
113
- color: #FF4136;
114
- }
115
- .omgf form .omgf-manual-optimization-mode .status,
116
- .omgf form .omgf-automatic-optimization-mode .status {
117
  padding-left: 0;
118
  line-height: 1;
119
  }
120
- .omgf form .omgf-manual-optimization-mode .status ul,
121
- .omgf form .omgf-automatic-optimization-mode .status ul {
122
  margin-top: 5px;
123
  list-style: none;
124
  margin-left: 0;
125
  padding-left: 0;
126
  }
127
- .omgf form .omgf-manual-optimization-mode .status ul li,
128
- .omgf form .omgf-automatic-optimization-mode .status ul li {
129
  padding-left: 1.5em;
130
  text-indent: -2em;
131
- line-height: 18px;
132
  }
133
- .omgf form .omgf-manual-optimization-mode .status ul li:before,
134
- .omgf form .omgf-automatic-optimization-mode .status ul li:before {
135
  font-family: 'dashicons';
136
- font-size: 18px;
137
- vertical-align: middle;
138
- margin-right: 0.5em;
139
  }
140
- .omgf form .omgf-manual-optimization-mode .status ul li.stale:before,
141
- .omgf form .omgf-automatic-optimization-mode .status ul li.stale:before {
142
  content: "\f534";
143
  color: #FF851B;
144
  }
145
- .omgf form .omgf-manual-optimization-mode .status ul li.found:before,
146
- .omgf form .omgf-automatic-optimization-mode .status ul li.found:before {
147
- content: "\f147";
148
  color: #2ECC40;
149
  }
150
- .omgf form .omgf-manual-optimization-mode .status ul li.not-found:before,
151
- .omgf form .omgf-automatic-optimization-mode .status ul li.not-found:before {
152
  content: "\f158";
153
  color: #FF4136;
154
  }
 
 
 
 
 
 
 
 
155
  .omgf-optimize-fonts-container {
156
  text-align: center;
157
  padding: 25px 50px;
@@ -183,6 +121,7 @@
183
  position: relative;
184
  font-size: 16px;
185
  line-height: 16px;
 
186
  }
187
  .omgf-optimize-fonts-container .omgf-optimize-fonts-manage table .tooltip .tooltip-text {
188
  visibility: hidden;
@@ -248,11 +187,6 @@
248
  font-size: 18px;
249
  font-weight: bold;
250
  }
251
- .omgf-optimize-fonts-container .omgf-optimize-fonts-description #omgf_manual_optimize_url {
252
- font-size: 18px;
253
- padding: 0 15px;
254
- margin-left: 10px;
255
- }
256
  .omgf-optimize-fonts-container .omgf-optimize-fonts-tooltip {
257
  padding: 0 15px 5px;
258
  }
9
  *
10
  * @package : OMGF
11
  * @author : Daan van den Bergh
12
+ * @copyright: © 2022 Daan van den Bergh
13
+ * @url : https://ffw.press
14
  * * * * * * * * * * * * * * * * * * * */
15
  /**
16
  * General
50
  .omgf form .dashicons {
51
  line-height: 15px;
52
  }
53
+ .omgf form .omgf-task-manager .task-manager-row {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
54
  padding-left: 0;
55
  line-height: 1;
56
  }
57
+ .omgf form .omgf-task-manager ul {
 
58
  margin-top: 5px;
59
  list-style: none;
60
  margin-left: 0;
61
  padding-left: 0;
62
  }
63
+ .omgf form .omgf-task-manager ul li {
 
64
  padding-left: 1.5em;
65
  text-indent: -2em;
66
+ line-height: 1.5em;
67
  }
68
+ .omgf form .omgf-task-manager ul li:before {
 
69
  font-family: 'dashicons';
70
+ font-size: 16px;
71
+ vertical-align: -3px;
 
72
  }
73
+ .omgf form .omgf-task-manager ul li.stale:before {
 
74
  content: "\f534";
75
  color: #FF851B;
76
  }
77
+ .omgf form .omgf-task-manager ul li.found:before {
78
+ content: "\f15e";
 
79
  color: #2ECC40;
80
  }
81
+ .omgf form .omgf-task-manager ul li.not-found:before {
 
82
  content: "\f158";
83
  color: #FF4136;
84
  }
85
+ .omgf form .omgf-task-manager ul li.stale-cache-notice:before {
86
+ content: "\f348";
87
+ color: #0074D9;
88
+ }
89
+ .omgf form .omgf-task-manager ul li.unloaded:before {
90
+ content: "\f460";
91
+ color: #0074D9;
92
+ }
93
  .omgf-optimize-fonts-container {
94
  text-align: center;
95
  padding: 25px 50px;
121
  position: relative;
122
  font-size: 16px;
123
  line-height: 16px;
124
+ height: 12px;
125
  }
126
  .omgf-optimize-fonts-container .omgf-optimize-fonts-manage table .tooltip .tooltip-text {
127
  visibility: hidden;
187
  font-size: 18px;
188
  font-weight: bold;
189
  }
 
 
 
 
 
190
  .omgf-optimize-fonts-container .omgf-optimize-fonts-tooltip {
191
  padding: 0 15px 5px;
192
  }
assets/css/omgf-admin.css.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["omgf-admin.less"],"names":[],"mappings":";;;;;;;;;;;;;;;;;AAkBA,KACE;EACE,WAAA;EACA,qBAAA;EACA,yBAAA;EACA,gBAAA;EACA,eAAA;EACA,kBAAA;EACA,mBAAA;EACA,4BAAA;;AAEA,KAVF,eAUG;EACC,eAAA;EACA,mBAAA;EACA,WAAA;EACA,qBAAA;;;;;AAQN;EACE,oBAAA;;AADF,SAGE;EACE,eAAA;;AAJJ,SAOE,kBAAiB;EACf,oBAAA;EACA,mBAAA;;AAIJ,KAAM;EACJ,iBAAA;;AADF,KAAM,KAGJ;EACE,iBAAA;;AAJJ,KAAM,KAQJ,+BAEE;AAVJ,KAAM,KASJ,kCACE;EACE,aAAA;EACA,uBAAA;;AAZN,KAAM,KAQJ,+BAEE,mBAIE;AAdN,KAAM,KASJ,kCACE,mBAIE;AAdN,KAAM,KAQJ,+BAEE,mBAIS;AAdb,KAAM,KASJ,kCACE,mBAIS;EACL,UAAA;;AAfR,KAAM,KAQJ,+BAEE,mBAIE,MAGE;AAjBR,KAAM,KASJ,kCACE,mBAIE,MAGE;AAjBR,KAAM,KAQJ,+BAEE,mBAIS,MAGL;AAjBR,KAAM,KASJ,kCACE,mBAIS,MAGL;AAjBR,KAAM,KAQJ,+BAEE,mBAIE,MAIE;AAlBR,KAAM,KASJ,kCACE,mBAIE,MAIE;AAlBR,KAAM,KAQJ,+BAEE,mBAIS,MAIL;AAlBR,KAAM,KASJ,kCACE,mBAIS,MAIL;EACE,gBAAA;EACA,cAAA;EACA,eAAA;;AArBV,KAAM,KAQJ,+BAEE,mBAIE,MAGE,WAME;AAvBV,KAAM,KASJ,kCACE,mBAIE,MAGE,WAME;AAvBV,KAAM,KAQJ,+BAEE,mBAIS,MAGL,WAME;AAvBV,KAAM,KASJ,kCACE,mBAIS,MAGL,WAME;AAvBV,KAAM,KAQJ,+BAEE,mBAIE,MAIE,WAKE;AAvBV,KAAM,KASJ,kCACE,mBAIE,MAIE,WAKE;AAvBV,KAAM,KAQJ,+BAEE,mBAIS,MAIL,WAKE;AAvBV,KAAM,KASJ,kCACE,mBAIS,MAIL,WAKE;EACE,mBAAA;EACA,iBAAA;EACA,iBAAA;;AA1BZ,KAAM,KAQJ,+BAEE,mBAIE,MAGE,WAYE,GAAE;AA7BZ,KAAM,KASJ,kCACE,mBAIE,MAGE,WAYE,GAAE;AA7BZ,KAAM,KAQJ,+BAEE,mBAIS,MAGL,WAYE,GAAE;AA7BZ,KAAM,KASJ,kCACE,mBAIS,MAGL,WAYE,GAAE;AA7BZ,KAAM,KAQJ,+BAEE,mBAIE,MAIE,WAWE,GAAE;AA7BZ,KAAM,KASJ,kCACE,mBAIE,MAIE,WAWE,GAAE;AA7BZ,KAAM,KAQJ,+BAEE,mBAIS,MAIL,WAWE,GAAE;AA7BZ,KAAM,KASJ,kCACE,mBAIS,MAIL,WAWE,GAAE;EACA,aAAa,WAAb;EACA,eAAA;EACA,sBAAA;EACA,mBAAA;;AAjCZ,KAAM,KAQJ,+BAEE,mBAIE,MAuBE,WACE,GAAE;AAtCZ,KAAM,KASJ,kCACE,mBAIE,MAuBE,WACE,GAAE;AAtCZ,KAAM,KAQJ,+BAEE,mBAIS,MAuBL,WACE,GAAE;AAtCZ,KAAM,KASJ,kCACE,mBAIS,MAuBL,WACE,GAAE;EACA,SAAS,OAAT;EACA,cAAA;;AAxCZ,KAAM,KAQJ,+BAEE,mBAIE,MA8BE,WACE,GAAE;AA7CZ,KAAM,KASJ,kCACE,mBAIE,MA8BE,WACE,GAAE;AA7CZ,KAAM,KAQJ,+BAEE,mBAIS,MA8BL,WACE,GAAE;AA7CZ,KAAM,KASJ,kCACE,mBAIS,MA8BL,WACE,GAAE;EACA,SAAS,OAAT;EACA,cAAA;;AA/CZ,KAAM,KAQJ,+BA6CE;AArDJ,KAAM,KASJ,kCA4CE;EACE,eAAA;EACA,cAAA;;AAvDN,KAAM,KAQJ,+BA6CE,QAIE;AAzDN,KAAM,KASJ,kCA4CE,QAIE;EACE,eAAA;EACA,gBAAA;EACA,cAAA;EACA,eAAA;;AA7DR,KAAM,KAQJ,+BA6CE,QAIE,GAME;AA/DR,KAAM,KASJ,kCA4CE,QAIE,GAME;EACE,mBAAA;EACA,iBAAA;EACA,iBAAA;;AAEA,KApEJ,KAQJ,+BA6CE,QAIE,GAME,GAKG;AAAD,KApEJ,KASJ,kCA4CE,QAIE,GAME,GAKG;EACC,aAAa,WAAb;EACA,eAAA;EACA,sBAAA;EACA,mBAAA;;AAGF,KA3EJ,KAQJ,+BA6CE,QAIE,GAME,GAYG,MAAM;AAAP,KA3EJ,KASJ,kCA4CE,QAIE,GAME,GAYG,MAAM;EACL,SAAS,OAAT;EACA,cAAA;;AAGF,KAhFJ,KAQJ,+BA6CE,QAIE,GAME,GAiBG,MAAM;AAAP,KAhFJ,KASJ,kCA4CE,QAIE,GAME,GAiBG,MAAM;EACL,SAAS,OAAT;EACA,cAAA;;AAGF,KArFJ,KAQJ,+BA6CE,QAIE,GAME,GAsBG,UAAU;AAAX,KArFJ,KASJ,kCA4CE,QAIE,GAME,GAsBG,UAAU;EACT,SAAS,OAAT;EACA,cAAA;;AASZ;EACE,kBAAA;EACA,kBAAA;EACA,iBAAA;EACA,yBAAA;EACA,iBAAA;EACA,kBAAA;;AANF,8BAQE;EACE,kBAAA;EACA,YAAA;EACA,MAAA;EACA,gBAAA;EACA,eAAA;EACA,cAAA;;AAdJ,8BAiBE;EACE,gBAAA;EACA,aAAA;;AAnBJ,8BAsBE;EACE,gBAAA;;AAvBJ,8BAsBE,4BAGE;EACE,WAAA;EACA,yBAAA;;AA3BN,8BAsBE,4BAGE,MAIE;EACE,kBAAA;EACA,eAAA;EACA,iBAAA;;AAhCR,8BAsBE,4BAGE,MAIE,SAKE;EACE,kBAAA;EACA,kBAAA;EACA,SAAA;EACA,UAAA;EACA,cAAA;EACA,qCAAA;EACA,gDAA8C,oDAA+C,4BAA7F;EACA,gBAAA;EACA,WAAA;EACA,gBAAA;EACA,YAAA;EACA,aAAA;EACA,mBAAA;EACA,kBAAA;;AAhDV,8BAsBE,4BAGE,MAIE,SAKE,cAgBE;EACE,gBAAA;;AAIJ,8BAjCN,4BAGE,MAIE,SA0BG,MAAO;EACN,mBAAA;;AAxDV,8BAsBE,4BAGE,MAmCE,MACE;EACE,UAAA;;AA9DV,8BAsBE,4BAGE,MAyCE;EACE,yBAAA;;AAnER,8BAsBE,4BAGE,MAyCE,MAGE;EACE,qBAAA;EACA,UAAA;;AAvEV,8BAsBE,4BAGE,MAyCE,MAQE;EACE,mBAAA;EACA,UAAA;;AA5EV,8BAsBE,4BAGE,MAyCE,MAQE,GAIE;EACE,gBAAA;;AA/EZ,8BAsBE,4BAGE,MAyCE,MAQE,GAQE;EACE,iBAAA;EACA,gBAAA;;AAKF,8BAnER,4BAGE,MAyCE,MAsBE,GACG,WACC;EACE,oBAAA;;AA3Fd,8BAmGE,iCACE;EACE,kBAAA;;AArGN,8BAmGE,iCAKE;AAxGJ,8BAmGE,iCAME;EACE,gBAAA;EACA,UAAA;EACA,qBAAA;EACA,mBAAA;;AA7GN,8BAmGE,iCAKE,0BAOE,KAAI;AA/GV,8BAmGE,iCAME,0BAME,KAAI;EACF,oBAAA;;AAhHR,8BAmGE,iCAiBE;EACE,eAAA;EACA,iBAAA;;AAtHN,8BAmGE,iCAsBE;EACE,eAAA;EACA,eAAA;EACA,iBAAA;;AA5HN,8BAgIE;EACE,mBAAA;;AAjIJ,8BAoIE;AApIF,8BAqIE;EACE,mBAAA;;AAIJ,eACE;EACE,mBAAA;;AAFJ,eACE,SAGE;EACE,aAAA;EACA,mBAAA;EACA,8BAAA;;AAPN,eACE,SAGE,kBAKE,QACE,GACE;EACE,mBAAA;;AAEA,eAbV,SAGE,kBAKE,QACE,GACE,GAGG;EACC,mBAAA;;AAfd,eACE,SAGE,kBAKE,QACE,GACE,GAOE;EACE,qBAAA;EACA,iBAAA;;AAGE,eAtBd,SAGE,kBAKE,QACE,GACE,GAOE,EAIE,EACG;EACC,iBAAA;EACA,cAAA;;AAOV,eA/BN,SAGE,kBAKE,QAuBG;EACC,kBAAA;;AADF,eA/BN,SAGE,kBAKE,QAuBG,KAGC;EACE,kBAAA;;AAJJ,eA/BN,SAGE,kBAKE,QAuBG,KAGC,WAGE;EACE,cAAA;;AASd,wBAA0C;EACxC;IACE,cAAA;;EADF,8BAGE;IACE,kBAAA;IACA,aAAA;IACA,YAAA;;;;;;AAQN;EACE,eAAA;EACA,0CAAA;EACA,WAAA;EACA,YAAA;EACA,MAAA;EACA,kBAAA;;AANF,aAQE;EACE,QAAA;EACA,SAAA;EACA,kBAAA;EACA,eAAe,gBAAf;EACA,WAAW,gBAAX;;;;;AAOH,gBACC;EACE,uBAAA;;AAIA,gBADF,WACG;EACC,sBAAA;;AAGF,gBALF,WAKG,WAAW;EACV,cAAA;;AAXL,gBAeC;EACE,WAAA"}
1
+ {"version":3,"sources":["omgf-admin.less"],"names":[],"mappings":";;;;;;;;;;;;;;;;;AAkBA,KACE;EACE,WAAA;EACA,qBAAA;EACA,yBAAA;EACA,gBAAA;EACA,eAAA;EACA,kBAAA;EACA,mBAAA;EACA,4BAAA;;AAEA,KAVF,eAUG;EACC,eAAA;EACA,mBAAA;EACA,WAAA;EACA,qBAAA;;;;;AAQN;EACE,oBAAA;;AADF,SAGE;EACE,eAAA;;AAJJ,SAOE,kBAAiB;EACf,oBAAA;EACA,mBAAA;;AAIJ,KAAM;EACJ,iBAAA;;AADF,KAAM,KAGJ;EACE,iBAAA;;AAJJ,KAAM,KAQJ,mBACE;EACE,eAAA;EACA,cAAA;;AAXN,KAAM,KAQJ,mBAME;EACE,eAAA;EACA,gBAAA;EACA,cAAA;EACA,eAAA;;AAlBN,KAAM,KAQJ,mBAME,GAME;EACE,mBAAA;EACA,iBAAA;EACA,kBAAA;;AAEA,KAzBF,KAQJ,mBAME,GAME,GAKG;EACC,aAAa,WAAb;EACA,eAAA;EACA,oBAAA;;AAGF,KA/BF,KAQJ,mBAME,GAME,GAWG,MAAM;EACL,SAAS,OAAT;EACA,cAAA;;AAGF,KApCF,KAQJ,mBAME,GAME,GAgBG,MAAM;EACL,SAAS,OAAT;EACA,cAAA;;AAGF,KAzCF,KAQJ,mBAME,GAME,GAqBG,UAAU;EACT,SAAS,OAAT;EACA,cAAA;;AAGF,KA9CF,KAQJ,mBAME,GAME,GA0BG,mBAAmB;EAClB,SAAS,OAAT;EACA,cAAA;;AAGF,KAnDF,KAQJ,mBAME,GAME,GA+BG,SAAS;EACR,SAAS,OAAT;EACA,cAAA;;AAOV;EACE,kBAAA;EACA,kBAAA;EACA,iBAAA;EACA,yBAAA;EACA,iBAAA;EACA,kBAAA;;AANF,8BAQE;EACE,kBAAA;EACA,YAAA;EACA,MAAA;EACA,gBAAA;EACA,eAAA;EACA,cAAA;;AAdJ,8BAiBE;EACE,gBAAA;EACA,aAAA;;AAnBJ,8BAsBE;EACE,gBAAA;;AAvBJ,8BAsBE,4BAGE;EACE,WAAA;EACA,yBAAA;;AA3BN,8BAsBE,4BAGE,MAIE;EACE,kBAAA;EACA,eAAA;EACA,iBAAA;EACA,YAAA;;AAjCR,8BAsBE,4BAGE,MAIE,SAME;EACE,kBAAA;EACA,kBAAA;EACA,SAAA;EACA,UAAA;EACA,cAAA;EACA,qCAAA;EACA,gDAA8C,oDAA+C,4BAA7F;EACA,gBAAA;EACA,WAAA;EACA,gBAAA;EACA,YAAA;EACA,aAAA;EACA,mBAAA;EACA,kBAAA;;AAjDV,8BAsBE,4BAGE,MAIE,SAME,cAgBE;EACE,gBAAA;;AAIJ,8BAlCN,4BAGE,MAIE,SA2BG,MAAO;EACN,mBAAA;;AAzDV,8BAsBE,4BAGE,MAoCE,MACE;EACE,UAAA;;AA/DV,8BAsBE,4BAGE,MA0CE;EACE,yBAAA;;AApER,8BAsBE,4BAGE,MA0CE,MAGE;EACE,qBAAA;EACA,UAAA;;AAxEV,8BAsBE,4BAGE,MA0CE,MAQE;EACE,mBAAA;EACA,UAAA;;AA7EV,8BAsBE,4BAGE,MA0CE,MAQE,GAIE;EACE,gBAAA;;AAhFZ,8BAsBE,4BAGE,MA0CE,MAQE,GAQE;EACE,iBAAA;EACA,gBAAA;;AAKF,8BApER,4BAGE,MA0CE,MAsBE,GACG,WACC;EACE,oBAAA;;AA5Fd,8BAoGE,iCACE;EACE,kBAAA;;AAtGN,8BAoGE,iCAKE;AAzGJ,8BAoGE,iCAME;EACE,gBAAA;EACA,UAAA;EACA,qBAAA;EACA,mBAAA;;AA9GN,8BAoGE,iCAKE,0BAOE,KAAI;AAhHV,8BAoGE,iCAME,0BAME,KAAI;EACF,oBAAA;;AAjHR,8BAoGE,iCAiBE;EACE,eAAA;EACA,iBAAA;;AAvHN,8BA2HE;EACE,mBAAA;;AA5HJ,8BA+HE;AA/HF,8BAgIE;EACE,mBAAA;;AAIJ,eACE;EACE,mBAAA;;AAFJ,eACE,SAGE;EACE,aAAA;EACA,mBAAA;EACA,8BAAA;;AAPN,eACE,SAGE,kBAKE,QACE,GACE;EACE,mBAAA;;AAEA,eAbV,SAGE,kBAKE,QACE,GACE,GAGG;EACC,mBAAA;;AAfd,eACE,SAGE,kBAKE,QACE,GACE,GAOE;EACE,qBAAA;EACA,iBAAA;;AAGE,eAtBd,SAGE,kBAKE,QACE,GACE,GAOE,EAIE,EACG;EACC,iBAAA;EACA,cAAA;;AAOV,eA/BN,SAGE,kBAKE,QAuBG;EACC,kBAAA;;AADF,eA/BN,SAGE,kBAKE,QAuBG,KAGC;EACE,kBAAA;;AAJJ,eA/BN,SAGE,kBAKE,QAuBG,KAGC,WAGE;EACE,cAAA;;AASd,wBAA0C;EACxC;IACE,cAAA;;EADF,8BAGE;IACE,kBAAA;IACA,aAAA;IACA,YAAA;;;;;;AAQN;EACE,eAAA;EACA,0CAAA;EACA,WAAA;EACA,YAAA;EACA,MAAA;EACA,kBAAA;;AANF,aAQE;EACE,QAAA;EACA,SAAA;EACA,kBAAA;EACA,eAAe,gBAAf;EACA,WAAW,gBAAX;;;;;AAOH,gBACC;EACE,uBAAA;;AAIA,gBADF,WACG;EACC,sBAAA;;AAGF,gBALF,WAKG,WAAW;EACV,cAAA;;AAXL,gBAeC;EACE,WAAA"}
assets/css/omgf-admin.less CHANGED
@@ -9,8 +9,8 @@
9
  *
10
  * @package : OMGF
11
  * @author : Daan van den Bergh
12
- * @copyright: (c) 2021 Daan van den Bergh
13
- * @url : https://daan.dev
14
  * * * * * * * * * * * * * * * * * * * */
15
 
16
  /**
@@ -60,89 +60,53 @@
60
 
61
  }
62
 
63
- .omgf-manual-optimization-mode,
64
- .omgf-automatic-optimization-mode {
65
- .pro-con-container {
66
- display: flex;
67
- justify-content: center;
68
-
69
- .pros, .cons {
70
- width: 50%;
71
 
72
- .pros-list,
73
- .cons-list {
74
- list-style: none;
75
- margin-left: 0;
76
- padding-left: 0;
77
 
78
- li {
79
- padding-left: 1.5em;
80
- text-indent: -2em;
81
- line-height: 18px;
82
- }
83
 
84
- li:before {
85
- font-family: 'dashicons';
86
- font-size: 18px;
87
- vertical-align: middle;
88
- margin-right: .5em;
89
- }
90
  }
91
 
92
- .pros-list {
93
- li:before {
94
- content: "\f147";
95
- color: #2ECC40;
96
- }
97
  }
98
 
99
- .cons-list {
100
- li:before {
101
- content: "\f158";
102
- color: #FF4136;
103
- }
104
  }
105
- }
106
- }
107
 
108
- .status {
109
- padding-left: 0;
110
- line-height: 1;
111
-
112
- ul {
113
- margin-top: 5px;
114
- list-style: none;
115
- margin-left: 0;
116
- padding-left: 0;
117
-
118
- li {
119
- padding-left: 1.5em;
120
- text-indent: -2em;
121
- line-height: 18px;
122
-
123
- &:before {
124
- font-family: 'dashicons';
125
- font-size: 18px;
126
- vertical-align: middle;
127
- margin-right: .5em;
128
- }
129
-
130
- &.stale:before {
131
- content: "\f534";
132
- color: #FF851B;
133
- }
134
-
135
- &.found:before {
136
- content: "\f147";
137
- color: #2ECC40;
138
- }
139
 
140
- &.not-found:before {
141
- content: "\f158";
142
- color: #FF4136;
143
- }
144
  }
145
 
 
 
 
 
146
  }
147
  }
148
  }
@@ -181,6 +145,7 @@
181
  position: relative;
182
  font-size: 16px;
183
  line-height: 16px;
 
184
 
185
  .tooltip-text {
186
  visibility: hidden;
@@ -268,12 +233,6 @@
268
  font-size: 18px;
269
  font-weight: bold;
270
  }
271
-
272
- #omgf_manual_optimize_url {
273
- font-size: 18px;
274
- padding: 0 15px;
275
- margin-left: 10px;
276
- }
277
  }
278
 
279
  .omgf-optimize-fonts-tooltip {
9
  *
10
  * @package : OMGF
11
  * @author : Daan van den Bergh
12
+ * @copyright: © 2022 Daan van den Bergh
13
+ * @url : https://ffw.press
14
  * * * * * * * * * * * * * * * * * * * */
15
 
16
  /**
60
 
61
  }
62
 
63
+ .omgf-task-manager {
64
+ .task-manager-row {
65
+ padding-left: 0;
66
+ line-height: 1;
67
+ }
 
 
 
68
 
69
+ ul {
70
+ margin-top: 5px;
71
+ list-style: none;
72
+ margin-left: 0;
73
+ padding-left: 0;
74
 
75
+ li {
76
+ padding-left: 1.5em;
77
+ text-indent: -2em;
78
+ line-height: 1.5em;
 
79
 
80
+ &:before {
81
+ font-family: 'dashicons';
82
+ font-size: 16px;
83
+ vertical-align: -3px;
 
 
84
  }
85
 
86
+ &.stale:before {
87
+ content: "\f534";
88
+ color: #FF851B;
 
 
89
  }
90
 
91
+ &.found:before {
92
+ content: "\f15e";
93
+ color: #2ECC40;
 
 
94
  }
 
 
95
 
96
+ &.not-found:before {
97
+ content: "\f158";
98
+ color: #FF4136;
99
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
100
 
101
+ &.stale-cache-notice:before {
102
+ content: "\f348";
103
+ color: #0074D9;
 
104
  }
105
 
106
+ &.unloaded:before {
107
+ content: "\f460";
108
+ color: #0074D9;
109
+ }
110
  }
111
  }
112
  }
145
  position: relative;
146
  font-size: 16px;
147
  line-height: 16px;
148
+ height: 12px;
149
 
150
  .tooltip-text {
151
  visibility: hidden;
233
  font-size: 18px;
234
  font-weight: bold;
235
  }
 
 
 
 
 
 
236
  }
237
 
238
  .omgf-optimize-fonts-tooltip {
assets/css/omgf-admin.min.css CHANGED
@@ -1 +1 @@
1
- .omgf .button-cancel{color:#a00;text-decoration:none;border-color:transparent;box-shadow:none;background:0 0;border-radius:3px;white-space:nowrap;padding:1px 10px!important}.omgf .button-cancel:hover{cursor:pointer;background:#d54e21;color:#fff;border-color:#d54e21}.omgf-nav{padding:1em 0 1.5em}.omgf-nav a{cursor:pointer}.omgf-nav .dashicons-before:before{margin-right:.25em;line-height:1.15em}.omgf form{max-width:1350px}.omgf form .dashicons{line-height:15px}.omgf form .omgf-automatic-optimization-mode .pro-con-container,.omgf form .omgf-manual-optimization-mode .pro-con-container{display:flex;justify-content:center}.omgf form .omgf-automatic-optimization-mode .pro-con-container .cons,.omgf form .omgf-automatic-optimization-mode .pro-con-container .pros,.omgf form .omgf-manual-optimization-mode .pro-con-container .cons,.omgf form .omgf-manual-optimization-mode .pro-con-container .pros{width:50%}.omgf form .omgf-automatic-optimization-mode .pro-con-container .cons .cons-list,.omgf form .omgf-automatic-optimization-mode .pro-con-container .cons .pros-list,.omgf form .omgf-automatic-optimization-mode .pro-con-container .pros .cons-list,.omgf form .omgf-automatic-optimization-mode .pro-con-container .pros .pros-list,.omgf form .omgf-manual-optimization-mode .pro-con-container .cons .cons-list,.omgf form .omgf-manual-optimization-mode .pro-con-container .cons .pros-list,.omgf form .omgf-manual-optimization-mode .pro-con-container .pros .cons-list,.omgf form .omgf-manual-optimization-mode .pro-con-container .pros .pros-list{list-style:none;margin-left:0;padding-left:0}.omgf form .omgf-automatic-optimization-mode .pro-con-container .cons .cons-list li,.omgf form .omgf-automatic-optimization-mode .pro-con-container .cons .pros-list li,.omgf form .omgf-automatic-optimization-mode .pro-con-container .pros .cons-list li,.omgf form .omgf-automatic-optimization-mode .pro-con-container .pros .pros-list li,.omgf form .omgf-manual-optimization-mode .pro-con-container .cons .cons-list li,.omgf form .omgf-manual-optimization-mode .pro-con-container .cons .pros-list li,.omgf form .omgf-manual-optimization-mode .pro-con-container .pros .cons-list li,.omgf form .omgf-manual-optimization-mode .pro-con-container .pros .pros-list li{padding-left:1.5em;text-indent:-2em;line-height:18px}.omgf form .omgf-automatic-optimization-mode .pro-con-container .cons .cons-list li:before,.omgf form .omgf-automatic-optimization-mode .pro-con-container .cons .pros-list li:before,.omgf form .omgf-automatic-optimization-mode .pro-con-container .pros .cons-list li:before,.omgf form .omgf-automatic-optimization-mode .pro-con-container .pros .pros-list li:before,.omgf form .omgf-manual-optimization-mode .pro-con-container .cons .cons-list li:before,.omgf form .omgf-manual-optimization-mode .pro-con-container .cons .pros-list li:before,.omgf form .omgf-manual-optimization-mode .pro-con-container .pros .cons-list li:before,.omgf form .omgf-manual-optimization-mode .pro-con-container .pros .pros-list li:before{font-family:dashicons;font-size:18px;vertical-align:middle;margin-right:.5em}.omgf form .omgf-automatic-optimization-mode .pro-con-container .cons .pros-list li:before,.omgf form .omgf-automatic-optimization-mode .pro-con-container .pros .pros-list li:before,.omgf form .omgf-manual-optimization-mode .pro-con-container .cons .pros-list li:before,.omgf form .omgf-manual-optimization-mode .pro-con-container .pros .pros-list li:before{content:"\f147";color:#2ecc40}.omgf form .omgf-automatic-optimization-mode .pro-con-container .cons .cons-list li:before,.omgf form .omgf-automatic-optimization-mode .pro-con-container .pros .cons-list li:before,.omgf form .omgf-manual-optimization-mode .pro-con-container .cons .cons-list li:before,.omgf form .omgf-manual-optimization-mode .pro-con-container .pros .cons-list li:before{content:"\f158";color:#ff4136}.omgf form .omgf-automatic-optimization-mode .status,.omgf form .omgf-manual-optimization-mode .status{padding-left:0;line-height:1}.omgf form .omgf-automatic-optimization-mode .status ul,.omgf form .omgf-manual-optimization-mode .status ul{margin-top:5px;list-style:none;margin-left:0;padding-left:0}.omgf form .omgf-automatic-optimization-mode .status ul li,.omgf form .omgf-manual-optimization-mode .status ul li{padding-left:1.5em;text-indent:-2em;line-height:18px}.omgf form .omgf-automatic-optimization-mode .status ul li:before,.omgf form .omgf-manual-optimization-mode .status ul li:before{font-family:dashicons;font-size:18px;vertical-align:middle;margin-right:.5em}.omgf form .omgf-automatic-optimization-mode .status ul li.stale:before,.omgf form .omgf-manual-optimization-mode .status ul li.stale:before{content:"\f534";color:#ff851b}.omgf form .omgf-automatic-optimization-mode .status ul li.found:before,.omgf form .omgf-manual-optimization-mode .status ul li.found:before{content:"\f147";color:#2ecc40}.omgf form .omgf-automatic-optimization-mode .status ul li.not-found:before,.omgf form .omgf-manual-optimization-mode .status ul li.not-found:before{content:"\f158";color:#ff4136}.omgf-optimize-fonts-container{text-align:center;padding:25px 50px;max-width:1024px;margin:20px auto 0 220px;overflow:visible;position:relative}.omgf-optimize-fonts-container .option-title{position:absolute;left:-220px;top:0;font-weight:600;font-size:14px;color:#1d2327}.omgf-optimize-fonts-container h3{font-size:1.3em;margin-top:0}.omgf-optimize-fonts-container .omgf-optimize-fonts-manage{text-align:left}.omgf-optimize-fonts-container .omgf-optimize-fonts-manage table{width:100%;border-collapse:collapse}.omgf-optimize-fonts-container .omgf-optimize-fonts-manage table .tooltip{position:relative;font-size:16px;line-height:16px}.omgf-optimize-fonts-container .omgf-optimize-fonts-manage table .tooltip .tooltip-text{visibility:hidden;position:absolute;top:100%;left:100%;z-index:10000;background-color:rgba(0,0,0,.75);font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Oxygen-Sans,Ubuntu,Cantarell,"Helvetica Neue",sans-serif;font-size:.8em;color:#fff;line-height:1.5;width:250px;padding:10px;margin-left:-125px;border-radius:3px}.omgf-optimize-fonts-container .omgf-optimize-fonts-manage table .tooltip .tooltip-text .illustration{margin-top:10px}.omgf-optimize-fonts-container .omgf-optimize-fonts-manage table .tooltip:hover .tooltip-text{visibility:visible}.omgf-optimize-fonts-container .omgf-optimize-fonts-manage table thead th{width:13%}.omgf-optimize-fonts-container .omgf-optimize-fonts-manage table tbody{border:1px solid #ccd0d4}.omgf-optimize-fonts-container .omgf-optimize-fonts-manage table tbody th{padding:5px 0 0 10px;width:40%}.omgf-optimize-fonts-container .omgf-optimize-fonts-manage table tbody td{padding-bottom:5px;width:13%}.omgf-optimize-fonts-container .omgf-optimize-fonts-manage table tbody td .unload-mass-action{font-size:.9em}.omgf-optimize-fonts-container .omgf-optimize-fonts-manage table tbody td .family{padding:0 10px 0;font-weight:600}.omgf-optimize-fonts-container .omgf-optimize-fonts-manage table tbody tr:last-child td{padding-bottom:10px}.omgf-optimize-fonts-container .omgf-optimize-fonts-description .omgf-optimize-fonts-pros{margin-right:10px}.omgf-optimize-fonts-container .omgf-optimize-fonts-description .omgf-optimize-fonts-cons,.omgf-optimize-fonts-container .omgf-optimize-fonts-description .omgf-optimize-fonts-pros{text-align:left;width:48%;display:inline-block;vertical-align:top}.omgf-optimize-fonts-container .omgf-optimize-fonts-description .omgf-optimize-fonts-cons span:before,.omgf-optimize-fonts-container .omgf-optimize-fonts-description .omgf-optimize-fonts-pros span:before{vertical-align:-4px}.omgf-optimize-fonts-container .omgf-optimize-fonts-description label{font-size:18px;font-weight:700}.omgf-optimize-fonts-container .omgf-optimize-fonts-description #omgf_manual_optimize_url{font-size:18px;padding:0 15px;margin-left:10px}.omgf-optimize-fonts-container .omgf-optimize-fonts-tooltip{padding:0 15px 5px}.omgf-optimize-fonts-container p,.omgf-optimize-fonts-container ul{text-align:justify}#omgf-help-form .postbox{padding:0 15px 5px}#omgf-help-form .postbox .column-container{display:flex;flex-flow:row wrap;justify-content:space-between}#omgf-help-form .postbox .column-container .column ul li{margin-bottom:10px}#omgf-help-form .postbox .column-container .column ul li:last-child{margin-bottom:none}#omgf-help-form .postbox .column-container .column ul li a{text-decoration:none;line-height:1.45}#omgf-help-form .postbox .column-container .column ul li a i.dashicons{margin-right:5px;color:#646970}#omgf-help-form .postbox .column-container .column.last{margin-right:45px}#omgf-help-form .postbox .column-container .column.last .signature{text-align:center}#omgf-help-form .postbox .column-container .column.last .signature .dashicons-heart{color:#ff4136}@media only screen and (max-width:782px){.omgf-optimize-fonts-container{margin:20px 0}.omgf-optimize-fonts-container .option-title{position:relative;left:initial;top:initial}}.omgf-loading{position:fixed;background-color:rgba(255,255,255,.6);width:100%;height:100%;top:0;text-align:center}.omgf-loading .spinner{top:50%;left:50%;position:absolute;-ms-transform:translateX(-50%);transform:translateX(-50%)}#footer-thankyou a{vertical-align:-.65em}#footer-thankyou .dashicons.ffwp-heart{vertical-align:middle}#footer-thankyou .dashicons.ffwp-heart:before{color:#ff4136}#footer-thankyou .signature-image{width:96px}
1
+ .omgf .button-cancel{color:#a00;text-decoration:none;border-color:transparent;box-shadow:none;background:0 0;border-radius:3px;white-space:nowrap;padding:1px 10px!important}.omgf .button-cancel:hover{cursor:pointer;background:#d54e21;color:#fff;border-color:#d54e21}.omgf-nav{padding:1em 0 1.5em}.omgf-nav a{cursor:pointer}.omgf-nav .dashicons-before:before{margin-right:.25em;line-height:1.15em}.omgf form{max-width:1350px}.omgf form .dashicons{line-height:15px}.omgf form .omgf-task-manager .task-manager-row{padding-left:0;line-height:1}.omgf form .omgf-task-manager ul{margin-top:5px;list-style:none;margin-left:0;padding-left:0}.omgf form .omgf-task-manager ul li{padding-left:1.5em;text-indent:-2em;line-height:1.5em}.omgf form .omgf-task-manager ul li:before{font-family:dashicons;font-size:16px;vertical-align:-3px}.omgf form .omgf-task-manager ul li.stale:before{content:"\f534";color:#ff851b}.omgf form .omgf-task-manager ul li.found:before{content:"\f15e";color:#2ecc40}.omgf form .omgf-task-manager ul li.not-found:before{content:"\f158";color:#ff4136}.omgf form .omgf-task-manager ul li.stale-cache-notice:before{content:"\f348";color:#0074d9}.omgf form .omgf-task-manager ul li.unloaded:before{content:"\f460";color:#0074d9}.omgf-optimize-fonts-container{text-align:center;padding:25px 50px;max-width:1024px;margin:20px auto 0 220px;overflow:visible;position:relative}.omgf-optimize-fonts-container .option-title{position:absolute;left:-220px;top:0;font-weight:600;font-size:14px;color:#1d2327}.omgf-optimize-fonts-container h3{font-size:1.3em;margin-top:0}.omgf-optimize-fonts-container .omgf-optimize-fonts-manage{text-align:left}.omgf-optimize-fonts-container .omgf-optimize-fonts-manage table{width:100%;border-collapse:collapse}.omgf-optimize-fonts-container .omgf-optimize-fonts-manage table .tooltip{position:relative;font-size:16px;line-height:16px;height:12px}.omgf-optimize-fonts-container .omgf-optimize-fonts-manage table .tooltip .tooltip-text{visibility:hidden;position:absolute;top:100%;left:100%;z-index:10000;background-color:rgba(0,0,0,.75);font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Oxygen-Sans,Ubuntu,Cantarell,"Helvetica Neue",sans-serif;font-size:.8em;color:#fff;line-height:1.5;width:250px;padding:10px;margin-left:-125px;border-radius:3px}.omgf-optimize-fonts-container .omgf-optimize-fonts-manage table .tooltip .tooltip-text .illustration{margin-top:10px}.omgf-optimize-fonts-container .omgf-optimize-fonts-manage table .tooltip:hover .tooltip-text{visibility:visible}.omgf-optimize-fonts-container .omgf-optimize-fonts-manage table thead th{width:13%}.omgf-optimize-fonts-container .omgf-optimize-fonts-manage table tbody{border:1px solid #ccd0d4}.omgf-optimize-fonts-container .omgf-optimize-fonts-manage table tbody th{padding:5px 0 0 10px;width:40%}.omgf-optimize-fonts-container .omgf-optimize-fonts-manage table tbody td{padding-bottom:5px;width:13%}.omgf-optimize-fonts-container .omgf-optimize-fonts-manage table tbody td .unload-mass-action{font-size:.9em}.omgf-optimize-fonts-container .omgf-optimize-fonts-manage table tbody td .family{padding:0 10px 0;font-weight:600}.omgf-optimize-fonts-container .omgf-optimize-fonts-manage table tbody tr:last-child td{padding-bottom:10px}.omgf-optimize-fonts-container .omgf-optimize-fonts-description .omgf-optimize-fonts-pros{margin-right:10px}.omgf-optimize-fonts-container .omgf-optimize-fonts-description .omgf-optimize-fonts-cons,.omgf-optimize-fonts-container .omgf-optimize-fonts-description .omgf-optimize-fonts-pros{text-align:left;width:48%;display:inline-block;vertical-align:top}.omgf-optimize-fonts-container .omgf-optimize-fonts-description .omgf-optimize-fonts-cons span:before,.omgf-optimize-fonts-container .omgf-optimize-fonts-description .omgf-optimize-fonts-pros span:before{vertical-align:-4px}.omgf-optimize-fonts-container .omgf-optimize-fonts-description label{font-size:18px;font-weight:700}.omgf-optimize-fonts-container .omgf-optimize-fonts-tooltip{padding:0 15px 5px}.omgf-optimize-fonts-container p,.omgf-optimize-fonts-container ul{text-align:justify}#omgf-help-form .postbox{padding:0 15px 5px}#omgf-help-form .postbox .column-container{display:flex;flex-flow:row wrap;justify-content:space-between}#omgf-help-form .postbox .column-container .column ul li{margin-bottom:10px}#omgf-help-form .postbox .column-container .column ul li:last-child{margin-bottom:none}#omgf-help-form .postbox .column-container .column ul li a{text-decoration:none;line-height:1.45}#omgf-help-form .postbox .column-container .column ul li a i.dashicons{margin-right:5px;color:#646970}#omgf-help-form .postbox .column-container .column.last{margin-right:45px}#omgf-help-form .postbox .column-container .column.last .signature{text-align:center}#omgf-help-form .postbox .column-container .column.last .signature .dashicons-heart{color:#ff4136}@media only screen and (max-width:782px){.omgf-optimize-fonts-container{margin:20px 0}.omgf-optimize-fonts-container .option-title{position:relative;left:initial;top:initial}}.omgf-loading{position:fixed;background-color:rgba(255,255,255,.6);width:100%;height:100%;top:0;text-align:center}.omgf-loading .spinner{top:50%;left:50%;position:absolute;-ms-transform:translateX(-50%);transform:translateX(-50%)}#footer-thankyou a{vertical-align:-.65em}#footer-thankyou .dashicons.ffwp-heart{vertical-align:middle}#footer-thankyou .dashicons.ffwp-heart:before{color:#ff4136}#footer-thankyou .signature-image{width:96px}
assets/js/omgf-admin.js CHANGED
@@ -9,8 +9,8 @@
9
  *
10
  * @package : OMGF
11
  * @author : Daan van den Bergh
12
- * @copyright: (c) 2021 Daan van den Bergh
13
- * @url : https://daan.dev
14
  * * * * * * * * * * * * * * * * * * * */
15
 
16
  jQuery(document).ready(function ($) {
@@ -28,10 +28,6 @@ jQuery(document).ready(function ($) {
28
  */
29
  init: function () {
30
  // Settings
31
- $('input[name="omgf_optimization_mode"]').on('click', this.toggle_optimization_mode_content);
32
- $('input[name="omgf_optimization_mode"]').on('change', this.toggle_manual_optimization_mode_section);
33
- $('#omgf-save-optimize').on('click', function () { $('#omgf-optimize-settings-form #submit').click(); });
34
- $('#omgf-stale-cache').on('click', function () { $('#omgf-empty').click(); });
35
  $('.omgf-optimize-fonts-manage .unload').on('change', this.unload_stylesheets);
36
  $('.omgf-optimize-fonts-manage .unload, .omgf-optimize-fonts-manage .fallback-font-stack select').on('change', this.generate_cache_key);
37
  $('.omgf-optimize-fonts-manage .unload').on('change', this.toggle_preload);
@@ -40,8 +36,11 @@ jQuery(document).ready(function ($) {
40
  $('.omgf-optimize-fonts-manage .unload-all').on('click', this.unload_all);
41
  $('.omgf-optimize-fonts-manage .load-all').on('click', this.load_all);
42
 
43
- // Buttons
44
- $('.omgf-empty').on('click', this.empty_cache_directory);
 
 
 
45
  $('#omgf-optimize-settings-form').submit(this.show_loader_before_submit);
46
 
47
  // Ticker
@@ -67,27 +66,46 @@ jQuery(document).ready(function ($) {
67
  }
68
  },
69
 
70
- /**
71
- *
72
- */
73
- toggle_optimization_mode_content: function () {
74
- if (this.value == 'manual') {
75
- $('.omgf-optimize-fonts-manual').show();
76
- $('.omgf-optimize-fonts-automatic').hide();
77
- } else {
78
- $('.omgf-optimize-fonts-automatic').show();
79
- $('.omgf-optimize-fonts-manual').hide();
80
- }
81
- },
82
 
83
- toggle_manual_optimization_mode_section: function () {
84
- var section = $('.omgf-manual-optimization-mode');
 
 
 
 
 
 
 
 
 
 
 
 
 
 
85
 
86
- if (this.value == 'manual') {
87
- section.show();
88
- } else {
89
- section.hide();
90
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
91
  },
92
 
93
  /**
@@ -121,9 +139,14 @@ jQuery(document).ready(function ($) {
121
  /**
122
  * Generate a new cache key upon each unload change.
123
  */
124
- generate_cache_key: function () {
125
- var current_handle = $(this).data('handle'),
126
- cache_keys_input = $('#omgf_cache_keys'),
 
 
 
 
 
127
  cache_keys = cache_keys_input.val().split(','),
128
  checked = $('#' + current_handle + ' input.unload:checked').length,
129
  total = $('#' + current_handle + ' input.unload').length,
@@ -270,7 +293,7 @@ jQuery(document).ready(function ($) {
270
  type: 'POST',
271
  url: ajaxurl,
272
  data: {
273
- action: 'omgf_ajax_empty_dir',
274
  nonce: omgf_admin.nonce,
275
  section: omgf_admin.cache_section
276
  },
@@ -291,7 +314,7 @@ jQuery(document).ready(function ($) {
291
  *
292
  */
293
  show_loader: function () {
294
- $('#wpcontent').append('<div class="omgf-loading"><span class="spinner is-active"></span></div>');
295
  }
296
  };
297
 
9
  *
10
  * @package : OMGF
11
  * @author : Daan van den Bergh
12
+ * @copyright: © 2022 Daan van den Bergh
13
+ * @url : https://ffw.press
14
  * * * * * * * * * * * * * * * * * * * */
15
 
16
  jQuery(document).ready(function ($) {
28
  */
29
  init: function () {
30
  // Settings
 
 
 
 
31
  $('.omgf-optimize-fonts-manage .unload').on('change', this.unload_stylesheets);
32
  $('.omgf-optimize-fonts-manage .unload, .omgf-optimize-fonts-manage .fallback-font-stack select').on('change', this.generate_cache_key);
33
  $('.omgf-optimize-fonts-manage .unload').on('change', this.toggle_preload);
36
  $('.omgf-optimize-fonts-manage .unload-all').on('click', this.unload_all);
37
  $('.omgf-optimize-fonts-manage .load-all').on('click', this.load_all);
38
 
39
+ // Buttons (AJAX, etc.)
40
+ $('#omgf-save-optimize').on('click', function () { $('#omgf-optimize-settings-form #submit').click(); });
41
+ $('#omgf-remove-stylesheet').on('click', this.remove_stylesheet_from_db);
42
+ $('#omgf-cache-refresh').on('click', this.refresh_cache);
43
+ $('.omgf-empty, #omgf-cache-flush').on('click', this.empty_cache_directory);
44
  $('#omgf-optimize-settings-form').submit(this.show_loader_before_submit);
45
 
46
  // Ticker
66
  }
67
  },
68
 
69
+ remove_stylesheet_from_db: function () {
70
+ var handle = $(this).data('handle');
 
 
 
 
 
 
 
 
 
 
71
 
72
+ $.ajax({
73
+ type: 'POST',
74
+ url: ajaxurl,
75
+ data: {
76
+ action: 'omgf_remove_stylesheet_from_db',
77
+ handle: handle,
78
+ nonce: omgf_admin.nonce,
79
+ },
80
+ beforeSend: function () {
81
+ omgf_admin.show_loader();
82
+ },
83
+ complete: function () {
84
+ location.reload();
85
+ }
86
+ });
87
+ },
88
 
89
+ /**
90
+ * Changes the cache keys to force a refresh with the current settings.
91
+ */
92
+ refresh_cache: function () {
93
+ $.ajax({
94
+ type: 'POST',
95
+ url: ajaxurl,
96
+ data: {
97
+ action: 'omgf_refresh_cache',
98
+ nonce: omgf_admin.nonce,
99
+ },
100
+ beforeSend: function () {
101
+ $('.omgf-optimize-fonts-manage table tbody').each(function (key, elem) {
102
+ omgf_admin.generate_cache_key(elem);
103
+ });
104
+ },
105
+ complete: function () {
106
+ $('#submit').click();
107
+ }
108
+ });
109
  },
110
 
111
  /**
139
  /**
140
  * Generate a new cache key upon each unload change.
141
  */
142
+ generate_cache_key: function (element = null) {
143
+ if (element.target === undefined) {
144
+ var current_handle = $(element).attr('id');
145
+ } else {
146
+ var current_handle = $(this).data('handle');
147
+ }
148
+
149
+ var cache_keys_input = $('#omgf_cache_keys'),
150
  cache_keys = cache_keys_input.val().split(','),
151
  checked = $('#' + current_handle + ' input.unload:checked').length,
152
  total = $('#' + current_handle + ' input.unload').length,
293
  type: 'POST',
294
  url: ajaxurl,
295
  data: {
296
+ action: 'omgf_empty_dir',
297
  nonce: omgf_admin.nonce,
298
  section: omgf_admin.cache_section
299
  },
314
  *
315
  */
316
  show_loader: function () {
317
+ $('#wpwrap').append('<div class="omgf-loading"><span class="spinner is-active"></span></div>');
318
  }
319
  };
320
 
ffwp-autoload.php CHANGED
@@ -2,7 +2,7 @@
2
  /* * * * * * * * * * * * * * * * * * * * * *
3
  * @author : Daan van den Bergh
4
  * @url : https://ffw.press/wordpress-plugins/
5
- * @copyright: (c) 2021 Daan van den Bergh
6
  * @license : GPL2v2 or later
7
  * * * * * * * * * * * * * * * * * * * * * */
8
 
2
  /* * * * * * * * * * * * * * * * * * * * * *
3
  * @author : Daan van den Bergh
4
  * @url : https://ffw.press/wordpress-plugins/
5
+ * @copyright: © 2022 Daan van den Bergh
6
  * @license : GPL2v2 or later
7
  * * * * * * * * * * * * * * * * * * * * * */
8
 
host-webfonts-local.php CHANGED
@@ -4,7 +4,7 @@
4
  * Plugin Name: OMGF
5
  * Plugin URI: https://ffw.press/wordpress/omgf/
6
  * Description: Increase GDPR compliance, reduce DNS requests and leverage browser cache by automatically downloading Google Fonts to your server.
7
- * Version: 4.6.0
8
  * Author: Daan from FFW.Press
9
  * Author URI: https://ffw.press
10
  * License: GPL2v2 or later
@@ -19,8 +19,8 @@ defined('ABSPATH') || exit;
19
  define('OMGF_PLUGIN_DIR', plugin_dir_path(__FILE__));
20
  define('OMGF_PLUGIN_FILE', __FILE__);
21
  define('OMGF_PLUGIN_BASENAME', plugin_basename(OMGF_PLUGIN_FILE));
22
- define('OMGF_STATIC_VERSION', '4.6.0');
23
- define('OMGF_DB_VERSION', '4.5.1');
24
 
25
  /**
26
  * Takes care of loading classes on demand.
4
  * Plugin Name: OMGF
5
  * Plugin URI: https://ffw.press/wordpress/omgf/
6
  * Description: Increase GDPR compliance, reduce DNS requests and leverage browser cache by automatically downloading Google Fonts to your server.
7
+ * Version: 5.0.0
8
  * Author: Daan from FFW.Press
9
  * Author URI: https://ffw.press
10
  * License: GPL2v2 or later
19
  define('OMGF_PLUGIN_DIR', plugin_dir_path(__FILE__));
20
  define('OMGF_PLUGIN_FILE', __FILE__);
21
  define('OMGF_PLUGIN_BASENAME', plugin_basename(OMGF_PLUGIN_FILE));
22
+ define('OMGF_STATIC_VERSION', '5.0.0');
23
+ define('OMGF_DB_VERSION', '5.0.0');
24
 
25
  /**
26
  * Takes care of loading classes on demand.
includes/admin/class-notice.php CHANGED
@@ -10,8 +10,8 @@
10
  *
11
  * @package : OMGF
12
  * @author : Daan van den Bergh
13
- * @copyright: (c) 2021 Daan van den Bergh
14
- * @url : https://daan.dev
15
  * * * * * * * * * * * * * * * * * * * */
16
 
17
  defined('ABSPATH') || exit;
@@ -31,7 +31,7 @@ class OMGF_Admin_Notice
31
  * @param bool $json
32
  * @param int $code
33
  */
34
- public static function set_notice($message, $message_id = '', $die = true, $type = 'success', $code = 200, $screen_id = 'all')
35
  {
36
  self::$notices = get_transient(self::OMGF_ADMIN_NOTICE_TRANSIENT);
37
 
@@ -42,16 +42,6 @@ class OMGF_Admin_Notice
42
  self::$notices[$screen_id][$type][$message_id] = $message;
43
 
44
  set_transient(self::OMGF_ADMIN_NOTICE_TRANSIENT, self::$notices, self::OMGF_ADMIN_NOTICE_EXPIRATION);
45
-
46
- if ($die) {
47
- switch ($type) {
48
- case 'error':
49
- wp_send_json_error($message, $code);
50
- break;
51
- default:
52
- wp_send_json_success($message, $code);
53
- }
54
- }
55
  }
56
 
57
  /**
10
  *
11
  * @package : OMGF
12
  * @author : Daan van den Bergh
13
+ * @copyright: © 2022 Daan van den Bergh
14
+ * @url : https://ffw.press
15
  * * * * * * * * * * * * * * * * * * * */
16
 
17
  defined('ABSPATH') || exit;
31
  * @param bool $json
32
  * @param int $code
33
  */
34
+ public static function set_notice($message, $message_id = '', $type = 'success', $code = 200, $screen_id = 'all')
35
  {
36
  self::$notices = get_transient(self::OMGF_ADMIN_NOTICE_TRANSIENT);
37
 
42
  self::$notices[$screen_id][$type][$message_id] = $message;
43
 
44
  set_transient(self::OMGF_ADMIN_NOTICE_TRANSIENT, self::$notices, self::OMGF_ADMIN_NOTICE_EXPIRATION);
 
 
 
 
 
 
 
 
 
 
45
  }
46
 
47
  /**
includes/admin/class-optimize.php ADDED
@@ -0,0 +1,91 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ defined('ABSPATH') || exit;
3
+
4
+ /* * * * * * * * * * * * * * * * * * * * *
5
+ *
6
+ * ██████╗ ███╗ ███╗ ██████╗ ███████╗
7
+ * ██╔═══██╗████╗ ████║██╔════╝ ██╔════╝
8
+ * ██║ ██║██╔████╔██║██║ ███╗█████╗
9
+ * ██║ ██║██║╚██╔╝██║██║ ██║██╔══╝
10
+ * ╚██████╔╝██║ ╚═╝ ██║╚██████╔╝██║
11
+ * ╚═════╝ ╚═╝ ╚═╝ ╚═════╝ ╚═╝
12
+ *
13
+ * @package : OMGF
14
+ * @author : Daan van den Bergh
15
+ * @copyright: © 2022 Daan van den Bergh
16
+ * @url : https://ffw.press
17
+ * * * * * * * * * * * * * * * * * * * */
18
+
19
+ class OMGF_Admin_Optimize
20
+ {
21
+ /** @var string */
22
+ private $settings_page = '';
23
+
24
+ /** @var string */
25
+ private $settings_tab = '';
26
+
27
+ /** @var bool */
28
+ private $settings_updated = false;
29
+
30
+ /**
31
+ * OMGF_Optimize constructor.
32
+ */
33
+ public function __construct()
34
+ {
35
+ $this->settings_page = $_GET['page'] ?? '';
36
+ $this->settings_tab = $_GET['tab'] ?? OMGF_Admin_Settings::OMGF_SETTINGS_FIELD_OPTIMIZE;
37
+ $this->settings_updated = isset($_GET['settings-updated']);
38
+
39
+ $this->init();
40
+ }
41
+
42
+ /**
43
+ * Run either manual or auto mode after settings are updated.
44
+ *
45
+ * @return void
46
+ */
47
+ private function init()
48
+ {
49
+ if (OMGF_Admin_Settings::OMGF_ADMIN_PAGE != $this->settings_page) {
50
+ return;
51
+ }
52
+
53
+ if (OMGF_Admin_Settings::OMGF_SETTINGS_FIELD_OPTIMIZE != $this->settings_tab) {
54
+ return;
55
+ }
56
+
57
+ if (!$this->settings_updated) {
58
+ return;
59
+ }
60
+
61
+ add_filter('http_request_args', [$this, 'verify_ssl']);
62
+
63
+ $this->run();
64
+ }
65
+
66
+ /**
67
+ * If this site is non-SSL it makes no sense to verify its SSL certificates.
68
+ *
69
+ * Settings sslverify to false will set CURLOPT_SSL_VERIFYPEER and CURLOPT_SSL_VERIFYHOST
70
+ * to 0 further down the road.
71
+ *
72
+ * @param mixed $url
73
+ * @return array
74
+ */
75
+ public function verify_ssl($args)
76
+ {
77
+ $args['sslverify'] = strpos(home_url(), 'https:') !== false;
78
+
79
+ return $args;
80
+ }
81
+
82
+ /**
83
+ * Run Force mode.
84
+ *
85
+ * @return void
86
+ */
87
+ private function run()
88
+ {
89
+ new OMGF_Optimize_Run();
90
+ }
91
+ }
includes/admin/class-settings.php CHANGED
@@ -10,8 +10,8 @@
10
  *
11
  * @package : OMGF
12
  * @author : Daan van den Bergh
13
- * @copyright: (c) 2021 Daan van den Bergh
14
- * @url : https://daan.dev
15
  * * * * * * * * * * * * * * * * * * * */
16
 
17
  defined('ABSPATH') || exit;
@@ -24,6 +24,7 @@ class OMGF_Admin_Settings extends OMGF_Admin
24
  * Transients
25
  */
26
  const OMGF_NEWS_REEL = 'omgf_news_reel';
 
27
  const OMGF_CURRENT_DB_VERSION = 'omgf_current_db_version';
28
 
29
  /**
@@ -35,16 +36,8 @@ class OMGF_Admin_Settings extends OMGF_Admin
35
  const OMGF_SETTINGS_FIELD_HELP = 'omgf-help';
36
 
37
  /**
38
- * Option Values
39
  */
40
- const OMGF_OPTIMIZATION_MODE = [
41
- 'manual' => 'Force (default)',
42
- 'auto' => 'Scan Posts/Pages (Pro)'
43
- ];
44
- const OMGF_FONT_PROCESSING_OPTIONS = [
45
- 'replace' => 'Replace (default)',
46
- 'remove' => 'Remove only'
47
- ];
48
  const OMGF_FONT_DISPLAY_OPTIONS = [
49
  'swap' => 'Swap (recommended)',
50
  'auto' => 'Auto',
@@ -131,8 +124,6 @@ class OMGF_Admin_Settings extends OMGF_Admin
131
  * Optimize Fonts
132
  */
133
  const OMGF_OPTIMIZE_SETTING_DISPLAY_OPTION = 'omgf_display_option';
134
- const OMGF_OPTIMIZE_SETTING_MANUAL_OPTIMIZE_URL = 'omgf_manual_optimize_url';
135
- const OMGF_OPTIMIZE_SETTING_OPTIMIZATION_MODE = 'omgf_optimization_mode';
136
  const OMGF_OPTIMIZE_SETTING_OPTIMIZED_FONTS = 'omgf_optimized_fonts';
137
  const OMGF_OPTIMIZE_SETTING_OPTIMIZE_EDIT_ROLES = 'omgf_optimize_edit_roles';
138
  const OMGF_OPTIMIZE_SETTING_PRELOAD_FONTS = 'omgf_preload_fonts';
@@ -140,16 +131,11 @@ class OMGF_Admin_Settings extends OMGF_Admin
140
  const OMGF_OPTIMIZE_SETTING_UNLOAD_STYLESHEETS = 'omgf_unload_stylesheets';
141
  const OMGF_OPTIMIZE_SETTING_CACHE_KEYS = 'omgf_cache_keys';
142
 
143
- /**
144
- * Detection Settings
145
- */
146
- const OMGF_DETECTION_SETTING_FONT_PROCESSING = 'omgf_font_processing';
147
-
148
  /**
149
  * Advanced Settings
150
  */
151
- const OMGF_ADV_SETTING_CACHE_PATH = 'omgf_cache_dir';
152
- const OMGF_ADV_SETTING_UNINSTALL = 'omgf_uninstall';
153
 
154
  /**
155
  * Miscellaneous
@@ -420,7 +406,6 @@ class OMGF_Admin_Settings extends OMGF_Admin
420
  ?>
421
  <?php if ($this->active_tab !== self::OMGF_SETTINGS_FIELD_HELP) : ?>
422
  <?php submit_button($this->submit_button_text, 'primary', 'submit', false); ?>
423
- <a id="omgf-empty" data-cache-section="/*" data-nonce="<?= wp_create_nonce(self::OMGF_ADMIN_PAGE); ?>" class="omgf-empty button-cancel"><?php _e('Empty Cache Directory', $this->plugin_text_domain); ?></a>
424
  <?php endif; ?>
425
  </form>
426
  <?php
@@ -494,6 +479,7 @@ class OMGF_Admin_Settings extends OMGF_Admin
494
  /**
495
  * Make sure the XML is properly encoded.
496
  */
 
497
  $xml = utf8_encode(html_entity_decode($xml));
498
  $xml = simplexml_load_string($xml);
499
 
@@ -507,7 +493,7 @@ class OMGF_Admin_Settings extends OMGF_Admin
507
  return $text;
508
  }
509
 
510
- $text = sprintf(__('Recently tagged <a target="_blank" href="%s"><strong>#OMGF</strong></a> on my blog:', $this->plugin_text_domain), 'https://daan.dev/tag/omgf') . ' ';
511
  $text .= '<span id="omgf-ticker-wrap">';
512
  $i = 0;
513
 
10
  *
11
  * @package : OMGF
12
  * @author : Daan van den Bergh
13
+ * @copyright: © 2022 Daan van den Bergh
14
+ * @url : https://ffw.press
15
  * * * * * * * * * * * * * * * * * * * */
16
 
17
  defined('ABSPATH') || exit;
24
  * Transients
25
  */
26
  const OMGF_NEWS_REEL = 'omgf_news_reel';
27
+ const OMGF_CACHE_IS_STALE = 'omgf_cache_is_stale';
28
  const OMGF_CURRENT_DB_VERSION = 'omgf_current_db_version';
29
 
30
  /**
36
  const OMGF_SETTINGS_FIELD_HELP = 'omgf-help';
37
 
38
  /**
39
+ * Option values for (multi)selects.
40
  */
 
 
 
 
 
 
 
 
41
  const OMGF_FONT_DISPLAY_OPTIONS = [
42
  'swap' => 'Swap (recommended)',
43
  'auto' => 'Auto',
124
  * Optimize Fonts
125
  */
126
  const OMGF_OPTIMIZE_SETTING_DISPLAY_OPTION = 'omgf_display_option';
 
 
127
  const OMGF_OPTIMIZE_SETTING_OPTIMIZED_FONTS = 'omgf_optimized_fonts';
128
  const OMGF_OPTIMIZE_SETTING_OPTIMIZE_EDIT_ROLES = 'omgf_optimize_edit_roles';
129
  const OMGF_OPTIMIZE_SETTING_PRELOAD_FONTS = 'omgf_preload_fonts';
131
  const OMGF_OPTIMIZE_SETTING_UNLOAD_STYLESHEETS = 'omgf_unload_stylesheets';
132
  const OMGF_OPTIMIZE_SETTING_CACHE_KEYS = 'omgf_cache_keys';
133
 
 
 
 
 
 
134
  /**
135
  * Advanced Settings
136
  */
137
+ const OMGF_ADV_SETTING_CACHE_DIR = 'omgf_cache_dir';
138
+ const OMGF_ADV_SETTING_UNINSTALL = 'omgf_uninstall';
139
 
140
  /**
141
  * Miscellaneous
406
  ?>
407
  <?php if ($this->active_tab !== self::OMGF_SETTINGS_FIELD_HELP) : ?>
408
  <?php submit_button($this->submit_button_text, 'primary', 'submit', false); ?>
 
409
  <?php endif; ?>
410
  </form>
411
  <?php
479
  /**
480
  * Make sure the XML is properly encoded.
481
  */
482
+ libxml_use_internal_errors(true);
483
  $xml = utf8_encode(html_entity_decode($xml));
484
  $xml = simplexml_load_string($xml);
485
 
493
  return $text;
494
  }
495
 
496
+ $text = sprintf(__('Recently tagged <a target="_blank" href="%s"><strong>#OMGF</strong></a> on my blog:', $this->plugin_text_domain), 'https://ffw.press/blog/tag/omgf') . ' ';
497
  $text .= '<span id="omgf-ticker-wrap">';
498
  $i = 0;
499
 
includes/admin/settings/class-advanced.php CHANGED
@@ -10,8 +10,8 @@
10
  *
11
  * @package : OMGF
12
  * @author : Daan van den Bergh
13
- * @copyright: (c) 2021 Daan van den Bergh
14
- * @url : https://daan.dev
15
  * * * * * * * * * * * * * * * * * * * */
16
 
17
  defined('ABSPATH') || exit;
@@ -34,7 +34,6 @@ class OMGF_Admin_Settings_Advanced extends OMGF_Admin_Settings_Builder
34
 
35
  // Settings
36
  add_filter('omgf_advanced_settings_content', [$this, 'do_promo_amp_handling'], 40);
37
- add_filter('omgf_advanced_settings_content', [$this, 'do_promo_exclude_posts'], 50);
38
  add_filter('omgf_advanced_settings_content', [$this, 'do_cache_dir'], 70);
39
  add_filter('omgf_advanced_settings_content', [$this, 'do_promo_fonts_source_url'], 80);
40
  add_filter('omgf_advanced_settings_content', [$this, 'do_uninstall'], 110);
@@ -68,23 +67,6 @@ class OMGF_Admin_Settings_Advanced extends OMGF_Admin_Settings_Builder
68
  );
69
  }
70
 
71
- /**
72
- * Excluded Post/Page IDs (Pro)
73
- *
74
- * @return void
75
- */
76
- public function do_promo_exclude_posts()
77
- {
78
- $this->do_text(
79
- __('Excluded Post/Page IDs (Pro)', $this->plugin_text_domain),
80
- 'omgf_pro_excluded_ids',
81
- __('e.g. 1,2,5,21,443'),
82
- defined('OMGF_PRO_EXCLUDED_IDS') ? OMGF_PRO_EXCLUDED_IDS : '',
83
- __('A comma separated list of post/page IDs where OMGF Pro shouldn\'t run. Only works when Advanced Proccessing is enabled under Detection Settings.', $this->plugin_text_domain) . ' ' . $this->promo,
84
- true
85
- );
86
- }
87
-
88
  /**
89
  *
90
  */
@@ -92,9 +74,9 @@ class OMGF_Admin_Settings_Advanced extends OMGF_Admin_Settings_Builder
92
  {
93
  $this->do_text(
94
  __('Fonts Cache Directory', $this->plugin_text_domain),
95
- OMGF_Admin_Settings::OMGF_ADV_SETTING_CACHE_PATH,
96
  __('e.g. /uploads/omgf', $this->plugin_text_domain),
97
- OMGF_CACHE_PATH,
98
  __("The directory (inside <code>wp-content</code>) where font files should be stored. Give each site a unique value if you're using Multisite. Defaults to <code>/uploads/omgf</code>. After changing this setting, the directory will be created if it doesn't exist and existing files will be moved automatically.", $this->plugin_text_domain)
99
  );
100
  }
@@ -105,14 +87,14 @@ class OMGF_Admin_Settings_Advanced extends OMGF_Admin_Settings_Builder
105
  public function do_promo_fonts_source_url()
106
  {
107
  $this->do_text(
108
- __('Fonts Source URL (Pro)', $this->plugin_text_domain),
109
  'omgf_pro_source_url',
110
  __('e.g. https://cdn.mydomain.com/alternate/relative-path', $this->plugin_text_domain),
111
  defined('OMGF_PRO_SOURCE_URL') ? OMGF_PRO_SOURCE_URL : '',
112
  sprintf(
113
- __("Modify the <code>src</code> URL for each font file in the stylesheet. This can be anything, like an absolute URL (e.g. <code>%s</code>) to an alternate relative URL (e.g. <code>/renamed-wp-content-dir/alternate/path/to/font-files</code>). Make sure you include the full path to where OMGF's files are stored and/or served from. Defaults to <code>%s</code>.", $this->plugin_text_domain),
114
- str_replace(home_url(), 'https://your-cdn.com', WP_CONTENT_URL . OMGF_CACHE_PATH),
115
- WP_CONTENT_URL . OMGF_CACHE_PATH
116
  ) . ' ' . $this->promo,
117
  true
118
  );
10
  *
11
  * @package : OMGF
12
  * @author : Daan van den Bergh
13
+ * @copyright: © 2022 Daan van den Bergh
14
+ * @url : https://ffw.press
15
  * * * * * * * * * * * * * * * * * * * */
16
 
17
  defined('ABSPATH') || exit;
34
 
35
  // Settings
36
  add_filter('omgf_advanced_settings_content', [$this, 'do_promo_amp_handling'], 40);
 
37
  add_filter('omgf_advanced_settings_content', [$this, 'do_cache_dir'], 70);
38
  add_filter('omgf_advanced_settings_content', [$this, 'do_promo_fonts_source_url'], 80);
39
  add_filter('omgf_advanced_settings_content', [$this, 'do_uninstall'], 110);
67
  );
68
  }
69
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
70
  /**
71
  *
72
  */
74
  {
75
  $this->do_text(
76
  __('Fonts Cache Directory', $this->plugin_text_domain),
77
+ OMGF_Admin_Settings::OMGF_ADV_SETTING_CACHE_DIR,
78
  __('e.g. /uploads/omgf', $this->plugin_text_domain),
79
+ OMGF_CACHE_DIR,
80
  __("The directory (inside <code>wp-content</code>) where font files should be stored. Give each site a unique value if you're using Multisite. Defaults to <code>/uploads/omgf</code>. After changing this setting, the directory will be created if it doesn't exist and existing files will be moved automatically.", $this->plugin_text_domain)
81
  );
82
  }
87
  public function do_promo_fonts_source_url()
88
  {
89
  $this->do_text(
90
+ __('Modify Fonts Source URL (Pro)', $this->plugin_text_domain),
91
  'omgf_pro_source_url',
92
  __('e.g. https://cdn.mydomain.com/alternate/relative-path', $this->plugin_text_domain),
93
  defined('OMGF_PRO_SOURCE_URL') ? OMGF_PRO_SOURCE_URL : '',
94
  sprintf(
95
+ __("Modify the <code>src</code> for each font file in stylesheets generated by OMGF Pro. This can be anything; from an absolute URL pointing to your CDN (e.g. <code>%s</code>) to an alternate relative URL (e.g. <code>/renamed-wp-content-dir/alternate/path/to/font-files</code>) to work with <em>security thru obscurity</em> plugins. Enter the full path to OMGF's files. Defaults to <code>%s</code> (no trailing slash)", $this->plugin_text_domain),
96
+ str_replace(home_url(), 'https://your-cdn.com', WP_CONTENT_URL . OMGF_CACHE_DIR),
97
+ WP_CONTENT_URL . OMGF_CACHE_DIR
98
  ) . ' ' . $this->promo,
99
  true
100
  );
includes/admin/settings/class-builder.php CHANGED
@@ -10,8 +10,8 @@
10
  *
11
  * @package : OMGF
12
  * @author : Daan van den Bergh
13
- * @copyright: (c) 2021 Daan van den Bergh
14
- * @url : https://daan.dev
15
  * * * * * * * * * * * * * * * * * * * */
16
 
17
  defined('ABSPATH') || exit;
@@ -45,7 +45,7 @@ class OMGF_Admin_Settings_Builder
45
  public function do_promo()
46
  {
47
  if (apply_filters('apply_omgf_pro_promo', true)) {
48
- $this->promo = apply_filters('omgf_pro_promo', sprintf(__('<a href="%s" target="_blank">Upgrade to Pro</a> to enable this option.', $this->plugin_text_domain), OMGF_Admin_Settings::FFWP_WORDPRESS_PLUGINS_OMGF_PRO));
49
  }
50
  }
51
 
10
  *
11
  * @package : OMGF
12
  * @author : Daan van den Bergh
13
+ * @copyright: © 2022 Daan van den Bergh
14
+ * @url : https://ffw.press
15
  * * * * * * * * * * * * * * * * * * * */
16
 
17
  defined('ABSPATH') || exit;
45
  public function do_promo()
46
  {
47
  if (apply_filters('apply_omgf_pro_promo', true)) {
48
+ $this->promo = apply_filters('omgf_pro_promo', sprintf(__('<a href="%s" target="_blank">Upgrade to Pro</a> to unlock this option.', $this->plugin_text_domain), OMGF_Admin_Settings::FFWP_WORDPRESS_PLUGINS_OMGF_PRO));
49
  }
50
  }
51
 
includes/admin/settings/class-detection.php CHANGED
@@ -10,8 +10,8 @@
10
  *
11
  * @package : OMGF
12
  * @author : Daan van den Bergh
13
- * @copyright: (c) 2021 Daan van den Bergh
14
- * @url : https://daan.dev
15
  * * * * * * * * * * * * * * * * * * * */
16
 
17
  defined('ABSPATH') || exit;
@@ -30,11 +30,8 @@ class OMGF_Admin_Settings_Detection extends OMGF_Admin_Settings_Builder
30
  add_filter('omgf_detection_settings_content', [$this, 'do_before'], 20);
31
 
32
  // Settings
33
- add_filter('omgf_detection_settings_content', [$this, 'do_process_google_fonts'], 30);
34
- add_filter('omgf_detection_settings_content', [$this, 'do_promo_advanced_processing'], 40);
35
- add_filter('omgf_detection_settings_content', [$this, 'do_promo_safe_mode'], 50);
36
- add_filter('omgf_detection_settings_content', [$this, 'do_promo_fonts_processing'], 60);
37
- add_filter('omgf_detection_settings_content', [$this, 'do_promo_process_resource_hints'], 70);
38
 
39
  // Close
40
  add_filter('omgf_detection_settings_content', [$this, 'do_after'], 100);
@@ -47,7 +44,7 @@ class OMGF_Admin_Settings_Detection extends OMGF_Admin_Settings_Builder
47
  {
48
  ?>
49
  <p>
50
- <?= __('These settings affect OMGF\'s automatic detection mechanism and how it treats the Google Fonts your theme and plugins use. If you want to use OMGF to remove the Google Fonts your WordPress configuration currently uses, set <strong>Google Fonts Processing</strong> to Remove.', $this->plugin_text_domain); ?>
51
  </p>
52
  <?php
53
  }
@@ -55,14 +52,31 @@ class OMGF_Admin_Settings_Detection extends OMGF_Admin_Settings_Builder
55
  /**
56
  *
57
  */
58
- public function do_promo_fonts_processing()
59
  {
60
  ?>
61
  <tr>
62
- <th scope="row"><?= __('Google Fonts Processing (Pro)', $this->plugin_text_domain); ?></th>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
63
  <td>
64
  <fieldset id="" class="scheme-list">
65
- <?php foreach ($this->fonts_processing_pro_options() as $name => $data) : ?>
66
  <?php
67
  $checked = defined(strtoupper($name)) ? constant(strtoupper($name)) : false;
68
  $disabled = apply_filters($name . '_setting_disabled', true) ? 'disabled' : '';
@@ -74,10 +88,10 @@ class OMGF_Admin_Settings_Detection extends OMGF_Admin_Settings_Builder
74
  <?php endforeach; ?>
75
  </fieldset>
76
  <p class="description">
77
- <?= $this->promo; ?>
78
  </p>
79
  <ul>
80
- <?php foreach ($this->fonts_processing_pro_options() as $name => $data) : ?>
81
  <li><strong><?= $data['label']; ?></strong>: <?= $data['description']; ?></li>
82
  <?php endforeach; ?>
83
  </ul>
@@ -89,91 +103,25 @@ class OMGF_Admin_Settings_Detection extends OMGF_Admin_Settings_Builder
89
  /**
90
  * @return array
91
  */
92
- private function fonts_processing_pro_options()
93
  {
94
  return [
95
- 'omgf_pro_process_stylesheets' => [
96
- 'label' => __('Process External Stylesheets', $this->plugin_text_domain),
97
- 'description' => __('Process stylesheets loaded from <code>fonts.googleapis.com</code> or <code>fonts.gstatic.com</code>.', $this->plugin_text_domain)
98
- ],
99
- 'omgf_pro_process_stylesheet_imports' => [
100
- 'label' => __('Process Stylesheet Imports', $this->plugin_text_domain),
101
- 'description' => __('Scan stylesheets loaded by your theme and plugins for <code>@import</code> statements loading Google Fonts and process them.', $this->plugin_text_domain)
102
- ],
103
- 'omgf_pro_process_stylesheet_font_faces' => [
104
- 'label' => __('Process Stylesheet Font Faces', $this->plugin_text_domain),
105
- 'description' => __('Scan stylesheets loaded by your theme and plugins for <code>@font-face</code> statements loading Google Fonts and process them.', $this->plugin_text_domain)
106
- ],
107
  'omgf_pro_process_inline_styles' => [
108
  'label' => __('Process Inline Styles', $this->plugin_text_domain),
109
  'description' => __('Process all inline <code>@font-face</code> and <code>@import</code> rules loading Google Fonts.', $this->plugin_text_domain)
110
  ],
 
 
 
 
111
  'omgf_pro_process_webfont_loader' => [
112
  'label' => __('Process Webfont Loader', $this->plugin_text_domain),
113
  'description' => __('Process <code>webfont.js</code> libraries and the corresponding configuration defining which Google Fonts to load.', $this->plugin_text_domain)
114
  ],
115
  'omgf_pro_process_early_access' => [
116
  'label' => __('Process Early Access', $this->plugin_text_domain),
117
- 'description' => __('Process stylesheets loaded from <code>fonts.googleapis.com/earlyaccess</code> or <code>fonts.gstatic.com/ea</code>.', $this->plugin_text_domain)
118
  ]
119
  ];
120
  }
121
-
122
- /**
123
- *
124
- */
125
- public function do_promo_advanced_processing()
126
- {
127
- $this->do_checkbox(
128
- __('Advanced Processing (Pro)', $this->plugin_text_domain),
129
- 'omgf_pro_advanced_processing',
130
- defined('OMGF_PRO_ADVANCED_PROCESSING') ? OMGF_PRO_ADVANCED_PROCESSING : false,
131
- __('By default, OMGF scans for Google Fonts which are registered/enqueued using the <code>wp_enqueue_scripts()</code> action in WordPress\' header (<code>wp_head()</code>). Enabling this option will process all Google Fonts throughout the entire document. This setting can be fine-tuned using the settings below.', $this->plugin_text_domain) . ' ' . $this->promo,
132
- true
133
- );
134
- }
135
-
136
- /**
137
- * Add option for Safe Mode (Pro)
138
- *
139
- * @return void
140
- */
141
- public function do_promo_safe_mode()
142
- {
143
- $this->do_checkbox(
144
- __('Safe Mode (Pro)', $this->plugin_text_domain),
145
- 'omgf_pro_safe_mode',
146
- defined('OMGF_PRO_SAFE_MODE') ? OMGF_PRO_SAFE_MODE : false,
147
- __('Enable Safe Mode if Advanced Processing (Pro) breaks styling of certain pages.', $this->plugin_text_domain) . ' ' . $this->promo,
148
- true
149
- );
150
- }
151
-
152
- /**
153
- * Add promo options for Process Resource Hints
154
- */
155
- public function do_promo_process_resource_hints()
156
- {
157
- $this->do_checkbox(
158
- __('Remove Resource Hints (Pro)', $this->plugin_text_domain),
159
- 'omgf_pro_process_resource_hints',
160
- defined('OMGF_PRO_PROCESS_RESOURCE_HINTS') ? OMGF_PRO_PROCESS_RESOURCE_HINTS : false,
161
- __('Remove all <code>link</code> elements with a <code>rel</code> attribute value of <code>dns-prefetch</code>, <code>preload</code> or <code>preconnect</code> pointing to <code>fonts.googleapis.com</code> or <code>fonts.gstatic.com</code>.', $this->plugin_text_domain) . ' ' . $this->promo,
162
- true
163
- );
164
- }
165
-
166
- /**
167
- *
168
- */
169
- public function do_process_google_fonts()
170
- {
171
- $this->do_select(
172
- __('Google Fonts Processing', $this->plugin_text_domain),
173
- OMGF_Admin_Settings::OMGF_DETECTION_SETTING_FONT_PROCESSING,
174
- OMGF_Admin_Settings::OMGF_FONT_PROCESSING_OPTIONS,
175
- OMGF_FONT_PROCESSING,
176
- sprintf(__("Choose whether OMGF should (find, download and) <strong>replace</strong> all Google Fonts, or just <strong>remove</strong> them. Choosing Remove will force WordPress to fallback to system fonts.", $this->plugin_text_domain), OMGF_Admin_Settings::FFWP_WORDPRESS_PLUGINS_OMGF_PRO)
177
- );
178
- }
179
  }
10
  *
11
  * @package : OMGF
12
  * @author : Daan van den Bergh
13
+ * @copyright: © 2022 Daan van den Bergh
14
+ * @url : https://ffw.press
15
  * * * * * * * * * * * * * * * * * * * */
16
 
17
  defined('ABSPATH') || exit;
30
  add_filter('omgf_detection_settings_content', [$this, 'do_before'], 20);
31
 
32
  // Settings
33
+ add_filter('omgf_detection_settings_content', [$this, 'google_fonts_processing'], 30);
34
+ add_filter('omgf_detection_settings_content', [$this, 'advanced_processing_promo'], 60);
 
 
 
35
 
36
  // Close
37
  add_filter('omgf_detection_settings_content', [$this, 'do_after'], 100);
44
  {
45
  ?>
46
  <p>
47
+ <?= __('These settings affect the detection mechanism and in which areas it searches (i.e. how deep it digs) to find Google Fonts. If you want to remove (instead of replace) the Google Fonts your WordPress configuration currently uses, set <strong>Google Fonts Processing</strong> to Remove.', $this->plugin_text_domain); ?>
48
  </p>
49
  <?php
50
  }
52
  /**
53
  *
54
  */
55
+ public function google_fonts_processing()
56
  {
57
  ?>
58
  <tr>
59
+ <th scope="row"><?= __('Google Fonts Processing', $this->plugin_text_domain); ?></th>
60
+ <td>
61
+ <p class="description">
62
+ <?= sprintf(__('By default, OMGF replaces Google Fonts stylesheets (e.g. <code>https://fonts.googleapis.com/css?family=Open+Sans</code>) with locally hosted copies. This behavior can be tweaked further using the <strong>Advanced Processing (Pro)</strong> option. To remove/unload Google Fonts, go to <em>Optimize Fonts</em> > <a href="%s"><em>Manage Optimized Fonts</em></a> and click <strong>Unload all</strong> next to the stylesheet handle you\'d like to remove.', $this->plugin_text_domain), admin_url('options-general.php?page=optimize-webfonts&tab=omgf-optimize-settings#omgf-manage-optimized-fonts')); ?>
63
+ </p>
64
+ </td>
65
+ </tr>
66
+ <?php
67
+ }
68
+
69
+ /**
70
+ *
71
+ */
72
+ public function advanced_processing_promo()
73
+ {
74
+ ?>
75
+ <tr>
76
+ <th scope="row"><?= __('Advanced Processing (Pro)', $this->plugin_text_domain); ?></th>
77
  <td>
78
  <fieldset id="" class="scheme-list">
79
+ <?php foreach ($this->advanced_processing_pro_options() as $name => $data) : ?>
80
  <?php
81
  $checked = defined(strtoupper($name)) ? constant(strtoupper($name)) : false;
82
  $disabled = apply_filters($name . '_setting_disabled', true) ? 'disabled' : '';
88
  <?php endforeach; ?>
89
  </fieldset>
90
  <p class="description">
91
+ <?= sprintf(__('By default, OMGF scans each page for mentions of URLs pointing to fonts.googleapis.com. If you need OMGF to "dig deeper", e.g. inside a theme or plugin\'s CSS stylesheets or (Web Font Loader) JS files, <a href="%s" target="_blank">enable these options</a> to increase its level of detection.', $this->plugin_text_domain), 'https://docs.ffw.press/article/21-omgf-pro-google-fonts-processing') . ' ' . $this->promo; ?>
92
  </p>
93
  <ul>
94
+ <?php foreach ($this->advanced_processing_pro_options() as $name => $data) : ?>
95
  <li><strong><?= $data['label']; ?></strong>: <?= $data['description']; ?></li>
96
  <?php endforeach; ?>
97
  </ul>
103
  /**
104
  * @return array
105
  */
106
+ private function advanced_processing_pro_options()
107
  {
108
  return [
 
 
 
 
 
 
 
 
 
 
 
 
109
  'omgf_pro_process_inline_styles' => [
110
  'label' => __('Process Inline Styles', $this->plugin_text_domain),
111
  'description' => __('Process all inline <code>@font-face</code> and <code>@import</code> rules loading Google Fonts.', $this->plugin_text_domain)
112
  ],
113
+ 'omgf_pro_process_local_stylesheets' => [
114
+ 'label' => __('Process Local Stylesheets', $this->plugin_text_domain),
115
+ 'description' => __('Scan stylesheets loaded by your theme and plugins for <code>@import</code> and <code>@font-face</code> statements loading Google Fonts and process them.', $this->plugin_text_domain)
116
+ ],
117
  'omgf_pro_process_webfont_loader' => [
118
  'label' => __('Process Webfont Loader', $this->plugin_text_domain),
119
  'description' => __('Process <code>webfont.js</code> libraries and the corresponding configuration defining which Google Fonts to load.', $this->plugin_text_domain)
120
  ],
121
  'omgf_pro_process_early_access' => [
122
  'label' => __('Process Early Access', $this->plugin_text_domain),
123
+ 'description' => __('Process Google Fonts loaded from <code>fonts.googleapis.com/earlyaccess</code> or <code>fonts.gstatic.com/ea</code>.', $this->plugin_text_domain)
124
  ]
125
  ];
126
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
127
  }
includes/admin/settings/class-help.php CHANGED
@@ -10,8 +10,8 @@
10
  *
11
  * @package : OMGF
12
  * @author : Daan van den Bergh
13
- * @copyright: (c) 2021 Daan van den Bergh
14
- * @url : https://daan.dev
15
  * * * * * * * * * * * * * * * * * * * */
16
 
17
  defined('ABSPATH') || exit;
10
  *
11
  * @package : OMGF
12
  * @author : Daan van den Bergh
13
+ * @copyright: © 2022 Daan van den Bergh
14
+ * @url : https://ffw.press
15
  * * * * * * * * * * * * * * * * * * * */
16
 
17
  defined('ABSPATH') || exit;
includes/admin/settings/class-optimize.php CHANGED
@@ -10,8 +10,8 @@
10
  *
11
  * @package : OMGF
12
  * @author : Daan van den Bergh
13
- * @copyright: (c) 2021 Daan van den Bergh
14
- * @url : https://daan.dev
15
  * * * * * * * * * * * * * * * * * * * */
16
 
17
  defined('ABSPATH') || exit;
@@ -35,18 +35,13 @@ class OMGF_Admin_Settings_Optimize extends OMGF_Admin_Settings_Builder
35
  add_filter('omgf_optimize_settings_content', [$this, 'do_title'], 10);
36
  add_filter('omgf_optimize_settings_content', [$this, 'do_description'], 11);
37
 
38
- add_filter('omgf_optimize_settings_content', [$this, 'do_before'], 20);
39
- add_filter('omgf_optimize_settings_content', [$this, 'do_optimization_mode'], 21);
40
- add_filter('omgf_optimize_settings_content', [$this, 'do_after'], 22);
41
-
42
- add_filter('omgf_optimize_settings_content', [$this, 'open_manual_optimization_mode'], 23);
43
  add_filter('omgf_optimize_settings_content', [$this, 'do_before'], 24);
44
- add_filter('omgf_optimize_settings_content', [$this, 'manual_optimization_status'], 25);
45
  add_filter('omgf_optimize_settings_content', [$this, 'do_after'], 26);
46
- add_filter('omgf_optimize_settings_content', [$this, 'close_manual_optimization_mode'], 27);
47
 
48
  add_filter('omgf_optimize_settings_content', [$this, 'do_before'], 30);
49
- add_filter('omgf_optimize_settings_content', [$this, 'do_promo_combine_requests'], 40);
50
  add_filter('omgf_optimize_settings_content', [$this, 'do_display_option'], 50);
51
  add_filter('omgf_optimize_settings_content', [$this, 'do_promo_force_font_display'], 60);
52
  add_filter('omgf_optimize_settings_content', [$this, 'do_promo_include_file_types'], 70);
@@ -69,7 +64,7 @@ class OMGF_Admin_Settings_Optimize extends OMGF_Admin_Settings_Builder
69
  {
70
  ?>
71
  <p>
72
- <?= __('These settings affect the fonts OMGF downloads and the stylesheet it generates. If you\'re simply looking to replace your Google Fonts for locally hosted copies, the default settings should suffice.', $this->plugin_text_domain); ?>
73
  </p>
74
  <p>
75
  <?= sprintf(__('To install additional Google Fonts, an add-on is required, which can be downloaded <a href="%s" target="blank">here</a>.', $this->plugin_text_domain), self::FFW_PRESS_OMGF_AF_URL); ?>
@@ -77,60 +72,35 @@ class OMGF_Admin_Settings_Optimize extends OMGF_Admin_Settings_Builder
77
  <?php
78
  }
79
 
80
- /**
81
- *
82
- * @return void
83
- */
84
- public function do_optimization_mode()
85
- {
86
- $this->do_radio(
87
- __('Optimization Mode', $this->plugin_text_domain),
88
- OMGF_Admin_Settings::OMGF_OPTIMIZATION_MODE,
89
- OMGF_Admin_Settings::OMGF_OPTIMIZE_SETTING_OPTIMIZATION_MODE,
90
- OMGF_OPTIMIZATION_MODE,
91
- __('<strong>Force</strong> will apply a single stylesheet to all of your posts/pages. <strong>Scan Posts/Pages</strong> will go through each page one by one and compile separate stylesheets for each different Google Fonts configuration.', $this->plugin_text_domain)
92
- );
93
- }
94
-
95
  /**
96
  * Opens the Force info screen container.
97
  *
98
  * @return void
99
  */
100
- public function open_manual_optimization_mode()
101
  {
102
  ?>
103
- <div class="omgf-manual-optimization-mode postbox" style="padding: 0 15px 5px; <?= OMGF_OPTIMIZATION_MODE == 'manual' ? '' : 'display: none;'; ?>">
104
- <h3><?= __('Optimization Mode: Force — Task Manager', $this->plugin_text_domain); ?></h3>
105
  <p class="description">
106
- <?= __('Are you using a regular theme (and a page builder) and are the same Google Fonts loading throughout all your posts/pages? Then <strong>Force</strong> is right for you.', $this->plugin_text_domain); ?>
107
  </p>
108
- <div class="pro-con-container">
109
- <div class="pros">
110
- <h4><?= __('Pros', $this->plugin_text_domain); ?></h4>
111
- <ul class="pros-list">
112
- <li><?= __('Fast. Immediate results.', $this->plugin_text_domain); ?></li>
113
- <li><?= __('One (or a few) stylesheets to manage.', $this->plugin_text_domain); ?></li>
114
- <li><?= __('Compatible with multilanguage plugins, e.g. WPML or Polylang.', $this->plugin_text_domain); ?></li>
115
- </ul>
116
- </div>
117
- <div class="cons">
118
- <h4><?= __('Cons', $this->plugin_text_domain); ?></h4>
119
- <ul class="cons-list">
120
- <li><?= __('Might miss a font, when using a page builder and a unique font is used on a few separate pages.', $this->plugin_text_domain); ?></li>
121
- </ul>
122
- </div>
123
- </div>
124
  <?php
125
  }
126
 
127
- public function manual_optimization_status()
 
 
 
 
 
128
  {
129
- $stylesheets = OMGF::optimized_fonts();
 
130
  ?>
131
  <tr valign="top">
132
- <th scope="row"><?= __('Stylesheet Status', $this->plugin_text_domain); ?></th>
133
- <td class="status">
134
  <?php if (!empty($stylesheets)) : ?>
135
  <ul>
136
  <?php foreach ($stylesheets as $handle => $contents) : ?>
@@ -141,21 +111,41 @@ class OMGF_Admin_Settings_Optimize extends OMGF_Admin_Settings_Builder
141
  $cache_key = $handle;
142
  }
143
 
144
- $downloaded = file_exists(OMGF_FONTS_DIR . "/$cache_key/$cache_key.css");
145
- $stale = function_exists('omgf_pro_init') && strpos($cache_key, 'pro-merged') === false;
146
  ?>
147
- <li class="<?= $stale ? 'stale' : ($downloaded ? 'found' : 'not-found'); ?>">
148
- <strong><?= $handle; ?></strong> <?php if (!$stale) : ?><em>(<?= sprintf(__('stored in %s', $this->plugin_text_domain), str_replace(ABSPATH, '', OMGF_FONTS_DIR . "/$cache_key")); ?>)</em><?php elseif ($stale) : ?><em>(<?= __('Stale cache item. <a id="omgf-stale-cache" href="#">Empty cache</a> and run optimization again.', $this->plugin_text_domain); ?>)</em><?php endif; ?>
149
  </li>
150
  <?php endforeach; ?>
 
 
 
151
  </ul>
152
  <?php else : ?>
153
  <p>
154
- <?= __('No stylesheets found. <a href="#" id="omgf-save-optimize">Run optimization</a>?', $this->plugin_text_domain); ?>
155
  </p>
156
  <?php endif; ?>
157
  </td>
158
  </tr>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
159
  <?php
160
  }
161
 
@@ -164,27 +154,13 @@ class OMGF_Admin_Settings_Optimize extends OMGF_Admin_Settings_Builder
164
  *
165
  * @return void
166
  */
167
- public function close_manual_optimization_mode()
168
  {
169
  ?>
170
  </div>
171
  <?php
172
  }
173
 
174
- /**
175
- *
176
- */
177
- public function do_promo_combine_requests()
178
- {
179
- $this->do_checkbox(
180
- __('Combine & Dedupe (Pro)', $this->plugin_text_domain),
181
- 'omgf_pro_combine_requests',
182
- defined('OMGF_PRO_COMBINE_REQUESTS') ? true : false,
183
- __('Combine and deduplicate multiple Google Fonts stylesheets into one stylesheet. This feature is always on in OMGF Pro.', $this->plugin_text_domain) . ' ' . $this->promo,
184
- true
185
- );
186
- }
187
-
188
  /**
189
  *
190
  */
@@ -253,7 +229,7 @@ class OMGF_Admin_Settings_Optimize extends OMGF_Admin_Settings_Builder
253
  public function do_optimize_fonts_container()
254
  {
255
  ?>
256
- <div class="omgf-optimize-fonts-container postbox">
257
  <?php
258
  }
259
 
@@ -273,8 +249,7 @@ class OMGF_Admin_Settings_Optimize extends OMGF_Admin_Settings_Builder
273
  <?php else : ?>
274
  <div class="omgf-optimize-fonts-description">
275
  <?php
276
- $this->do_manual_template();
277
- $this->do_automatic_template();
278
  ?>
279
  </div>
280
  <?php endif;
@@ -318,7 +293,7 @@ class OMGF_Admin_Settings_Optimize extends OMGF_Admin_Settings_Builder
318
  <?php foreach ($fonts as $font) : ?>
319
  <?php if (!is_object($font) || count((array) $font->variants) <= 0) continue; ?>
320
  <?php
321
- $aka = in_array($font->id, OMGF_API_Download::OMGF_RENAMED_GOOGLE_FONTS) ? array_search($font->id, OMGF_API_Download::OMGF_RENAMED_GOOGLE_FONTS) : '';
322
  ?>
323
  <tr class="font-family" data-id="<?= $handle . '-' . $font->id; ?>">
324
  <td colspan="5">
@@ -365,18 +340,13 @@ class OMGF_Admin_Settings_Optimize extends OMGF_Admin_Settings_Builder
365
  <div class="omgf-optimize-fonts-tooltip">
366
  <p>
367
  <span class="dashicons-before dashicons-info-outline"></span>
368
- <?php if (OMGF_OPTIMIZATION_MODE == 'manual') : ?>
369
- <em><?= sprintf(__("This list is populated with all Google Fonts captured and downloaded from <strong>%s</strong>. Optimizations will be applied on every page using these fonts. If you want to optimize additional Google Fonts from other pages, switch to <strong>Automatic (Pro)</strong> and visit the pages containing the stylesheets you'd like to optimize. This list will automatically be populated with the captured fonts.", $this->plugin_text_domain), OMGF_MANUAL_OPTIMIZE_URL); ?></em>
370
- <?php else : ?>
371
- <?php $no_cache_param = '?omgf_optimize=' . substr(md5(microtime()), rand(0, 26), 5); ?>
372
- <em><?= sprintf(__("This list is automatically populated with Google Fonts captured throughout your entire site. Optimizations will be applied on every page using these fonts. <strong>Automatic</strong> mode might not work when a Full Page Cache plugin is activated. If this list is not being populated with Google Fonts, you could try to visit your frontend and append the following parameter to the URL: <strong>%s</strong>", $this->plugin_text_domain), $no_cache_param); ?></em>
373
- <?php endif; ?>
374
  </p>
375
  </div>
376
  <input type="hidden" name="<?= OMGF_Admin_Settings::OMGF_OPTIMIZE_SETTING_OPTIMIZED_FONTS; ?>" value='<?= serialize($this->optimized_fonts); ?>' />
377
- <input type="hidden" name="<?= OMGF_Admin_Settings::OMGF_OPTIMIZE_SETTING_MANUAL_OPTIMIZE_URL; ?>" value="<?= OMGF_MANUAL_OPTIMIZE_URL; ?>" />
378
  <input id="<?= OMGF_Admin_Settings::OMGF_OPTIMIZE_SETTING_UNLOAD_STYLESHEETS; ?>" type="hidden" name="<?= OMGF_Admin_Settings::OMGF_OPTIMIZE_SETTING_UNLOAD_STYLESHEETS; ?>" value="<?= OMGF_UNLOAD_STYLESHEETS; ?>" />
379
  <input id="<?= OMGF_Admin_Settings::OMGF_OPTIMIZE_SETTING_CACHE_KEYS; ?>" type="hidden" name="<?= OMGF_Admin_Settings::OMGF_OPTIMIZE_SETTING_CACHE_KEYS; ?>" value="<?= implode(',', $cache_handles); ?>" />
 
380
  </div>
381
  <?php
382
  }
@@ -384,38 +354,14 @@ class OMGF_Admin_Settings_Optimize extends OMGF_Admin_Settings_Builder
384
  /**
385
  *
386
  */
387
- public function do_manual_template()
388
- {
389
- ?>
390
- <div class="omgf-optimize-fonts-manual" <?= OMGF_OPTIMIZATION_MODE == 'manual' ? '' : 'style="display: none;"'; ?>>
391
- <p>
392
- <?= __('Enter the URL of the post/page you\'d like to scan for Google Fonts. The detected and optimized stylesheets will be applied on all pages where they\'re used.', $this->plugin_text_domain); ?>
393
- </p>
394
- <label for="<?= OMGF_Admin_Settings::OMGF_OPTIMIZE_SETTING_MANUAL_OPTIMIZE_URL; ?>">
395
- <?= __('URL to Scan', $this->plugin_text_domain); ?>
396
- <input id="<?= OMGF_Admin_Settings::OMGF_OPTIMIZE_SETTING_MANUAL_OPTIMIZE_URL; ?>" type="text" name="<?= OMGF_Admin_Settings::OMGF_OPTIMIZE_SETTING_MANUAL_OPTIMIZE_URL; ?>" value="<?= OMGF_MANUAL_OPTIMIZE_URL; ?>" />
397
- </label>
398
- <div class="omgf-optimize-fonts-tooltip">
399
- <p>
400
- <span class="dashicons-before dashicons-info-outline"></span>
401
- <em><?= __('This section will be populated with all captured fonts, font styles and available options after saving changes.', $this->plugin_text_domain); ?></em>
402
- </p>
403
- </div>
404
- </div>
405
- <?php
406
- }
407
-
408
- /**
409
- *
410
- */
411
- public function do_automatic_template()
412
  {
413
  ?>
414
- <div class="omgf-optimize-fonts-automatic" <?= OMGF_OPTIMIZATION_MODE == 'auto' ? '' : 'style="display: none;"'; ?>>
415
  <div class="omgf-optimize-fonts-tooltip">
416
  <p>
417
  <span class="dashicons-before dashicons-info-outline"></span>
418
- <em><?= __("After saving your changes, this section will be populated with all captured fonts, font styles and available options as the cron task progresses.", $this->plugin_text_domain); ?></em>
419
  </p>
420
  </div>
421
  </div>
10
  *
11
  * @package : OMGF
12
  * @author : Daan van den Bergh
13
+ * @copyright: © 2022 Daan van den Bergh
14
+ * @url : https://ffw.press
15
  * * * * * * * * * * * * * * * * * * * */
16
 
17
  defined('ABSPATH') || exit;
35
  add_filter('omgf_optimize_settings_content', [$this, 'do_title'], 10);
36
  add_filter('omgf_optimize_settings_content', [$this, 'do_description'], 11);
37
 
38
+ add_filter('omgf_optimize_settings_content', [$this, 'open_task_manager'], 23);
 
 
 
 
39
  add_filter('omgf_optimize_settings_content', [$this, 'do_before'], 24);
40
+ add_filter('omgf_optimize_settings_content', [$this, 'task_manager_status'], 25);
41
  add_filter('omgf_optimize_settings_content', [$this, 'do_after'], 26);
42
+ add_filter('omgf_optimize_settings_content', [$this, 'close_task_manager'], 27);
43
 
44
  add_filter('omgf_optimize_settings_content', [$this, 'do_before'], 30);
 
45
  add_filter('omgf_optimize_settings_content', [$this, 'do_display_option'], 50);
46
  add_filter('omgf_optimize_settings_content', [$this, 'do_promo_force_font_display'], 60);
47
  add_filter('omgf_optimize_settings_content', [$this, 'do_promo_include_file_types'], 70);
64
  {
65
  ?>
66
  <p>
67
+ <?= __('These settings affect the downloaded files and generated stylesheet(s). If you\'re simply looking to replace your Google Fonts for locally hosted copies, the default settings should suffice.', $this->plugin_text_domain); ?>
68
  </p>
69
  <p>
70
  <?= sprintf(__('To install additional Google Fonts, an add-on is required, which can be downloaded <a href="%s" target="blank">here</a>.', $this->plugin_text_domain), self::FFW_PRESS_OMGF_AF_URL); ?>
72
  <?php
73
  }
74
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
75
  /**
76
  * Opens the Force info screen container.
77
  *
78
  * @return void
79
  */
80
+ public function open_task_manager()
81
  {
82
  ?>
83
+ <div class="omgf-task-manager postbox" style="padding: 0 15px 5px;">
84
+ <h3><?= __('Task Manager', $this->plugin_text_domain); ?></h3>
85
  <p class="description">
86
+ <?= __('A quick overview of the stylesheets (and their status) currently in your cache folder.', $this->plugin_text_domain); ?>
87
  </p>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
88
  <?php
89
  }
90
 
91
+ /**
92
+ *
93
+ *
94
+ * @return void
95
+ */
96
+ public function task_manager_status()
97
  {
98
+ $stylesheets = OMGF::optimized_fonts();
99
+ $unloaded_stylesheets = OMGF::unloaded_stylesheets();
100
  ?>
101
  <tr valign="top">
102
+ <th scope="row"><?= __('Cache Status', $this->plugin_text_domain); ?></th>
103
+ <td class="task-manager-row">
104
  <?php if (!empty($stylesheets)) : ?>
105
  <ul>
106
  <?php foreach ($stylesheets as $handle => $contents) : ?>
111
  $cache_key = $handle;
112
  }
113
 
114
+ $downloaded = file_exists(OMGF_CACHE_PATH . "/$cache_key/$cache_key.css");
115
+ $unloaded = in_array($handle, $unloaded_stylesheets);
116
  ?>
117
+ <li class="<?= OMGF_CACHE_IS_STALE ? 'stale' : ($unloaded ? 'unloaded' : ($downloaded ? 'found' : 'not-found')); ?>">
118
+ <strong><?= $handle; ?></strong> <em>(<?= sprintf(__('stored in %s', $this->plugin_text_domain), str_replace(ABSPATH, '', OMGF_CACHE_PATH . "/$cache_key")); ?>)</em> <?php if (!$unloaded) : ?><a href="<?php echo $downloaded ? "#$handle" : '#'; ?>" data-handle="<?php echo esc_attr($handle); ?>" id="<?php echo $downloaded ? 'omgf-manage-stylesheet' : 'omgf-remove-stylesheet'; ?>" title="<?php echo sprintf(__('Manage %s', $this->plugin_text_domain), $cache_key); ?>"><?php $downloaded ? _e('Configure', $this->plugin_text_domain) : _e('Remove', $this->plugin_text_domain); ?></a><?php endif; ?>
119
  </li>
120
  <?php endforeach; ?>
121
+ <?php if (OMGF_CACHE_IS_STALE) : ?>
122
+ <li class="stale-cache-notice"><em><?= __('The stylesheets in the cache do not reflect the current settings. Either <a href="#" id="omgf-cache-refresh">refresh</a> the cache (and maintain settings) or <a href="#" id="omgf-cache-flush">flush</a> it and start over.', $this->plugin_text_domain); ?></em></li>
123
+ <?php endif; ?>
124
  </ul>
125
  <?php else : ?>
126
  <p>
127
+ <?= __('No stylesheets found. <a href="#" id="omgf-save-optimize">Start optimization</a>?', $this->plugin_text_domain); ?>
128
  </p>
129
  <?php endif; ?>
130
  </td>
131
  </tr>
132
+ <tr>
133
+ <th scope="row"><?php _e('Legend', $this->plugin_text_domain); ?></th>
134
+ <td class="task-manager-row">
135
+ <ul>
136
+ <li class="found"> <?php _e('<strong>Found</strong>. Stylesheet exists on your file system.', $this->plugin_text_domain); ?></li>
137
+ <li class="unloaded"> <?php _e('<strong>Unloaded</strong>. Stylesheet exists, but is not loaded in the frontend.', $this->plugin_text_domain); ?></li>
138
+ <li class="stale"> <?php _e('<strong>Stale</strong>. Settings were changed and the stylesheet\'s content do not reflect those changes.', $this->plugin_text_domain); ?></li>
139
+ <li class="not-found"> <?php _e('<strong>Not Found</strong>. Stylesheet was detected once, but is missing now. You can safely remove it.', $this->plugin_text_domain); ?></li>
140
+ </ul>
141
+ </td>
142
+ </tr>
143
+ <tr>
144
+ <th scope="row"><?php _e('Flush Cache', $this->plugin_text_domain); ?></th>
145
+ <td class="task-manager-row">
146
+ <a id="omgf-empty" data-cache-section="/*" data-nonce="<?= wp_create_nonce(OMGF_Admin_Settings::OMGF_ADMIN_PAGE); ?>" class="omgf-empty button-cancel"><?php _e('Empty Cache Directory', $this->plugin_text_domain); ?></a>
147
+ </td>
148
+ </tr>
149
  <?php
150
  }
151
 
154
  *
155
  * @return void
156
  */
157
+ public function close_task_manager()
158
  {
159
  ?>
160
  </div>
161
  <?php
162
  }
163
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
164
  /**
165
  *
166
  */
229
  public function do_optimize_fonts_container()
230
  {
231
  ?>
232
+ <div id="omgf-manage-optimized-fonts" class="omgf-optimize-fonts-container postbox">
233
  <?php
234
  }
235
 
249
  <?php else : ?>
250
  <div class="omgf-optimize-fonts-description">
251
  <?php
252
+ $this->do_optimize_fonts_section();
 
253
  ?>
254
  </div>
255
  <?php endif;
293
  <?php foreach ($fonts as $font) : ?>
294
  <?php if (!is_object($font) || count((array) $font->variants) <= 0) continue; ?>
295
  <?php
296
+ $aka = in_array($font->id, OMGF_Optimize::OMGF_RENAMED_GOOGLE_FONTS) ? array_search($font->id, OMGF_Optimize::OMGF_RENAMED_GOOGLE_FONTS) : '';
297
  ?>
298
  <tr class="font-family" data-id="<?= $handle . '-' . $font->id; ?>">
299
  <td colspan="5">
340
  <div class="omgf-optimize-fonts-tooltip">
341
  <p>
342
  <span class="dashicons-before dashicons-info-outline"></span>
343
+ <em><?= sprintf(__("This list is populated with all Google Fonts stylesheets captured and downloaded throughout your site. It will grow organically if other Google Fonts stylesheets are discovered throughout your site.", $this->plugin_text_domain), get_site_url()); ?></em>
 
 
 
 
 
344
  </p>
345
  </div>
346
  <input type="hidden" name="<?= OMGF_Admin_Settings::OMGF_OPTIMIZE_SETTING_OPTIMIZED_FONTS; ?>" value='<?= serialize($this->optimized_fonts); ?>' />
 
347
  <input id="<?= OMGF_Admin_Settings::OMGF_OPTIMIZE_SETTING_UNLOAD_STYLESHEETS; ?>" type="hidden" name="<?= OMGF_Admin_Settings::OMGF_OPTIMIZE_SETTING_UNLOAD_STYLESHEETS; ?>" value="<?= OMGF_UNLOAD_STYLESHEETS; ?>" />
348
  <input id="<?= OMGF_Admin_Settings::OMGF_OPTIMIZE_SETTING_CACHE_KEYS; ?>" type="hidden" name="<?= OMGF_Admin_Settings::OMGF_OPTIMIZE_SETTING_CACHE_KEYS; ?>" value="<?= implode(',', $cache_handles); ?>" />
349
+ <?php echo apply_filters('omgf_optimize_fonts_hidden_fields', ''); ?>
350
  </div>
351
  <?php
352
  }
354
  /**
355
  *
356
  */
357
+ public function do_optimize_fonts_section()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
358
  {
359
  ?>
360
+ <div class="omgf-optimize-fonts">
361
  <div class="omgf-optimize-fonts-tooltip">
362
  <p>
363
  <span class="dashicons-before dashicons-info-outline"></span>
364
+ <em><?= sprintf(__('After clicking <strong>Save & Optimize</strong>, this section will be populated with any Google Fonts (along with requested styles and available options) requested on <code>%s</code>. The list will grow organically if other Google Fonts stylesheets are discovered throughout your site.', $this->plugin_text_domain), get_site_url()); ?></em>
365
  </p>
366
  </div>
367
  </div>
includes/api/class-download.php DELETED
@@ -1,491 +0,0 @@
1
- <?php
2
- /* * * * * * * * * * * * * * * * * * * * *
3
- *
4
- * ██████╗ ███╗ ███╗ ██████╗ ███████╗
5
- * ██╔═══██╗████╗ ████║██╔════╝ ██╔════╝
6
- * ██║ ██║██╔████╔██║██║ ███╗█████╗
7
- * ██║ ██║██║╚██╔╝██║██║ ██║██╔══╝
8
- * ╚██████╔╝██║ ╚═╝ ██║╚██████╔╝██║
9
- * ╚═════╝ ╚═╝ ╚═╝ ╚═════╝ ╚═╝
10
- *
11
- * @package : OMGF
12
- * @author : Daan van den Bergh
13
- * @copyright: (c) 2021 Daan van den Bergh
14
- * @url : https://daan.dev
15
- * * * * * * * * * * * * * * * * * * * */
16
-
17
- defined('ABSPATH') || exit;
18
-
19
- class OMGF_API_Download extends WP_REST_Controller
20
- {
21
- const OMGF_GOOGLE_FONTS_API_URL = 'https://google-webfonts-helper.herokuapp.com/api/fonts/';
22
- const OMGF_GOOGLE_FONTS_API_FALLBACK = 'https://omgf-google-fonts-api.herokuapp.com/api/fonts/';
23
- const OMGF_USE_FALLBACK_API_TRANSIENT = 'omgf_use_fallback_api';
24
-
25
- /**
26
- * If a font changed names recently, this array will map the old name (key) to the new name (value).
27
- *
28
- * The key of an element should be dashed (no spaces) if necessary, e.g. open-sans.
29
- */
30
- const OMGF_RENAMED_GOOGLE_FONTS = [
31
- 'ek-mukta' => 'mukta',
32
- 'muli' => 'mulish'
33
- ];
34
-
35
- /** @var string */
36
- private $plugin_text_domain = 'host-webfonts-local';
37
-
38
- /** @var array */
39
- private $endpoints = ['css', 'css2'];
40
-
41
- /** @var string */
42
- protected $namespace = 'omgf/v1';
43
-
44
- /** @var string */
45
- protected $rest_base = '/download/';
46
-
47
- /** @var string */
48
- private $handle = '';
49
-
50
- /** @var string */
51
- private $path = '';
52
-
53
- /**
54
- * @return void
55
- */
56
- public function register_routes()
57
- {
58
- foreach ($this->endpoints as $endpoint) {
59
- register_rest_route(
60
- $this->namespace,
61
- '/' . $this->rest_base . $endpoint,
62
- [
63
- [
64
- 'methods' => 'GET',
65
- 'callback' => [$this, 'process'],
66
- 'permission_callback' => [$this, 'permissions_check']
67
- ],
68
- 'schema' => null,
69
- ]
70
- );
71
- }
72
- }
73
-
74
- /**
75
- * Prevent CSRF.
76
- *
77
- * @since v4.5.4
78
- *
79
- * @return bool
80
- */
81
- public function permissions_check()
82
- {
83
- if (!isset($_REQUEST['_wpnonce'])) {
84
- return false;
85
- }
86
-
87
- /**
88
- * This API should only be accessible to users with manage_options capabilities.
89
- *
90
- * @since v4.5.13
91
- */
92
- return current_user_can('manage_options') && wp_verify_nonce($_REQUEST['_wpnonce'], 'wp_rest') > 0;
93
- }
94
-
95
- /**
96
- * @param WP_REST_Request $request
97
- */
98
- public function process($request)
99
- {
100
- $this->handle = sanitize_title_with_dashes($request->get_param('handle'));
101
- $original_handle = sanitize_title_with_dashes($request->get_param('original_handle'));
102
-
103
- if (!$this->handle || !$original_handle) {
104
- OMGF_Admin_Notice::set_notice(sprintf(__('OMGF couldn\'t find required stylesheet handle parameter while attempting to talk to API. Values sent were <code>%s</code> and <code>%s</code>.', $this->plugin_text_domain), $original_handle, $this->handle), 'omgf-api-handle-not-found', false, 'error', 406);
105
-
106
- return;
107
- }
108
-
109
- $this->path = WP_CONTENT_DIR . OMGF_CACHE_PATH . '/' . $this->handle;
110
- $font_families = explode('|', $request->get_param('family'));
111
- $query['subsets'] = $request->get_param('subset') ?? 'latin,latin-ext';
112
- $fonts = [];
113
-
114
- foreach ($font_families as $font_family) {
115
- if (empty($font_family)) {
116
- continue;
117
- }
118
-
119
- $fonts[] = $this->grab_font_family($font_family, $query);
120
- }
121
-
122
- // Filter out empty elements, i.e. failed requests.
123
- $fonts = array_filter($fonts);
124
-
125
- if (empty($fonts)) {
126
- return;
127
- }
128
-
129
- foreach ($fonts as $font_key => &$font) {
130
- $fonts_request = $this->build_fonts_request($font_families, $font);
131
-
132
- if (strpos($fonts_request, ':') != false) {
133
- list($family, $requested_variants) = explode(':', $fonts_request);
134
- } else {
135
- $family = $fonts_request;
136
- $requested_variants = '';
137
- }
138
-
139
- $requested_variants = $this->parse_requested_variants($requested_variants, $font);
140
-
141
- if ($unloaded_fonts = OMGF::unloaded_fonts()) {
142
- $font_id = $font->id;
143
-
144
- // Now we're sure we got 'em all. We can safely dequeue those we don't want.
145
- if (isset($unloaded_fonts[$original_handle][$font_id])) {
146
- $requested_variants = $this->dequeue_unloaded_variants($requested_variants, $unloaded_fonts[$original_handle], $font->id);
147
- $fonts_request = $family . ':' . implode(',', $requested_variants);
148
- }
149
- }
150
-
151
- $font->variants = $this->process_unload_queue($font->id, $font->variants, $fonts_request, $original_handle);
152
- }
153
-
154
- /**
155
- * Which file types should we download and include in the stylesheet?
156
- *
157
- * @since v4.5
158
- */
159
- $file_types = apply_filters('omgf_include_file_types', ['woff2', 'woff', 'eot', 'ttf', 'svg']);
160
-
161
- foreach ($fonts as &$font) {
162
- $font_id = $font->id;
163
-
164
- /**
165
- * Sanitize font family, because it may contain spaces.
166
- *
167
- * @since v4.5.6
168
- */
169
- $font->family = rawurlencode($font->family);
170
-
171
- foreach ($font->variants as &$variant) {
172
- $filename = strtolower($font_id . '-' . $variant->fontStyle . '-' . $variant->fontWeight);
173
-
174
- /**
175
- * Encode font family, because it may contain spaces.
176
- *
177
- * @since v4.5.6
178
- */
179
- $variant->fontFamily = rawurlencode($variant->fontFamily);
180
-
181
- foreach ($file_types as $file_type) {
182
- if (isset($variant->$file_type)) {
183
- $variant->$file_type = OMGF::download($variant->$file_type, $filename, $file_type, $this->path);
184
- }
185
- }
186
- }
187
- }
188
-
189
- $local_file = $this->path . '/' . $this->handle . '.css';
190
-
191
- /**
192
- * If this $stylesheet doesn't exist yet, let's generate it.
193
- *
194
- * If any modifications are done, e.g. unloads, the cache key ($handle) changes. Therefore it makes no sense to
195
- * continue after this point if $local_file already exists.
196
- *
197
- * @since v4.5.9
198
- */
199
- if (file_exists($local_file)) {
200
- return;
201
- }
202
-
203
- $stylesheet = OMGF::generate_stylesheet($fonts, $original_handle);
204
-
205
- file_put_contents($local_file, $stylesheet);
206
-
207
- $current_stylesheet = [$original_handle => $fonts];
208
-
209
- /**
210
- * $current_stylesheet is added to temporary cache layer, if it isn't present in database.
211
- *
212
- * @since v4.5.7
213
- */
214
- $optimized_fonts = OMGF::optimized_fonts($current_stylesheet);
215
-
216
- /**
217
- * When unload is used, this takes care of rewriting the font style URLs in the database.
218
- *
219
- * @since v4.5.7
220
- */
221
- $optimized_fonts = $this->rewrite_variants($optimized_fonts, $current_stylesheet);
222
-
223
- update_option(OMGF_Admin_Settings::OMGF_OPTIMIZE_SETTING_OPTIMIZED_FONTS, $optimized_fonts);
224
- }
225
-
226
- /**
227
- * @param $variants
228
- * @param $unloaded_fonts
229
- * @param $font_id
230
- *
231
- * @return array
232
- */
233
- private function dequeue_unloaded_variants($variants, $unloaded_fonts, $font_id)
234
- {
235
- return array_filter(
236
- $variants,
237
- function ($value) use ($unloaded_fonts, $font_id) {
238
- if ($value == '400') {
239
- // Sometimes the font is defined as 'regular', so we need to check both.
240
- return !in_array('regular', $unloaded_fonts[$font_id]) && !in_array($value, $unloaded_fonts[$font_id]);
241
- }
242
-
243
- if ($value == '400italic') {
244
- // Sometimes the font is defined as 'italic', so we need to check both.
245
- return !in_array('italic', $unloaded_fonts[$font_id]) && !in_array($value, $unloaded_fonts[$font_id]);
246
- }
247
-
248
- return !in_array($value, $unloaded_fonts[$font_id]);
249
- }
250
- );
251
- }
252
-
253
- /**
254
- * @param $font_family
255
- * @param $url
256
- * @param $query
257
- *
258
- * @return mixed|void
259
- */
260
- private function grab_font_family($font_family, $query)
261
- {
262
- $url = $this->get_working_service_url();
263
- list($family) = explode(':', $font_family);
264
-
265
- /**
266
- * Replace multiple spaces or plus signs (or a combination of, with a single dash)
267
- *
268
- * @since v4.5.10
269
- */
270
- $family = strtolower(preg_replace("/[\s\+]+/", '-', $family));
271
-
272
- /**
273
- * Add fonts to the request's $_GET 'family' parameter. Then pass an array to 'omgf_alternate_fonts'
274
- * filter. Then pass an alternate API url to the 'omgf_alternate_api_url' filter to fetch fonts from
275
- * an alternate API.
276
- */
277
- $alternate_fonts = apply_filters('omgf_alternate_fonts', []);
278
-
279
- if (in_array($family, array_keys($alternate_fonts))) {
280
- $url = apply_filters('omgf_alternate_api_url', $url, $family);
281
- unset($query);
282
- }
283
-
284
- $query_string = '';
285
-
286
- if (isset($query)) {
287
- $query_string = '?' . http_build_query($query);
288
- }
289
-
290
- /**
291
- * If a font changed names recently, map their old name to the new name, before triggering the API request.
292
- */
293
- if (in_array($family, array_keys(self::OMGF_RENAMED_GOOGLE_FONTS))) {
294
- $family = self::OMGF_RENAMED_GOOGLE_FONTS[$family];
295
- }
296
-
297
- $response = wp_remote_get(
298
- sprintf($url . '%s', $family) . $query_string
299
- );
300
-
301
- if (is_wp_error($response)) {
302
- OMGF_Admin_Notice::set_notice(sprintf(__('OMGF encountered an error while trying to fetch fonts: %s', $this->plugin_text_domain), $response->get_error_message()), $response->get_error_code(), true, 'error', 500);
303
- }
304
-
305
- $response_code = wp_remote_retrieve_response_code($response);
306
-
307
- if ($response_code != 200) {
308
- $font_family = str_replace('-', ' ', $family);
309
- $error_body = wp_remote_retrieve_body($response);
310
- $error_message = wp_remote_retrieve_response_message($response);
311
- $message = sprintf(__('OMGF couldn\'t find <strong>%s</strong>. The API returned the following error: %s.', $this->plugin_text_domain), ucwords($font_family), $error_message);
312
-
313
- OMGF_Admin_Notice::set_notice($message, 'omgf_api_error', false, 'error');
314
-
315
- if ($error_message == 'Service Unavailable') {
316
- $message = __('OMGF\'s Google Fonts API is currently unavailable. Try again later.', $this->plugin_text_domain);
317
-
318
- OMGF_Admin_Notice::set_notice($message, 'omgf_api_error', true, 'error', $response_code);
319
- }
320
-
321
- if ($error_body == 'Not found') {
322
- $message = sprintf(__('Please verify that %s is available for free at Google Fonts by doing <a href="%s" target="_blank">a manual search</a>. Maybe it\'s a Premium font?', $this->plugin_text_domain), ucwords($font_family), 'https://fonts.google.com/?query=' . str_replace('-', '+', $family));
323
-
324
- OMGF_Admin_Notice::set_notice($message, 'omgf_api_info_not_found', false, 'info');
325
- }
326
-
327
- if ($error_body == 'Internal Server Error') {
328
- $message = sprintf(__('Try using the Force Subsets option (available in OMGF Pro) to force loading %s in a subset in which it\'s actually available. Use the Language filter <a href="%s" target="_blank">here</a> to verify which subsets are available for %s.', $this->plugin_text_domain), ucwords($font_family), 'https://fonts.google.com/?query=' . str_replace('-', '+', $family), ucwords($font_family));
329
-
330
- OMGF_Admin_Notice::set_notice($message, 'omgf_api_info_internal_server_error', false, 'info');
331
- }
332
-
333
- return [];
334
- }
335
-
336
- return json_decode(wp_remote_retrieve_body($response));
337
- }
338
-
339
- /**
340
- * Because the regular Google Webfonts Helper API tends to go offline sometimes, this function allows us
341
- * to use fallback services.
342
- *
343
- * @return string Will return regular API url if fallback API url fails, too. Error handling later on will display a
344
- * proper message to the user.
345
- */
346
- private function get_working_service_url()
347
- {
348
- /**
349
- * If this transient returns true, then that means that the regular API has failed in the last 24 hours.
350
- */
351
- if (get_transient(self::OMGF_USE_FALLBACK_API_TRANSIENT)) {
352
- return self::OMGF_GOOGLE_FONTS_API_FALLBACK;
353
- }
354
-
355
- $url = self::OMGF_GOOGLE_FONTS_API_URL;
356
- $response = wp_remote_get($url);
357
-
358
- if (is_wp_error($response) || wp_remote_retrieve_response_code($response) != 200) {
359
- set_transient(self::OMGF_USE_FALLBACK_API_TRANSIENT, true, DAY_IN_SECONDS);
360
-
361
- $response = wp_remote_get(self::OMGF_GOOGLE_FONTS_API_FALLBACK);
362
-
363
- if (!is_wp_error($response) && wp_remote_retrieve_response_code($response) == 200) {
364
- $url = self::OMGF_GOOGLE_FONTS_API_FALLBACK;
365
- }
366
- }
367
-
368
- return $url;
369
- }
370
-
371
- /**
372
- * @param $font_families
373
- * @param $font
374
- *
375
- * @return mixed
376
- */
377
- private function build_fonts_request($font_families, $font)
378
- {
379
- $font_request = array_filter(
380
- $font_families,
381
- function ($value) use ($font) {
382
- if (isset($font->early_access)) {
383
- return strpos($value, strtolower(str_replace(' ', '', $font->family))) !== false;
384
- }
385
-
386
- return strpos($value, $font->family) !== false;
387
- }
388
- );
389
-
390
- return reset($font_request);
391
- }
392
-
393
- /**
394
- * @param $request
395
- * @param $font
396
- *
397
- * @return array
398
- */
399
- private function parse_requested_variants($request, $font)
400
- {
401
- $requested_variants = array_filter(explode(',', $request));
402
-
403
- /**
404
- * This means by default all fonts are requested, so we need to fill up the queue, before unloading the unwanted variants.
405
- */
406
- if (count($requested_variants) == 0) {
407
- foreach ($font->variants as $variant) {
408
- $requested_variants[] = $variant->id;
409
- }
410
- }
411
-
412
- return $requested_variants;
413
- }
414
-
415
- /**
416
- *
417
- * @param mixed $font_id
418
- * @param mixed $available
419
- * @param mixed $wanted
420
- * @param mixed $stylesheet_handle
421
- * @return mixed
422
- */
423
- private function process_unload_queue($font_id, $available, $wanted, $stylesheet_handle)
424
- {
425
- if (strpos($wanted, ':') !== false) {
426
- // We don't need the first variable.
427
- list(, $variants) = explode(':', $wanted);
428
- } else {
429
- $variants = '';
430
- }
431
-
432
- /**
433
- * Build array and filter out empty elements.
434
- */
435
- $variants = array_filter(explode(',', $variants));
436
-
437
- /**
438
- * If $variants is empty and this is the first run, i.e. there are no unloaded fonts (yet)
439
- * return all available variants.
440
- */
441
- if (empty($variants) && !isset(OMGF::unloaded_fonts()[$stylesheet_handle][$font_id])) {
442
- return $available;
443
- }
444
-
445
- return array_filter(
446
- $available,
447
- function ($font) use ($variants) {
448
- $id = $font->id;
449
-
450
- if ($id == 'regular' || $id == '400') {
451
- return in_array('400', $variants) || in_array('regular', $variants);
452
- }
453
-
454
- if ($id == 'italic') {
455
- return in_array('400italic', $variants) || in_array('italic', $variants);
456
- }
457
-
458
- return in_array($id, $variants);
459
- }
460
- );
461
- }
462
-
463
- /**
464
- * When unload is used, insert the cache key in the font URLs for the variants still in use.
465
- *
466
- * @param array $all_stylesheets Contains all font styles, loaded and unloaded.
467
- * @param array $current_stylesheet Contains just the loaded font styles of current stylesheet.
468
- *
469
- * @return mixed
470
- */
471
- private function rewrite_variants($all_stylesheets, $current_stylesheet)
472
- {
473
- foreach ($all_stylesheets as $stylesheet => &$fonts) {
474
- foreach ($fonts as $index => &$font) {
475
- if (empty((array) $font->variants)) {
476
- continue;
477
- }
478
-
479
- foreach ($font->variants as $variant_index => &$variant) {
480
- $replace_variant = $current_stylesheet[$stylesheet][$index]->variants[$variant_index] ?? (object) [];
481
-
482
- if (!empty((array) $replace_variant)) {
483
- $variant = $replace_variant;
484
- }
485
- }
486
- }
487
- }
488
-
489
- return $all_stylesheets;
490
- }
491
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
includes/class-admin.php CHANGED
@@ -12,8 +12,8 @@ defined('ABSPATH') || exit;
12
  *
13
  * @package : OMGF
14
  * @author : Daan van den Bergh
15
- * @copyright: (c) 2021 Daan van den Bergh
16
- * @url : https://daan.dev
17
  * * * * * * * * * * * * * * * * * * * */
18
 
19
  class OMGF_Admin
@@ -21,8 +21,8 @@ class OMGF_Admin
21
  const OMGF_ADMIN_JS_HANDLE = 'omgf-admin-js';
22
  const OMGF_ADMIN_CSS_HANDLE = 'omgf-admin-css';
23
 
24
- /** @var array $show_notice */
25
- private $show_notice = [];
26
 
27
  /** @var string $plugin_text_domain */
28
  private $plugin_text_domain = 'host-webfonts-local';
@@ -33,14 +33,12 @@ class OMGF_Admin
33
  public function __construct()
34
  {
35
  /**
36
- * Filterable list of options that require the cache to be emptied.
37
  */
38
- $this->show_notice = apply_filters(
39
- 'omgf_admin_options_show_notice',
40
  [
41
- OMGF_Admin_Settings::OMGF_OPTIMIZE_SETTING_OPTIMIZATION_MODE,
42
- OMGF_Admin_Settings::OMGF_OPTIMIZE_SETTING_DISPLAY_OPTION,
43
- OMGF_Admin_Settings::OMGF_ADV_SETTING_CACHE_PATH,
44
  ]
45
  );
46
 
@@ -53,8 +51,10 @@ class OMGF_Admin
53
  $this->do_help();
54
  $this->maybe_do_after_update_notice();
55
 
56
- // This used to fix a bug, but now it breaks stuff. Leave it here for the time being.
57
- // add_filter('pre_update_option_omgf_optimized_fonts', [$this, 'update_optimized_fonts'], 10, 2);
 
 
58
  add_filter('pre_update_option_omgf_cache_keys', [$this, 'clean_up_cache'], 10, 3);
59
  add_action('pre_update_option_omgf_cache_dir', [$this, 'validate_cache_dir'], 10, 2);
60
  add_filter('pre_update_option', [$this, 'settings_changed'], 10, 3);
@@ -120,7 +120,7 @@ class OMGF_Admin
120
  */
121
  private function maybe_do_after_update_notice()
122
  {
123
- if (version_compare(OMGF_CURRENT_DB_VERSION, OMGF_DB_VERSION, '<')) {
124
  OMGF_Admin_Notice::set_notice(
125
  sprintf(
126
  __('Thank you for updating OMGF to v%s! This version contains database changes. <a href="%s">Verify your settings</a> and make sure everything is as you left it or, <a href="%s">view the changelog</a> for details. ', $this->plugin_text_domain),
@@ -128,8 +128,7 @@ class OMGF_Admin
128
  admin_url(OMGF_Admin_Settings::OMGF_OPTIONS_GENERAL_PAGE_OPTIMIZE_WEBFONTS),
129
  admin_url(OMGF_Admin_Settings::OMGF_PLUGINS_INSTALL_CHANGELOG_SECTION)
130
  ),
131
- 'omgf-post-update',
132
- false
133
  );
134
 
135
  update_option(OMGF_Admin_Settings::OMGF_CURRENT_DB_VERSION, OMGF_DB_VERSION);
@@ -172,7 +171,7 @@ class OMGF_Admin
172
  $cache_keys = explode(',', $old_value);
173
 
174
  foreach ($cache_keys as $key) {
175
- $entries = array_filter((array) glob(OMGF_FONTS_DIR . "/*$key"));
176
 
177
  foreach ($entries as $entry) {
178
  OMGF::delete($entry);
@@ -202,7 +201,7 @@ class OMGF_Admin
202
  }
203
 
204
  if (!$mkdir) {
205
- OMGF_Admin_Notice::set_notice(sprintf(__('Something went wrong while trying to create OMGF\'s Cache Directory: %s. Setting wasn\'t updated.', $this->plugin_text_domain), $new_dir), 'omgf-create-cache-dir-failed', false, 'error');
206
 
207
  return $old_dir;
208
  }
@@ -210,7 +209,7 @@ class OMGF_Admin
210
  $real_path = realpath($allowed_path);
211
 
212
  if ($real_path != rtrim($allowed_path, '/')) {
213
- OMGF_Admin_Notice::set_notice(__('OMGF\'s Cache Directory wasn\'t changed. Attempted path traversal.', $this->plugin_text_domain), 'omgf-attempted-path-traversal', false, 'error');
214
 
215
  return $old_dir;
216
  }
@@ -230,23 +229,28 @@ class OMGF_Admin
230
  */
231
  public function settings_changed($value, $option_name, $old_value)
232
  {
233
- if (!in_array($option_name, $this->show_notice)) {
234
  return $value;
235
  }
236
 
237
- if ($value != $old_value) {
 
 
 
238
  global $wp_settings_errors;
239
 
240
  if (!empty($wp_settings_errors)) {
241
  $wp_settings_errors = [];
242
  }
243
 
 
 
244
  add_settings_error(
245
  'general',
246
- 'omgf_settings_changed',
247
  sprintf(
248
- __('Settings changed. <a href="#" data-cache-section="/*" data-nonce="%s" class="omgf-empty">Click here</a> to empty OMGF\'s cache.', $this->plugin_text_domain),
249
- wp_create_nonce(OMGF_Admin_Settings::OMGF_ADMIN_PAGE)
250
  ),
251
  'success'
252
  );
12
  *
13
  * @package : OMGF
14
  * @author : Daan van den Bergh
15
+ * @copyright: © 2022 Daan van den Bergh
16
+ * @url : https://ffw.press
17
  * * * * * * * * * * * * * * * * * * * */
18
 
19
  class OMGF_Admin
21
  const OMGF_ADMIN_JS_HANDLE = 'omgf-admin-js';
22
  const OMGF_ADMIN_CSS_HANDLE = 'omgf-admin-css';
23
 
24
+ /** @var array $stale_cache_options */
25
+ private $stale_cache_options = [];
26
 
27
  /** @var string $plugin_text_domain */
28
  private $plugin_text_domain = 'host-webfonts-local';
33
  public function __construct()
34
  {
35
  /**
36
+ * Filterable list of options that marks the cache as stale.
37
  */
38
+ $this->stale_cache_options = apply_filters(
39
+ 'omgf_admin_stale_cache_options',
40
  [
41
+ OMGF_Admin_Settings::OMGF_ADV_SETTING_CACHE_DIR,
 
 
42
  ]
43
  );
44
 
51
  $this->do_help();
52
  $this->maybe_do_after_update_notice();
53
 
54
+ /**
55
+ * @since v4.7.0 Fixes a bug where the Optimized Fonts wouldn't be shown after page reload.
56
+ */
57
+ add_filter('pre_update_option_omgf_optimized_fonts', [$this, 'update_optimized_fonts'], 10, 2);
58
  add_filter('pre_update_option_omgf_cache_keys', [$this, 'clean_up_cache'], 10, 3);
59
  add_action('pre_update_option_omgf_cache_dir', [$this, 'validate_cache_dir'], 10, 2);
60
  add_filter('pre_update_option', [$this, 'settings_changed'], 10, 3);
120
  */
121
  private function maybe_do_after_update_notice()
122
  {
123
+ if (OMGF_CURRENT_DB_VERSION != false && version_compare(OMGF_CURRENT_DB_VERSION, OMGF_DB_VERSION, '<')) {
124
  OMGF_Admin_Notice::set_notice(
125
  sprintf(
126
  __('Thank you for updating OMGF to v%s! This version contains database changes. <a href="%s">Verify your settings</a> and make sure everything is as you left it or, <a href="%s">view the changelog</a> for details. ', $this->plugin_text_domain),
128
  admin_url(OMGF_Admin_Settings::OMGF_OPTIONS_GENERAL_PAGE_OPTIMIZE_WEBFONTS),
129
  admin_url(OMGF_Admin_Settings::OMGF_PLUGINS_INSTALL_CHANGELOG_SECTION)
130
  ),
131
+ 'omgf-post-update'
 
132
  );
133
 
134
  update_option(OMGF_Admin_Settings::OMGF_CURRENT_DB_VERSION, OMGF_DB_VERSION);
171
  $cache_keys = explode(',', $old_value);
172
 
173
  foreach ($cache_keys as $key) {
174
+ $entries = array_filter((array) glob(OMGF_CACHE_PATH . "/*$key"));
175
 
176
  foreach ($entries as $entry) {
177
  OMGF::delete($entry);
201
  }
202
 
203
  if (!$mkdir) {
204
+ OMGF_Admin_Notice::set_notice(sprintf(__('Something went wrong while trying to create OMGF\'s Cache Directory: %s. Setting wasn\'t updated.', $this->plugin_text_domain), $new_dir), 'omgf-create-cache-dir-failed', 'error');
205
 
206
  return $old_dir;
207
  }
209
  $real_path = realpath($allowed_path);
210
 
211
  if ($real_path != rtrim($allowed_path, '/')) {
212
+ OMGF_Admin_Notice::set_notice(__('OMGF\'s Cache Directory wasn\'t changed. Attempted path traversal.', $this->plugin_text_domain), 'omgf-attempted-path-traversal', 'error');
213
 
214
  return $old_dir;
215
  }
229
  */
230
  public function settings_changed($value, $option_name, $old_value)
231
  {
232
+ if (!in_array($option_name, $this->stale_cache_options)) {
233
  return $value;
234
  }
235
 
236
+ /**
237
+ * If $old_value equals false, that means it's never been set before.
238
+ */
239
+ if ($value != $old_value && $old_value !== false) {
240
  global $wp_settings_errors;
241
 
242
  if (!empty($wp_settings_errors)) {
243
  $wp_settings_errors = [];
244
  }
245
 
246
+ update_option(OMGF_Admin_Settings::OMGF_CACHE_IS_STALE, true);
247
+
248
  add_settings_error(
249
  'general',
250
+ 'omgf_cache_style',
251
  sprintf(
252
+ __('OMGF\'s cached stylesheets don\'t reflect the current settings. Refresh the cache from the <a href="%s">Task Manager</a>.', $this->plugin_text_domain),
253
+ admin_url(OMGF_Admin_Settings::OMGF_OPTIONS_GENERAL_PAGE_OPTIMIZE_WEBFONTS)
254
  ),
255
  'success'
256
  );
includes/class-ajax.php CHANGED
@@ -10,8 +10,8 @@
10
  *
11
  * @package : OMGF
12
  * @author : Daan van den Bergh
13
- * @copyright: (c) 2021 Daan van den Bergh
14
- * @url : https://daan.dev
15
  * * * * * * * * * * * * * * * * * * * */
16
 
17
  defined('ABSPATH') || exit;
@@ -26,7 +26,91 @@ class OMGF_AJAX
26
  */
27
  public function __construct()
28
  {
29
- add_action('wp_ajax_omgf_ajax_empty_dir', [$this, 'empty_directory']);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
30
  }
31
 
32
  /**
@@ -40,12 +124,12 @@ class OMGF_AJAX
40
  check_ajax_referer(OMGF_Admin_Settings::OMGF_ADMIN_PAGE, 'nonce');
41
 
42
  if (!current_user_can('manage_options')) {
43
- wp_die(__("You're not cool enough to access this page.", $this->plugin_text_domain));
44
  }
45
 
46
  $section = str_replace('*', '', $_POST['section']);
47
- $set_path = rtrim(OMGF_FONTS_DIR . $section, '/');
48
- $resolved_path = realpath(OMGF_FONTS_DIR . $section);
49
 
50
  if ($resolved_path != $set_path) {
51
  wp_die(__('Attempted path traversal detected. Sorry, no script kiddies allowed!', $this->plugin_text_domain));
@@ -53,45 +137,51 @@ class OMGF_AJAX
53
 
54
  try {
55
  $section = $_POST['section'];
56
- $entries = array_filter((array) glob(OMGF_FONTS_DIR . $section));
57
-
58
- $instructions = apply_filters(
59
- 'omgf_clean_up_instructions',
60
- [
61
- 'section' => $section,
62
- 'exclude' => [],
63
- 'queue' => [
64
- OMGF_Admin_Settings::OMGF_OPTIMIZE_SETTING_CACHE_KEYS,
65
- OMGF_Admin_Settings::OMGF_OPTIMIZE_SETTING_OPTIMIZED_FONTS,
66
- OMGF_Admin_Settings::OMGF_OPTIMIZE_SETTING_UNLOAD_FONTS,
67
- OMGF_Admin_Settings::OMGF_OPTIMIZE_SETTING_PRELOAD_FONTS,
68
- OMGF_Admin_Settings::OMGF_OPTIMIZE_SETTING_UNLOAD_STYLESHEETS
69
- ]
70
- ]
71
- );
72
-
73
- foreach ($entries as $entry) {
74
- if (in_array($entry, $instructions['exclude'])) {
75
- continue;
76
- }
77
-
78
- OMGF::delete($entry);
79
- }
80
 
81
-
82
- foreach ($instructions['queue'] as $option) {
83
- delete_option($option);
84
- }
85
 
86
  OMGF_Admin_Notice::set_notice(__('Cache directory successfully emptied.', $this->plugin_text_domain));
87
  } catch (\Exception $e) {
88
  OMGF_Admin_Notice::set_notice(
89
  __('OMGF encountered an error while emptying the cache directory: ', $this->plugin_text_domain) . $e->getMessage(),
90
  'omgf-cache-error',
91
- true,
92
  'error',
93
  $e->getCode()
94
  );
95
  }
96
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
97
  }
10
  *
11
  * @package : OMGF
12
  * @author : Daan van den Bergh
13
+ * @copyright: © 2022 Daan van den Bergh
14
+ * @url : https://ffw.press
15
  * * * * * * * * * * * * * * * * * * * */
16
 
17
  defined('ABSPATH') || exit;
26
  */
27
  public function __construct()
28
  {
29
+ add_action('wp_ajax_omgf_remove_stylesheet_from_db', [$this, 'remove_stylesheet_from_db']);
30
+ add_action('wp_ajax_omgf_refresh_cache', [$this, 'refresh_cache']);
31
+ add_action('wp_ajax_omgf_empty_dir', [$this, 'empty_directory']);
32
+ }
33
+
34
+ /**
35
+ * Remove stylesheet with $handle from database.
36
+ */
37
+ public function remove_stylesheet_from_db()
38
+ {
39
+ check_ajax_referer(OMGF_Admin_Settings::OMGF_ADMIN_PAGE, 'nonce');
40
+
41
+ if (!current_user_can('manage_options')) {
42
+ wp_die(__("Hmmm, you're not supposed to be here.", $this->plugin_text_domain));
43
+ }
44
+
45
+ $handle = $_POST['handle'];
46
+ $optimized_fonts = OMGF::optimized_fonts();
47
+ $unloaded_fonts = OMGF::unloaded_fonts();
48
+ $unloaded_stylesheets = OMGF::unloaded_stylesheets();
49
+ $preloaded_fonts = OMGF::preloaded_fonts();
50
+ $cache_keys = OMGF::cache_keys();
51
+
52
+ $this->maybe_unset(OMGF_Admin_Settings::OMGF_OPTIMIZE_SETTING_CACHE_KEYS, $cache_keys, $handle, true);
53
+ $this->maybe_unset(OMGF_Admin_Settings::OMGF_OPTIMIZE_SETTING_OPTIMIZED_FONTS, $optimized_fonts, $handle);
54
+ $this->maybe_unset(OMGF_Admin_Settings::OMGF_OPTIMIZE_SETTING_UNLOAD_FONTS, $unloaded_fonts, $handle);
55
+ $this->maybe_unset(OMGF_Admin_Settings::OMGF_OPTIMIZE_SETTING_UNLOAD_STYLESHEETS, $unloaded_stylesheets, $handle);
56
+ $this->maybe_unset(OMGF_Admin_Settings::OMGF_OPTIMIZE_SETTING_PRELOAD_FONTS, $preloaded_fonts, $handle);
57
+ }
58
+
59
+ /**
60
+ * Unset a $key from $array and update $option_name. Optionally store array as comma separated string.
61
+ *
62
+ * @param string $option_name The option name to update.
63
+ * @param array $array The array to saarch.
64
+ * @param string $key The key to unset when found.
65
+ * @param bool $comma_separated When true, $array is converted to a comma separated string before saving it
66
+ * to the database.
67
+ *
68
+ * @return void
69
+ */
70
+ private function maybe_unset($option_name, $array, $key, $comma_separated = false)
71
+ {
72
+ if (isset($array[$key]) || in_array($key, $array)) {
73
+ if ($comma_separated) {
74
+ $cache_key = OMGF::get_cache_key($key) ?: $key;
75
+ $key_key = array_search($cache_key, $array);
76
+
77
+ unset($array[$key_key]);
78
+ } else {
79
+ unset($array[$key]);
80
+ }
81
+
82
+ if ($comma_separated) {
83
+ $array = implode(',', $array);
84
+ }
85
+
86
+ update_option($option_name, $array);
87
+ }
88
+ }
89
+
90
+ /**
91
+ * Removes the stale cache mark. Should be triggered along with a form submit.
92
+ */
93
+ public function refresh_cache()
94
+ {
95
+ check_ajax_referer(OMGF_Admin_Settings::OMGF_ADMIN_PAGE, 'nonce');
96
+
97
+ if (!current_user_can('manage_options')) {
98
+ wp_die(__("Hmmm, you're not supposed to be here.", $this->plugin_text_domain));
99
+ }
100
+
101
+ add_filter('omgf_clean_up_instructions', function () {
102
+ return [
103
+ 'section' => '/',
104
+ 'exclude' => [],
105
+ 'queue' => [
106
+ OMGF_Admin_Settings::OMGF_CACHE_IS_STALE
107
+ ]
108
+ ];
109
+ });
110
+
111
+ $this->empty_cache('/');
112
+
113
+ delete_option(OMGF_Admin_Settings::OMGF_CACHE_IS_STALE);
114
  }
115
 
116
  /**
124
  check_ajax_referer(OMGF_Admin_Settings::OMGF_ADMIN_PAGE, 'nonce');
125
 
126
  if (!current_user_can('manage_options')) {
127
+ wp_die(__("Hmmm, you're not supposed to be here.", $this->plugin_text_domain));
128
  }
129
 
130
  $section = str_replace('*', '', $_POST['section']);
131
+ $set_path = rtrim(OMGF_CACHE_PATH . $section, '/');
132
+ $resolved_path = realpath(OMGF_CACHE_PATH . $section);
133
 
134
  if ($resolved_path != $set_path) {
135
  wp_die(__('Attempted path traversal detected. Sorry, no script kiddies allowed!', $this->plugin_text_domain));
137
 
138
  try {
139
  $section = $_POST['section'];
140
+ $entries = array_filter((array) glob(OMGF_CACHE_PATH . $section));
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
141
 
142
+ $this->empty_cache($section, $entries);
 
 
 
143
 
144
  OMGF_Admin_Notice::set_notice(__('Cache directory successfully emptied.', $this->plugin_text_domain));
145
  } catch (\Exception $e) {
146
  OMGF_Admin_Notice::set_notice(
147
  __('OMGF encountered an error while emptying the cache directory: ', $this->plugin_text_domain) . $e->getMessage(),
148
  'omgf-cache-error',
 
149
  'error',
150
  $e->getCode()
151
  );
152
  }
153
  }
154
+
155
+ private function empty_cache($section)
156
+ {
157
+ $entries = array_filter((array) glob(OMGF_CACHE_PATH . $section));
158
+ $instructions = apply_filters(
159
+ 'omgf_clean_up_instructions',
160
+ [
161
+ 'section' => $section,
162
+ 'exclude' => [],
163
+ 'queue' => [
164
+ OMGF_Admin_Settings::OMGF_CACHE_IS_STALE,
165
+ OMGF_Admin_Settings::OMGF_OPTIMIZE_SETTING_CACHE_KEYS,
166
+ OMGF_Admin_Settings::OMGF_OPTIMIZE_SETTING_OPTIMIZED_FONTS,
167
+ OMGF_Admin_Settings::OMGF_OPTIMIZE_SETTING_UNLOAD_FONTS,
168
+ OMGF_Admin_Settings::OMGF_OPTIMIZE_SETTING_PRELOAD_FONTS,
169
+ OMGF_Admin_Settings::OMGF_OPTIMIZE_SETTING_UNLOAD_STYLESHEETS
170
+ ]
171
+ ]
172
+ );
173
+
174
+ foreach ($entries as $entry) {
175
+ if (in_array($entry, $instructions['exclude'])) {
176
+ continue;
177
+ }
178
+
179
+ OMGF::delete($entry);
180
+ }
181
+
182
+
183
+ foreach ($instructions['queue'] as $option) {
184
+ delete_option($option);
185
+ }
186
+ }
187
  }
includes/class-download.php CHANGED
@@ -12,8 +12,8 @@ defined('ABSPATH') || exit;
12
  *
13
  * @package : OMGF
14
  * @author : Daan van den Bergh
15
- * @copyright: (c) 2021 Daan van den Bergh
16
- * @url : https://daan.dev
17
  * * * * * * * * * * * * * * * * * * * */
18
 
19
  class OMGF_Download
@@ -71,11 +71,15 @@ class OMGF_Download
71
  return urlencode(content_url($file_uri));
72
  }
73
 
 
 
 
 
74
  $tmp = download_url($this->url);
75
 
76
  if (is_wp_error($tmp)) {
77
  /** @var WP_Error $tmp */
78
- OMGF_Admin_Notice::set_notice(__('OMGF encountered an error while downloading fonts', $this->plugin_text_domain) . ': ' . $tmp->get_error_message(), 'omgf-download-failed', false, 'error', $tmp->get_error_code());
79
 
80
  return '';
81
  }
12
  *
13
  * @package : OMGF
14
  * @author : Daan van den Bergh
15
+ * @copyright: © 2022 Daan van den Bergh
16
+ * @url : https://ffw.press
17
  * * * * * * * * * * * * * * * * * * * */
18
 
19
  class OMGF_Download
71
  return urlencode(content_url($file_uri));
72
  }
73
 
74
+ if (strpos($this->url, '//') === 0) {
75
+ $this->url = 'https:' . $this->url;
76
+ }
77
+
78
  $tmp = download_url($this->url);
79
 
80
  if (is_wp_error($tmp)) {
81
  /** @var WP_Error $tmp */
82
+ OMGF_Admin_Notice::set_notice(__('OMGF encountered an error while downloading fonts', $this->plugin_text_domain) . ': ' . $tmp->get_error_message(), 'omgf-download-failed', 'error', $tmp->get_error_code());
83
 
84
  return '';
85
  }
includes/class-omgf.php CHANGED
@@ -10,8 +10,8 @@
10
  *
11
  * @package : OMGF
12
  * @author : Daan van den Bergh
13
- * @copyright: (c) 2021 Daan van den Bergh
14
- * @url : https://daan.dev
15
  * * * * * * * * * * * * * * * * * * * */
16
 
17
  defined('ABSPATH') || exit;
@@ -26,15 +26,16 @@ class OMGF
26
  $this->define_constants();
27
 
28
  if (is_admin()) {
29
- add_action('plugins_loaded', [$this, 'init_admin'], 50);
 
 
30
  }
31
 
32
  if (!is_admin()) {
33
- add_action('plugins_loaded', [$this, 'init_frontend'], 50);
34
  }
35
 
36
  add_action('admin_init', [$this, 'do_optimize']);
37
- add_action('rest_api_init', [$this, 'register_routes']);
38
  add_filter('content_url', [$this, 'force_ssl'], 1000, 2);
39
 
40
  /**
@@ -48,39 +49,115 @@ class OMGF
48
  */
49
  public function define_constants()
50
  {
51
- define('OMGF_SITE_URL', 'https://daan.dev');
 
 
 
52
  define('OMGF_CURRENT_DB_VERSION', esc_attr(get_option(OMGF_Admin_Settings::OMGF_CURRENT_DB_VERSION)));
53
- define('OMGF_OPTIMIZATION_MODE', esc_attr(get_option(OMGF_Admin_Settings::OMGF_OPTIMIZE_SETTING_OPTIMIZATION_MODE, 'manual')));
54
- define('OMGF_MANUAL_OPTIMIZE_URL', esc_url(get_option(OMGF_Admin_Settings::OMGF_OPTIMIZE_SETTING_MANUAL_OPTIMIZE_URL, get_site_url()) ?: get_site_url()));
55
- define('OMGF_FONT_PROCESSING', esc_attr(get_option(OMGF_Admin_Settings::OMGF_DETECTION_SETTING_FONT_PROCESSING, 'replace')));
56
  define('OMGF_DISPLAY_OPTION', esc_attr(get_option(OMGF_Admin_Settings::OMGF_OPTIMIZE_SETTING_DISPLAY_OPTION, 'swap')) ?: 'swap');
57
- define('OMGF_OPTIMIZE_EDIT_ROLES', esc_attr(get_option(OMGF_Admin_Settings::OMGF_OPTIMIZE_SETTING_OPTIMIZE_EDIT_ROLES, 'on')));
58
- define('OMGF_CACHE_PATH', esc_attr(get_option(OMGF_Admin_Settings::OMGF_ADV_SETTING_CACHE_PATH)) ?: '/uploads/omgf');
59
- define('OMGF_FONTS_DIR', WP_CONTENT_DIR . OMGF_CACHE_PATH);
60
- define('OMGF_UNINSTALL', esc_attr(get_option(OMGF_Admin_Settings::OMGF_ADV_SETTING_UNINSTALL)));
61
  define('OMGF_UNLOAD_STYLESHEETS', esc_attr(get_option(OMGF_Admin_Settings::OMGF_OPTIMIZE_SETTING_UNLOAD_STYLESHEETS, '')));
62
  define('OMGF_CACHE_KEYS', esc_attr(get_option(OMGF_Admin_Settings::OMGF_OPTIMIZE_SETTING_CACHE_KEYS, '')));
 
 
 
 
63
  }
64
 
65
  /**
66
- * Required in Admin.
67
  *
68
- * @return void
 
 
69
  */
70
  public function init_admin()
71
  {
72
- $this->do_settings();
73
- $this->add_ajax_hooks();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
74
  }
75
 
76
  /**
77
- * Required in Frontend.
78
  *
 
 
79
  * @return void
80
  */
81
- public function init_frontend()
82
  {
83
- $this->do_frontend();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
84
  }
85
 
86
  /**
@@ -233,110 +310,10 @@ class OMGF
233
  return $generator->generate();
234
  }
235
 
236
- /**
237
- * @return OMGF_Admin_Settings
238
- */
239
- private function do_settings()
240
- {
241
- return new OMGF_Admin_Settings();
242
- }
243
-
244
- /**
245
- * @return OMGF_AJAX
246
- */
247
- private function add_ajax_hooks()
248
- {
249
- return new OMGF_AJAX();
250
- }
251
-
252
- /**
253
- * @return OMGF_Frontend_Functions
254
- */
255
- public function do_frontend()
256
- {
257
- return new OMGF_Frontend_Functions();
258
- }
259
-
260
- /**
261
- *
262
- */
263
- public function register_routes()
264
- {
265
- $proxy = new OMGF_API_Download();
266
- $proxy->register_routes();
267
- }
268
-
269
- /**
270
- * @return OMGF_Optimize
271
- */
272
- public function do_optimize()
273
- {
274
- return new OMGF_Optimize();
275
- }
276
-
277
- /**
278
- * Render update notices if available.
279
- *
280
- * @param mixed $plugin
281
- * @param mixed $response
282
- * @return void
283
- */
284
- public function render_update_notice($plugin, $response)
285
- {
286
- $current_version = $plugin['Version'];
287
- $new_version = $plugin['new_version'];
288
-
289
- if (version_compare($current_version, $new_version, '<')) {
290
- $response = wp_remote_get('https://daan.dev/omgf-update-notices.json');
291
-
292
- if (is_wp_error($response)) {
293
- return;
294
- }
295
-
296
- $update_notices = (array) json_decode(wp_remote_retrieve_body($response));
297
-
298
- if (!isset($update_notices[$new_version])) {
299
- return;
300
- }
301
-
302
- printf(
303
- ' <strong>' . __('This update includes major changes, please <a href="%s" target="_blank">read this</a> before continuing.') . '</strong>',
304
- $update_notices[$new_version]->url
305
- );
306
- }
307
- }
308
-
309
- /**
310
- * content_url() uses is_ssl() to detect whether SSL is used. This fails for servers behind
311
- * load balancers and/or reverse proxies. So, we double check with this filter.
312
- *
313
- * @since v4.4.4
314
- *
315
- * @param mixed $url
316
- * @param mixed $path
317
- * @return mixed
318
- */
319
- public function force_ssl($url, $path)
320
- {
321
- /**
322
- * Only rewrite URLs requested by this plugin. We don't want to interfere with other plugins.
323
- */
324
- if (strpos($url, OMGF_CACHE_PATH) === false) {
325
- return $url;
326
- }
327
-
328
- /**
329
- * If the user entered https:// in the Home URL option, it's safe to assume that SSL is used.
330
- */
331
- if (!is_ssl() && strpos(home_url(), 'https://') !== false) {
332
- $url = str_replace('http://', 'https://', $url);
333
- }
334
-
335
- return $url;
336
- }
337
 
338
  /**
339
  * @return OMGF_Uninstall
 
340
  * @throws ReflectionException
341
  */
342
  public static function do_uninstall()
@@ -364,6 +341,23 @@ class OMGF
364
  }
365
  }
366
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
367
  /**
368
  * Global debug logging function.
369
  *
10
  *
11
  * @package : OMGF
12
  * @author : Daan van den Bergh
13
+ * @copyright: © 2022 Daan van den Bergh
14
+ * @url : https://ffw.press
15
  * * * * * * * * * * * * * * * * * * * */
16
 
17
  defined('ABSPATH') || exit;
26
  $this->define_constants();
27
 
28
  if (is_admin()) {
29
+ add_action('_admin_menu', [$this, 'init_admin']);
30
+
31
+ $this->add_ajax_hooks();
32
  }
33
 
34
  if (!is_admin()) {
35
+ add_action('init', [$this, 'init_frontend'], 50);
36
  }
37
 
38
  add_action('admin_init', [$this, 'do_optimize']);
 
39
  add_filter('content_url', [$this, 'force_ssl'], 1000, 2);
40
 
41
  /**
49
  */
50
  public function define_constants()
51
  {
52
+ /** Prevents undefined constant in OMGF Pro, if its not at version v3.3.0 (yet) */
53
+ define('OMGF_OPTIMIZATION_MODE', false);
54
+ define('OMGF_SITE_URL', 'https://ffw.press');
55
+ define('OMGF_CACHE_IS_STALE', esc_attr(get_option(OMGF_Admin_Settings::OMGF_CACHE_IS_STALE)));
56
  define('OMGF_CURRENT_DB_VERSION', esc_attr(get_option(OMGF_Admin_Settings::OMGF_CURRENT_DB_VERSION)));
 
 
 
57
  define('OMGF_DISPLAY_OPTION', esc_attr(get_option(OMGF_Admin_Settings::OMGF_OPTIMIZE_SETTING_DISPLAY_OPTION, 'swap')) ?: 'swap');
 
 
 
 
58
  define('OMGF_UNLOAD_STYLESHEETS', esc_attr(get_option(OMGF_Admin_Settings::OMGF_OPTIMIZE_SETTING_UNLOAD_STYLESHEETS, '')));
59
  define('OMGF_CACHE_KEYS', esc_attr(get_option(OMGF_Admin_Settings::OMGF_OPTIMIZE_SETTING_CACHE_KEYS, '')));
60
+ define('OMGF_OPTIMIZE_EDIT_ROLES', esc_attr(get_option(OMGF_Admin_Settings::OMGF_OPTIMIZE_SETTING_OPTIMIZE_EDIT_ROLES, 'on')));
61
+ define('OMGF_CACHE_DIR', esc_attr(get_option(OMGF_Admin_Settings::OMGF_ADV_SETTING_CACHE_DIR)) ?: '/uploads/omgf');
62
+ define('OMGF_UNINSTALL', esc_attr(get_option(OMGF_Admin_Settings::OMGF_ADV_SETTING_UNINSTALL)));
63
+ define('OMGF_CACHE_PATH', WP_CONTENT_DIR . OMGF_CACHE_DIR);
64
  }
65
 
66
  /**
67
+ * Needs to run before admin_menu and admin_init.
68
  *
69
+ * @action _admin_menu
70
+ *
71
+ * @return OMGF_Admin_Settings
72
  */
73
  public function init_admin()
74
  {
75
+ return new OMGF_Admin_Settings();
76
+ }
77
+
78
+ /**
79
+ * @return OMGF_AJAX
80
+ */
81
+ private function add_ajax_hooks()
82
+ {
83
+ return new OMGF_AJAX();
84
+ }
85
+
86
+ /**
87
+ * @return OMGF_Frontend_Process
88
+ */
89
+ public function init_frontend()
90
+ {
91
+ return new OMGF_Frontend_Process();
92
+ }
93
+
94
+ /**
95
+ * @return OMGF_Admin_Optimize
96
+ */
97
+ public function do_optimize()
98
+ {
99
+ return new OMGF_Admin_Optimize();
100
+ }
101
+
102
+ /**
103
+ * content_url() uses is_ssl() to detect whether SSL is used. This fails for servers behind
104
+ * load balancers and/or reverse proxies. So, we double check with this filter.
105
+ *
106
+ * @since v4.4.4
107
+ *
108
+ * @param mixed $url
109
+ * @param mixed $path
110
+ * @return mixed
111
+ */
112
+ public function force_ssl($url, $path)
113
+ {
114
+ /**
115
+ * Only rewrite URLs requested by this plugin. We don't want to interfere with other plugins.
116
+ */
117
+ if (strpos($url, OMGF_CACHE_DIR) === false) {
118
+ return $url;
119
+ }
120
+
121
+ /**
122
+ * If the user entered https:// in the Home URL option, it's safe to assume that SSL is used.
123
+ */
124
+ if (!is_ssl() && strpos(get_site_url(), 'https://') !== false) {
125
+ $url = str_replace('http://', 'https://', $url);
126
+ }
127
+
128
+ return $url;
129
  }
130
 
131
  /**
132
+ * Render update notices if available.
133
  *
134
+ * @param mixed $plugin
135
+ * @param mixed $response
136
  * @return void
137
  */
138
+ public function render_update_notice($plugin, $response)
139
  {
140
+ $current_version = $plugin['Version'];
141
+ $new_version = $plugin['new_version'];
142
+
143
+ if (version_compare($current_version, $new_version, '<')) {
144
+ $response = wp_remote_get('https://ffw.press/omgf-update-notices.json');
145
+
146
+ if (is_wp_error($response)) {
147
+ return;
148
+ }
149
+
150
+ $update_notices = (array) json_decode(wp_remote_retrieve_body($response));
151
+
152
+ if (!isset($update_notices[$new_version])) {
153
+ return;
154
+ }
155
+
156
+ printf(
157
+ ' <strong>' . __('This update includes major changes, please <a href="%s" target="_blank">read this</a> before continuing.') . '</strong>',
158
+ $update_notices[$new_version]->url
159
+ );
160
+ }
161
  }
162
 
163
  /**
310
  return $generator->generate();
311
  }
312
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
313
 
314
  /**
315
  * @return OMGF_Uninstall
316
+ *
317
  * @throws ReflectionException
318
  */
319
  public static function do_uninstall()
341
  }
342
  }
343
 
344
+ /**
345
+ * Helper to return WordPress filesystem subclass.
346
+ *
347
+ * @return WP_Filesystem_Base $wp_filesystem
348
+ */
349
+ public static function filesystem()
350
+ {
351
+ global $wp_filesystem;
352
+
353
+ if (is_null($wp_filesystem)) {
354
+ require_once ABSPATH . '/wp-admin/includes/file.php';
355
+ WP_Filesystem();
356
+ }
357
+
358
+ return $wp_filesystem;
359
+ }
360
+
361
  /**
362
  * Global debug logging function.
363
  *
includes/class-optimize.php CHANGED
@@ -1,6 +1,4 @@
1
  <?php
2
- defined('ABSPATH') || exit;
3
-
4
  /* * * * * * * * * * * * * * * * * * * * *
5
  *
6
  * ██████╗ ███╗ ███╗ ██████╗ ███████╗
@@ -12,84 +10,463 @@ defined('ABSPATH') || exit;
12
  *
13
  * @package : OMGF
14
  * @author : Daan van den Bergh
15
- * @copyright: (c) 2021 Daan van den Bergh
16
- * @url : https://daan.dev
17
  * * * * * * * * * * * * * * * * * * * */
18
 
 
 
19
  class OMGF_Optimize
20
  {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
21
  /** @var string */
22
- private $settings_page = '';
23
 
24
  /** @var string */
25
- private $settings_tab = '';
26
 
27
- /** @var bool */
28
- private $settings_updated = false;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
29
 
30
  /**
31
- * OMGF_Optimize constructor.
 
 
 
 
 
 
32
  */
33
- public function __construct()
34
  {
35
- $this->settings_page = $_GET['page'] ?? '';
36
- $this->settings_tab = $_GET['tab'] ?? OMGF_Admin_Settings::OMGF_SETTINGS_FIELD_OPTIMIZE;
37
- $this->settings_updated = isset($_GET['settings-updated']);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
38
 
39
- $this->init();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
40
  }
41
 
42
  /**
43
- * Run either manual or auto mode after settings are updated.
44
- *
45
- * @return void
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
46
  */
47
- private function init()
48
  {
49
- if (OMGF_Admin_Settings::OMGF_ADMIN_PAGE != $this->settings_page) {
50
- return;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
51
  }
52
 
53
- if (OMGF_Admin_Settings::OMGF_SETTINGS_FIELD_OPTIMIZE != $this->settings_tab) {
54
- return;
 
 
 
55
  }
56
 
57
- if (!$this->settings_updated) {
58
- return;
 
 
 
 
 
 
 
 
 
 
 
 
 
59
  }
60
 
61
- add_filter('http_request_args', [$this, 'verify_ssl']);
 
 
 
 
 
 
 
 
 
 
 
 
62
 
63
- $optimization_mode = apply_filters('omgf_optimization_mode', OMGF_OPTIMIZATION_MODE);
 
64
 
65
- if ('manual' == $optimization_mode) {
66
- $this->run_manual();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
67
  }
 
 
68
  }
69
 
70
  /**
71
- * If this site is non-SSL it makes no sense to verify its SSL certificates.
 
72
  *
73
- * Settings sslverify to false will set CURLOPT_SSL_VERIFYPEER and CURLOPT_SSL_VERIFYHOST
74
- * to 0 further down the road.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
75
  *
76
- * @param mixed $url
77
  * @return array
78
  */
79
- public function verify_ssl($args)
80
  {
81
- $args['sslverify'] = strpos(home_url(), 'https:') !== false;
 
 
 
 
 
 
 
 
 
82
 
83
- return $args;
84
  }
85
 
86
  /**
87
- * Run Force mode.
88
  *
89
- * @return void
 
 
 
 
90
  */
91
- private function run_manual()
92
  {
93
- new OMGF_OptimizationMode_Manual();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
94
  }
95
  }
1
  <?php
 
 
2
  /* * * * * * * * * * * * * * * * * * * * *
3
  *
4
  * ██████╗ ███╗ ███╗ ██████╗ ███████╗
10
  *
11
  * @package : OMGF
12
  * @author : Daan van den Bergh
13
+ * @copyright: © 2022 Daan van den Bergh
14
+ * @url : https://ffw.press
15
  * * * * * * * * * * * * * * * * * * * */
16
 
17
+ defined('ABSPATH') || exit;
18
+
19
  class OMGF_Optimize
20
  {
21
+ const OMGF_GOOGLE_FONTS_API_URL = 'https://google-webfonts-helper.herokuapp.com/api/fonts/';
22
+ const OMGF_GOOGLE_FONTS_API_FALLBACK = 'https://omgf-google-fonts-api.herokuapp.com/api/fonts/';
23
+ const OMGF_USE_FALLBACK_API_TRANSIENT = 'omgf_use_fallback_api';
24
+
25
+ /**
26
+ * If a font changed names recently, this array will map the old name (key) to the new name (value).
27
+ *
28
+ * The key of an element should be dashed (no spaces) if necessary, e.g. open-sans.
29
+ */
30
+ const OMGF_RENAMED_GOOGLE_FONTS = [
31
+ 'crimson-text' => 'crimson-pro',
32
+ 'ek-mukta' => 'mukta',
33
+ 'muli' => 'mulish'
34
+ ];
35
+
36
+ /** @var string $family */
37
+ private $family = '';
38
+
39
+ /** @var string */
40
+ private $handle = '';
41
+
42
+ /** @var string $original_handle */
43
+ private $original_handle = '';
44
+
45
+ /** @var string $subset */
46
+ private $subset = 'latin';
47
+
48
+ /** @var string $return */
49
+ private $return = 'url';
50
+
51
  /** @var string */
52
+ private $path = '';
53
 
54
  /** @var string */
55
+ private $plugin_text_domain = 'host-webfonts-local';
56
 
57
+ /**
58
+ * @param string $family Contents of "family" parameters in Google Fonts API URL, e.g. "?family="Lato:100,200,300,etc."
59
+ * @param string $handle The cache handle, generated using $handle + 5 random chars. Used for storing the fonts and stylesheet.
60
+ * @param string $original_handle The stylesheet handle, present in the ID attribute.
61
+ * @param string $subset Contents of "subset" parameter, defaults to 'latin', because most fonts are available in this subset.
62
+ * @param string $return Valid values: 'url' | 'path' | 'object'.
63
+ *
64
+ * @return string Local URL of generated stylesheet.
65
+ *
66
+ * @throws SodiumException
67
+ * @throws SodiumException
68
+ * @throws TypeError
69
+ * @throws TypeError
70
+ * @throws TypeError
71
+ */
72
+ public function __construct(
73
+ string $family,
74
+ string $handle,
75
+ string $original_handle,
76
+ string $subset = '',
77
+ string $return = 'url'
78
+ ) {
79
+ $this->family = $family;
80
+ $this->handle = sanitize_title_with_dashes($handle);
81
+ $this->original_handle = sanitize_title_with_dashes($original_handle);
82
+ $this->subset = $subset ?: 'latin';
83
+ $this->path = OMGF_CACHE_PATH . '/' . $this->handle;
84
+ $this->return = $return;
85
+ }
86
 
87
  /**
88
+ * @return string|array
89
+ *
90
+ * @throws SodiumException
91
+ * @throws SodiumException
92
+ * @throws TypeError
93
+ * @throws TypeError
94
+ * @throws TypeError
95
  */
96
+ public function process()
97
  {
98
+ if (!$this->handle || !$this->original_handle) {
99
+ OMGF_Admin_Notice::set_notice(sprintf(__('OMGF couldn\'t find required stylesheet handle parameter while attempting to talk to API. Values sent were <code>%s</code> and <code>%s</code>.', $this->plugin_text_domain), $this->original_handle, $this->handle), 'omgf-api-handle-not-found', 'error', 406);
100
+
101
+ return '';
102
+ }
103
+
104
+ $font_families = explode('|', $this->family);
105
+ $query['subsets'] = $this->subset;
106
+ $fonts = [];
107
+
108
+ foreach ($font_families as $font_family) {
109
+ if (empty($font_family)) {
110
+ continue;
111
+ }
112
+
113
+ $fonts[] = $this->grab_font_family($font_family, $query);
114
+ }
115
+
116
+ // Filter out empty elements, i.e. failed requests.
117
+ $fonts = array_filter($fonts);
118
 
119
+ if (empty($fonts)) {
120
+ return '';
121
+ }
122
+
123
+ foreach ($fonts as &$font) {
124
+ $fonts_request = $this->build_fonts_request($font_families, $font);
125
+
126
+ if (strpos($fonts_request, ':') != false) {
127
+ list($family, $requested_variants) = explode(':', $fonts_request);
128
+ } else {
129
+ $family = $fonts_request;
130
+ $requested_variants = '';
131
+ }
132
+
133
+ $requested_variants = $this->parse_requested_variants($requested_variants, $font);
134
+
135
+ if ($unloaded_fonts = OMGF::unloaded_fonts()) {
136
+ $font_id = $font->id;
137
+
138
+ // Now we're sure we got 'em all. We can safely dequeue those we don't want.
139
+ if (isset($unloaded_fonts[$this->original_handle][$font_id])) {
140
+ $requested_variants = $this->dequeue_unloaded_variants($requested_variants, $unloaded_fonts[$this->original_handle], $font->id);
141
+ $fonts_request = $family . ':' . implode(',', $requested_variants);
142
+ }
143
+ }
144
+
145
+ $font->variants = $this->process_unload_queue($font->id, $font->variants, $fonts_request, $this->original_handle);
146
+ }
147
+
148
+ /**
149
+ * Which file types should we download and include in the stylesheet?
150
+ *
151
+ * @since v4.5
152
+ */
153
+ $file_types = apply_filters('omgf_include_file_types', ['woff2', 'woff', 'eot', 'ttf', 'svg']);
154
+
155
+ foreach ($fonts as &$font) {
156
+ $font_id = $font->id;
157
+
158
+ /**
159
+ * Sanitize font family, because it may contain spaces.
160
+ *
161
+ * @since v4.5.6
162
+ */
163
+ $font->family = rawurlencode($font->family);
164
+
165
+ foreach ($font->variants as &$variant) {
166
+ $filename = strtolower($font_id . '-' . $variant->fontStyle . '-' . $variant->fontWeight);
167
+
168
+ /**
169
+ * Encode font family, because it may contain spaces.
170
+ *
171
+ * @since v4.5.6
172
+ */
173
+ $variant->fontFamily = rawurlencode($variant->fontFamily);
174
+
175
+ foreach ($file_types as $file_type) {
176
+ if (isset($variant->$file_type)) {
177
+ $variant->$file_type = OMGF::download($variant->$file_type, $filename, $file_type, $this->path);
178
+ }
179
+ }
180
+ }
181
+ }
182
+
183
+ $local_file = $this->path . '/' . $this->handle . '.css';
184
+ $stylesheet = OMGF::generate_stylesheet($fonts, $this->original_handle);
185
+ $filesystem = OMGF::filesystem();
186
+
187
+ if (!file_exists($this->path)) {
188
+ wp_mkdir_p($this->path);
189
+ }
190
+
191
+ $filesystem->put_contents($local_file, $stylesheet);
192
+
193
+ $current_stylesheet = [$this->original_handle => $fonts];
194
+
195
+ /**
196
+ * $current_stylesheet is added to temporary cache layer, if it isn't present in database.
197
+ *
198
+ * @since v4.5.7
199
+ */
200
+ $optimized_fonts = OMGF::optimized_fonts($current_stylesheet);
201
+
202
+ /**
203
+ * When unload is used, this takes care of rewriting the font style URLs in the database.
204
+ *
205
+ * @since v4.5.7
206
+ */
207
+ $optimized_fonts = $this->rewrite_variants($optimized_fonts, $current_stylesheet);
208
+
209
+ update_option(OMGF_Admin_Settings::OMGF_OPTIMIZE_SETTING_OPTIMIZED_FONTS, $optimized_fonts);
210
+
211
+ switch ($this->return) {
212
+ case 'path':
213
+ return $local_file;
214
+ break;
215
+ case 'object':
216
+ return $current_stylesheet;
217
+ break;
218
+ default: // 'url'
219
+ return str_replace(WP_CONTENT_DIR, content_url(), $local_file);
220
+ }
221
  }
222
 
223
  /**
224
+ * @param $variants
225
+ * @param $unloaded_fonts
226
+ * @param $font_id
227
+ *
228
+ * @return array
229
+ */
230
+ private function dequeue_unloaded_variants($variants, $unloaded_fonts, $font_id)
231
+ {
232
+ return array_filter(
233
+ $variants,
234
+ function ($value) use ($unloaded_fonts, $font_id) {
235
+ if ($value == '400') {
236
+ // Sometimes the font is defined as 'regular', so we need to check both.
237
+ return !in_array('regular', $unloaded_fonts[$font_id]) && !in_array($value, $unloaded_fonts[$font_id]);
238
+ }
239
+
240
+ if ($value == '400italic') {
241
+ // Sometimes the font is defined as 'italic', so we need to check both.
242
+ return !in_array('italic', $unloaded_fonts[$font_id]) && !in_array($value, $unloaded_fonts[$font_id]);
243
+ }
244
+
245
+ return !in_array($value, $unloaded_fonts[$font_id]);
246
+ }
247
+ );
248
+ }
249
+
250
+ /**
251
+ * @param $font_family
252
+ * @param $url
253
+ * @param $query
254
+ *
255
+ * @return mixed|void
256
  */
257
+ private function grab_font_family($font_family, $query)
258
  {
259
+ list($family) = explode(':', $font_family);
260
+
261
+ /**
262
+ * Replace multiple spaces or plus signs (or a combination of, with a single dash)
263
+ *
264
+ * @since v4.5.10
265
+ */
266
+ $family = strtolower(preg_replace("/[\s\+]+/", '-', $family));
267
+
268
+ /**
269
+ * Add fonts to the request's $_GET 'family' parameter. Then pass an array to 'omgf_alternate_fonts'
270
+ * filter. Then pass an alternate API url to the 'omgf_alternate_api_url' filter to fetch fonts from
271
+ * an alternate API.
272
+ */
273
+ $alternate_fonts = apply_filters('omgf_alternate_fonts', []);
274
+ $alternate_url = false;
275
+ $url = '';
276
+
277
+ if (in_array($family, array_keys($alternate_fonts))) {
278
+ $alternate_url = true;
279
+
280
+ $url = apply_filters('omgf_alternate_api_url', '', $family);
281
+ unset($query);
282
+ }
283
+
284
+ $query_string = '';
285
+
286
+ if (isset($query)) {
287
+ $query_string = '?' . http_build_query($query);
288
  }
289
 
290
+ /**
291
+ * If a font changed names recently, map their old name to the new name, before triggering the API request.
292
+ */
293
+ if (in_array($family, array_keys(self::OMGF_RENAMED_GOOGLE_FONTS))) {
294
+ $family = self::OMGF_RENAMED_GOOGLE_FONTS[$family];
295
  }
296
 
297
+ if (!$alternate_url) {
298
+ $response = wp_remote_get(
299
+ sprintf(self::OMGF_GOOGLE_FONTS_API_URL . '%s', $family) . $query_string
300
+ );
301
+
302
+ // Try with mirror, if first request failed.
303
+ if (is_wp_error($response) && $response->get_error_code() == 'http_request_failed') {
304
+ $response = wp_remote_get(
305
+ sprintf(self::OMGF_GOOGLE_FONTS_API_FALLBACK . '%s', $family) . $query_string
306
+ );
307
+ }
308
+ } else {
309
+ $response = wp_remote_get(
310
+ sprintf($url . '%s', $family) . $query_string
311
+ );
312
  }
313
 
314
+ if (is_wp_error($response)) {
315
+ OMGF_Admin_Notice::set_notice(sprintf(__('OMGF encountered an error while trying to fetch fonts: %s', $this->plugin_text_domain), $response->get_error_message()), $response->get_error_code(), 'error', 408);
316
+ }
317
+
318
+ $response_code = wp_remote_retrieve_response_code($response);
319
+
320
+ if ($response_code != 200) {
321
+ $font_family = str_replace('-', ' ', $family);
322
+ $error_body = wp_remote_retrieve_body($response);
323
+ $error_message = wp_remote_retrieve_response_message($response);
324
+ $message = sprintf(__('OMGF couldn\'t find <strong>%s</strong> while parsing %s. The API returned the following error: %s.', $this->plugin_text_domain), ucwords($font_family), isset($_GET['omgf_optimize']) ? 'your homepage' : $_SERVER['REQUEST_URI'], is_wp_error($response) ? $response->get_error_message() : $error_message);
325
+
326
+ OMGF_Admin_Notice::set_notice($message, 'omgf_api_error', 'error');
327
 
328
+ if ($error_message == 'Service Unavailable') {
329
+ $message = __('OMGF\'s Google Fonts API is currently unavailable. Try again later.', $this->plugin_text_domain);
330
 
331
+ OMGF_Admin_Notice::set_notice($message, 'omgf_api_error', 'error', $response_code);
332
+ }
333
+
334
+ if ($error_body == 'Not found') {
335
+ $message = sprintf(__('Please verify that %s is available for free at Google Fonts by doing <a href="%s" target="_blank">a manual search</a>. Maybe it\'s a Premium font?', $this->plugin_text_domain), ucwords($font_family), 'https://fonts.google.com/?query=' . str_replace('-', '+', $family));
336
+
337
+ OMGF_Admin_Notice::set_notice($message, 'omgf_api_info_not_found', 'info');
338
+ }
339
+
340
+ if ($error_body == 'Internal Server Error') {
341
+ $message = sprintf(__('Try using the Force Subsets option (available in OMGF Pro) to force loading %s in a subset in which it\'s actually available. Use the Language filter <a href="%s" target="_blank">here</a> to verify which subsets are available for %s.', $this->plugin_text_domain), ucwords($font_family), 'https://fonts.google.com/?query=' . str_replace('-', '+', $family), ucwords($font_family));
342
+
343
+ OMGF_Admin_Notice::set_notice($message, 'omgf_api_info_internal_server_error', 'info');
344
+ }
345
+
346
+ return [];
347
  }
348
+
349
+ return json_decode(wp_remote_retrieve_body($response));
350
  }
351
 
352
  /**
353
+ * @param $font_families
354
+ * @param $font
355
  *
356
+ * @return mixed
357
+ */
358
+ private function build_fonts_request($font_families, $font)
359
+ {
360
+ $font_request = array_filter(
361
+ $font_families,
362
+ function ($value) use ($font) {
363
+ if (isset($font->early_access)) {
364
+ return strpos($value, strtolower(str_replace(' ', '', $font->family))) !== false;
365
+ }
366
+
367
+ return strpos($value, $font->family) !== false;
368
+ }
369
+ );
370
+
371
+ return reset($font_request);
372
+ }
373
+
374
+ /**
375
+ * @param $request
376
+ * @param $font
377
  *
 
378
  * @return array
379
  */
380
+ private function parse_requested_variants($request, $font)
381
  {
382
+ $requested_variants = array_filter(explode(',', $request));
383
+
384
+ /**
385
+ * This means by default all fonts are requested, so we need to fill up the queue, before unloading the unwanted variants.
386
+ */
387
+ if (count($requested_variants) == 0) {
388
+ foreach ($font->variants as $variant) {
389
+ $requested_variants[] = $variant->id;
390
+ }
391
+ }
392
 
393
+ return $requested_variants;
394
  }
395
 
396
  /**
 
397
  *
398
+ * @param mixed $font_id
399
+ * @param mixed $available
400
+ * @param mixed $wanted
401
+ * @param mixed $stylesheet_handle
402
+ * @return mixed
403
  */
404
+ private function process_unload_queue($font_id, $available, $wanted, $stylesheet_handle)
405
  {
406
+ if (strpos($wanted, ':') !== false) {
407
+ // We don't need the first variable.
408
+ list(, $variants) = explode(':', $wanted);
409
+ } else {
410
+ $variants = '';
411
+ }
412
+
413
+ /**
414
+ * Build array and filter out empty elements.
415
+ */
416
+ $variants = array_filter(explode(',', $variants));
417
+
418
+ /**
419
+ * If $variants is empty and this is the first run, i.e. there are no unloaded fonts (yet)
420
+ * return all available variants.
421
+ */
422
+ if (empty($variants) && !isset(OMGF::unloaded_fonts()[$stylesheet_handle][$font_id])) {
423
+ return $available;
424
+ }
425
+
426
+ return array_filter(
427
+ $available,
428
+ function ($font) use ($variants) {
429
+ $id = $font->id;
430
+
431
+ if ($id == 'regular' || $id == '400') {
432
+ return in_array('400', $variants) || in_array('regular', $variants);
433
+ }
434
+
435
+ if ($id == 'italic') {
436
+ return in_array('400italic', $variants) || in_array('italic', $variants);
437
+ }
438
+
439
+ return in_array($id, $variants);
440
+ }
441
+ );
442
+ }
443
+
444
+ /**
445
+ * When unload is used, insert the cache key in the font URLs for the variants still in use.
446
+ *
447
+ * @param array $all_stylesheets Contains all font styles, loaded and unloaded.
448
+ * @param array $current_stylesheet Contains just the loaded font styles of current stylesheet.
449
+ *
450
+ * @return mixed
451
+ */
452
+ private function rewrite_variants($all_stylesheets, $current_stylesheet)
453
+ {
454
+ foreach ($all_stylesheets as $stylesheet => &$fonts) {
455
+ foreach ($fonts as $index => &$font) {
456
+ if (empty((array) $font->variants)) {
457
+ continue;
458
+ }
459
+
460
+ foreach ($font->variants as $variant_index => &$variant) {
461
+ $replace_variant = $current_stylesheet[$stylesheet][$index]->variants[$variant_index] ?? (object) [];
462
+
463
+ if (!empty((array) $replace_variant)) {
464
+ $variant = $replace_variant;
465
+ }
466
+ }
467
+ }
468
+ }
469
+
470
+ return $all_stylesheets;
471
  }
472
  }
includes/class-stylesheet-generator.php CHANGED
@@ -12,8 +12,8 @@ defined('ABSPATH') || exit;
12
  *
13
  * @package : OMGF
14
  * @author : Daan van den Bergh
15
- * @copyright: (c) 2021 Daan van den Bergh
16
- * @url : https://daan.dev
17
  * * * * * * * * * * * * * * * * * * * */
18
 
19
  class OMGF_StylesheetGenerator
@@ -61,8 +61,8 @@ class OMGF_StylesheetGenerator
61
  * If Font Family's name was recently renamed, the old name should be used so no manual changes have to be made
62
  * to the stylesheet after processing.
63
  */
64
- $renamed_font_family = in_array($font->id, OMGF_API_Download::OMGF_RENAMED_GOOGLE_FONTS)
65
- ? array_search($font->id, OMGF_API_Download::OMGF_RENAMED_GOOGLE_FONTS)
66
  : '';
67
 
68
  foreach ($font->variants as $variant) {
12
  *
13
  * @package : OMGF
14
  * @author : Daan van den Bergh
15
+ * @copyright: © 2022 Daan van den Bergh
16
+ * @url : https://ffw.press
17
  * * * * * * * * * * * * * * * * * * * */
18
 
19
  class OMGF_StylesheetGenerator
61
  * If Font Family's name was recently renamed, the old name should be used so no manual changes have to be made
62
  * to the stylesheet after processing.
63
  */
64
+ $renamed_font_family = in_array($font->id, OMGF_Optimize::OMGF_RENAMED_GOOGLE_FONTS)
65
+ ? array_search($font->id, OMGF_Optimize::OMGF_RENAMED_GOOGLE_FONTS)
66
  : '';
67
 
68
  foreach ($font->variants as $variant) {
includes/class-uninstall.php CHANGED
@@ -10,8 +10,8 @@
10
  *
11
  * @package : OMGF
12
  * @author : Daan van den Bergh
13
- * @copyright: (c) 2021 Daan van den Bergh
14
- * @url : https://daan.dev
15
  * * * * * * * * * * * * * * * * * * * */
16
 
17
  defined('ABSPATH') || exit;
@@ -42,7 +42,7 @@ class OMGF_Uninstall
42
 
43
  $this->wpdb = $wpdb;
44
  $this->options = $settings->get_settings();
45
- $this->cacheDir = OMGF_FONTS_DIR;
46
 
47
  $this->remove_db_entries();
48
  $this->delete_files();
10
  *
11
  * @package : OMGF
12
  * @author : Daan van den Bergh
13
+ * @copyright: © 2022 Daan van den Bergh
14
+ * @url : https://ffw.press
15
  * * * * * * * * * * * * * * * * * * * */
16
 
17
  defined('ABSPATH') || exit;
42
 
43
  $this->wpdb = $wpdb;
44
  $this->options = $settings->get_settings();
45
+ $this->cacheDir = OMGF_CACHE_PATH;
46
 
47
  $this->remove_db_entries();
48
  $this->delete_files();
includes/frontend/class-functions.php DELETED
@@ -1,255 +0,0 @@
1
- <?php
2
- defined('ABSPATH') || exit;
3
-
4
- /* * * * * * * * * * * * * * * * * * * * *
5
- *
6
- * ██████╗ ███╗ ███╗ ██████╗ ███████╗
7
- * ██╔═══██╗████╗ ████║██╔════╝ ██╔════╝
8
- * ██║ ██║██╔████╔██║██║ ███╗█████╗
9
- * ██║ ██║██║╚██╔╝██║██║ ██║██╔══╝
10
- * ╚██████╔╝██║ ╚═╝ ██║╚██████╔╝██║
11
- * ╚═════╝ ╚═╝ ╚═╝ ╚═════╝ ╚═╝
12
- *
13
- * @package : OMGF
14
- * @author : Daan van den Bergh
15
- * @copyright: (c) 2021 Daan van den Bergh
16
- * @url : https://daan.dev
17
- * * * * * * * * * * * * * * * * * * * */
18
- class OMGF_Frontend_Functions
19
- {
20
- const OMGF_STYLE_HANDLE = 'omgf-fonts';
21
-
22
- /** @var bool $do_optimize */
23
- private $do_optimize;
24
-
25
- /** @var string $plugin_text_domain */
26
- private $plugin_text_domain = 'host-webfonts-local';
27
-
28
- /**
29
- * OMGF_Frontend_Functions constructor.
30
- */
31
- public function __construct()
32
- {
33
- $this->do_optimize = $this->maybe_optimize_fonts();
34
-
35
- if (!$this->do_optimize) {
36
- return;
37
- }
38
-
39
- add_action('wp_head', [$this, 'add_preloads'], 3);
40
- add_action('wp_print_styles', [$this, 'process_fonts'], PHP_INT_MAX - 1000);
41
- }
42
-
43
- /**
44
- * Should we optimize for logged in editors/administrators?
45
- *
46
- * @return bool
47
- */
48
- private function maybe_optimize_fonts()
49
- {
50
- /**
51
- * Allows us to quickly bypass fonts optimization.
52
- */
53
- if (isset($_GET['nomgf'])) {
54
- return false;
55
- }
56
-
57
- if (!OMGF_OPTIMIZE_EDIT_ROLES && current_user_can('edit_pages')) {
58
- return false;
59
- }
60
-
61
- return true;
62
- }
63
-
64
- /**
65
- * TODO: When setting all preloads at once (different stylesheet handles) combined with unloads, not all URLs are rewritten with their cache keys properly.
66
- * When configured handle by handle, it works fine. PHP multi-threading issues?
67
- */
68
- public function add_preloads()
69
- {
70
- $preloaded_fonts = apply_filters('omgf_frontend_preloaded_fonts', OMGF::preloaded_fonts());
71
-
72
- if (!$preloaded_fonts) {
73
- return;
74
- }
75
-
76
- $optimized_fonts = apply_filters('omgf_frontend_optimized_fonts', OMGF::optimized_fonts());
77
-
78
- /**
79
- * When OMGF Pro is enabled and set to Automatic mode, the merged handle is used to only load selected
80
- * preloads for the currently used stylesheet.
81
- *
82
- * @since v4.5.3 Added 2nd dummy parameter, to prevent Fatal Errors after updating.
83
- */
84
- $pro_handle = apply_filters('omgf_pro_merged_handle', '', '');
85
- $i = 0;
86
-
87
- foreach ($optimized_fonts as $stylesheet_handle => $font_faces) {
88
- if ($pro_handle && $stylesheet_handle != $pro_handle) {
89
- continue;
90
- }
91
-
92
- foreach ($font_faces as $font_face) {
93
- $preloads_stylesheet = $preloaded_fonts[$stylesheet_handle] ?? [];
94
-
95
- if (!in_array($font_face->id, array_keys($preloads_stylesheet))) {
96
- continue;
97
- }
98
-
99
- $font_id = $font_face->id;
100
- $preload_variants = array_filter(
101
- (array) $font_face->variants,
102
- function ($variant) use ($preloads_stylesheet, $font_id) {
103
- return in_array($variant->id, $preloads_stylesheet[$font_id]);
104
- }
105
- );
106
-
107
- foreach ($preload_variants as $variant) {
108
- $url = rawurldecode($variant->woff2);
109
- echo "<link id='omgf-preload-$i' rel='preload' href='$url' as='font' type='font/woff2' crossorigin />\n";
110
- $i++;
111
- }
112
- }
113
- }
114
- }
115
-
116
- /**
117
- * Check if the Remove Google Fonts option is enabled.
118
- */
119
- public function process_fonts()
120
- {
121
- if (is_admin()) {
122
- return;
123
- }
124
-
125
- if (apply_filters('omgf_pro_advanced_processing_enabled', false)) {
126
- return;
127
- }
128
-
129
- switch (OMGF_FONT_PROCESSING) {
130
- case 'remove':
131
- add_action('wp_print_styles', [$this, 'remove_registered_fonts'], PHP_INT_MAX - 500);
132
- break;
133
- default:
134
- add_action('wp_print_styles', [$this, 'replace_registered_stylesheets'], PHP_INT_MAX - 500);
135
- }
136
- }
137
-
138
- /**
139
- * This function contains a nice little hack, to avoid messing with potential dependency issues. We simply set the source to an empty string!
140
- */
141
- public function remove_registered_fonts()
142
- {
143
- global $wp_styles;
144
-
145
- $registered = $wp_styles->registered;
146
- $stylesheets = apply_filters('omgf_remove_detected_stylesheets', $this->detect_registered_stylesheets($registered));
147
-
148
- foreach ($stylesheets as $handle => $stylesheet) {
149
- $wp_styles->registered[$handle]->src = '';
150
- }
151
- }
152
-
153
- /**
154
- * Retrieve stylesheets from Google Fonts' API and modify the stylesheet for local storage.
155
- */
156
- public function replace_registered_stylesheets()
157
- {
158
- global $wp_styles;
159
-
160
- $registered = $wp_styles->registered;
161
- $stylesheets = apply_filters('omgf_replace_detected_stylesheets', $this->detect_registered_stylesheets($registered));
162
- $unloaded_stylesheets = OMGF::unloaded_stylesheets();
163
- $unloaded_fonts = OMGF::unloaded_fonts();
164
-
165
- foreach ($stylesheets as $handle => $stylesheet) {
166
- // If this stylesheet has been marked for unload, empty the src and skip out early.
167
- if (in_array($handle, $unloaded_stylesheets)) {
168
- $wp_styles->registered[$handle]->src = '';
169
-
170
- continue;
171
- }
172
-
173
- $updated_handle = $handle;
174
-
175
- if ($unloaded_fonts && $cache_key = OMGF::get_cache_key($handle)) {
176
- /**
177
- * @since v4.5.16 Since cache key returns an empty string if none is found, an extra
178
- * check is required to not accidentally overwrite the $updated_handle.
179
- */
180
- $updated_handle = $cache_key;
181
- }
182
-
183
- $cached_file = OMGF_CACHE_PATH . '/' . $updated_handle . "/$updated_handle.css";
184
-
185
- /**
186
- * Bail early if stylesheet already exists.
187
- */
188
- if (file_exists(WP_CONTENT_DIR . $cached_file)) {
189
- $wp_styles->registered[$handle]->src = content_url($cached_file);
190
-
191
- continue;
192
- }
193
-
194
- /**
195
- * For future reference: this logic can't be moved to backend, because there's no other way to properly access the
196
- * $wp_styles global.
197
- *
198
- * @see $wp_styles global
199
- */
200
- if (OMGF_OPTIMIZATION_MODE == 'manual' && isset($_GET['omgf_optimize'])) {
201
- $request = parse_url($stylesheet->src);
202
- $query = $request['query'] ?? '';
203
- $path = $request['path'] ?? '/css';
204
-
205
- parse_str($query, $query_array);
206
-
207
- if (empty($query_array)) {
208
- continue;
209
- }
210
-
211
- $params = http_build_query(
212
- array_merge(
213
- $query_array,
214
- [
215
- /**
216
- * @since v4.5.16 convert handle parameters to lowercase, to make sure the naming is
217
- * consistent across the board.
218
- */
219
- 'handle' => strtolower($updated_handle),
220
- 'original_handle' => strtolower($handle),
221
- '_wpnonce' => wp_create_nonce('wp_rest')
222
- ]
223
- )
224
- );
225
-
226
- /**
227
- * Use Home URL directly while building API request. This might prevent local development (non-SSL) issues.
228
- */
229
- $wp_styles->registered[$handle]->src = home_url('/wp-json/omgf/v1/download') . $path . '?' . $params;
230
- }
231
- }
232
- }
233
-
234
- /**
235
- * @param $registered_styles
236
- *
237
- * @return array
238
- */
239
- private function detect_registered_stylesheets($registered_styles)
240
- {
241
- $detected_stylesheets = array_filter(
242
- $registered_styles,
243
- function ($contents) {
244
- return strpos($contents->src, 'fonts.googleapis.com/css') !== false;
245
- }
246
- );
247
-
248
- OMGF::debug(sprintf(__('Found %s stylesheets containing Google Fonts: %s', $this->plugin_text_domain), count($detected_stylesheets), print_r($detected_stylesheets, true)));
249
-
250
- /**
251
- * @since v4.5.11 Added filter to allow adding additional stylesheets.
252
- */
253
- return apply_filters('omgf_detected_registered_stylesheets', $detected_stylesheets, $registered_styles);
254
- }
255
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
includes/frontend/class-process.php ADDED
@@ -0,0 +1,469 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ defined('ABSPATH') || exit;
3
+
4
+ /* * * * * * * * * * * * * * * * * * * * *
5
+ *
6
+ * ██████╗ ███╗ ███╗ ██████╗ ███████╗
7
+ * ██╔═══██╗████╗ ████║██╔════╝ ██╔════╝
8
+ * ██║ ██║██╔████╔██║██║ ███╗█████╗
9
+ * ██║ ██║██║╚██╔╝██║██║ ██║██╔══╝
10
+ * ╚██████╔╝██║ ╚═╝ ██║╚██████╔╝██║
11
+ * ╚═════╝ ╚═╝ ╚═╝ ╚═════╝ ╚═╝
12
+ *
13
+ * @package : OMGF
14
+ * @author : Daan van den Bergh
15
+ * @copyright: © 2022 Daan van den Bergh
16
+ * @url : https://ffw.press
17
+ * * * * * * * * * * * * * * * * * * * */
18
+ class OMGF_Frontend_Process
19
+ {
20
+ const RESOURCE_HINTS = ['fonts.googleapis.com', 'fonts.gstatic.com'];
21
+
22
+ /**
23
+ * @var array $page_builders Array of keys set by page builders when they're displaying their previews.
24
+ */
25
+ private $page_builders = [
26
+ 'bt-beaverbuildertheme',
27
+ 'ct_builder',
28
+ 'elementor-preview',
29
+ 'et_fb',
30
+ 'fb-edit',
31
+ 'fl_builder',
32
+ 'siteorigin_panels_live_editor',
33
+ 'tve',
34
+ 'vc_action'
35
+ ];
36
+
37
+ /**
38
+ * OMGF_Frontend_Functions constructor.
39
+ */
40
+ public function __construct()
41
+ {
42
+ add_action('template_redirect', [$this, 'maybe_buffer_output'], 3);
43
+ add_filter('omgf_buffer_output', [$this, 'parse']);
44
+ add_action('wp_head', [$this, 'add_preloads'], 3);
45
+ add_filter('wp_resource_hints', [$this, 'remove_resource_hints']);
46
+
47
+ /** Smart Slider 3 compatibility */
48
+ add_filter('wordpress_prepare_output', [$this, 'parse'], 11);
49
+ }
50
+
51
+ /**
52
+ * TODO: When setting all preloads at once (different stylesheet handles) combined with unloads, not all URLs are rewritten with their cache keys properly.
53
+ * When configured handle by handle, it works fine. PHP multi-threading issues?
54
+ */
55
+ public function add_preloads()
56
+ {
57
+ $preloaded_fonts = apply_filters('omgf_frontend_preloaded_fonts', OMGF::preloaded_fonts());
58
+
59
+ if (!$preloaded_fonts) {
60
+ return;
61
+ }
62
+
63
+ $optimized_fonts = apply_filters('omgf_frontend_optimized_fonts', OMGF::optimized_fonts());
64
+
65
+ /**
66
+ * When OMGF Pro is enabled and set to Automatic mode, the merged handle is used to only load selected
67
+ * preloads for the currently used stylesheet.
68
+ *
69
+ * @since v4.5.3 Added 2nd dummy parameter, to prevent Fatal Errors after updating.
70
+ */
71
+ $pro_handle = apply_filters('omgf_pro_merged_handle', '', '');
72
+ $i = 0;
73
+
74
+ foreach ($optimized_fonts as $stylesheet_handle => $font_faces) {
75
+ if ($pro_handle && $stylesheet_handle != $pro_handle) {
76
+ continue;
77
+ }
78
+
79
+ foreach ($font_faces as $font_face) {
80
+ $preloads_stylesheet = $preloaded_fonts[$stylesheet_handle] ?? [];
81
+
82
+ if (!in_array($font_face->id, array_keys($preloads_stylesheet))) {
83
+ continue;
84
+ }
85
+
86
+ $font_id = $font_face->id;
87
+ $preload_variants = array_filter(
88
+ (array) $font_face->variants,
89
+ function ($variant) use ($preloads_stylesheet, $font_id) {
90
+ return in_array($variant->id, $preloads_stylesheet[$font_id]);
91
+ }
92
+ );
93
+
94
+ foreach ($preload_variants as $variant) {
95
+ $url = rawurldecode($variant->woff2);
96
+ echo "<link id='omgf-preload-$i' rel='preload' href='$url' as='font' type='font/woff2' crossorigin />\n";
97
+ $i++;
98
+ }
99
+ }
100
+ }
101
+ }
102
+
103
+ /**
104
+ * We're downloading the fonts, so preconnecting to Google is a waste of time. Literally.
105
+ *
106
+ * @param array $urls
107
+ * @return array
108
+ */
109
+ public function remove_resource_hints($urls)
110
+ {
111
+ foreach ($urls as $key => &$url) {
112
+ if (is_array($url)) {
113
+ $url = $this->remove_resource_hints($url);
114
+
115
+ continue;
116
+ }
117
+
118
+ foreach (self::RESOURCE_HINTS as $hint) {
119
+ if (strpos($url, $hint) !== false) {
120
+ unset($urls[$key]);
121
+ }
122
+ }
123
+ }
124
+
125
+ return $urls;
126
+ }
127
+
128
+ /**
129
+ * Start output buffer.
130
+ *
131
+ * @action template_redirect
132
+ *
133
+ * @return void
134
+ */
135
+ public function maybe_buffer_output()
136
+ {
137
+ /**
138
+ * Allows us to quickly bypass fonts optimization.
139
+ */
140
+ if (isset($_GET['nomgf'])) {
141
+ return false;
142
+ }
143
+
144
+ /**
145
+ * Should we optimize for logged in Administrators/Editors?
146
+ */
147
+ if (!OMGF_OPTIMIZE_EDIT_ROLES && current_user_can('edit_pages')) {
148
+ return false;
149
+ }
150
+
151
+ /**
152
+ * Make sure Page Builder previews don't get optimized content.
153
+ */
154
+ foreach ($this->page_builders as $page_builder) {
155
+ if (array_key_exists($page_builder, $_GET)) {
156
+ return false;
157
+ }
158
+ }
159
+
160
+ /**
161
+ * Customizer previews shouldn't get optimized content.
162
+ */
163
+ if (function_exists('is_customize_preview') && is_customize_preview()) {
164
+ return false;
165
+ }
166
+
167
+ /**
168
+ * Let's GO!
169
+ */
170
+ ob_start([$this, 'return_buffer']);
171
+ }
172
+
173
+ /**
174
+ * Returns the buffer for filtering, so page cache doesn't break.
175
+ *
176
+ * @since v5.0.0 Tested with:
177
+ * - Cache Enabler v1.8.7
178
+ * - Default Settings
179
+ * - LiteSpeed Cache
180
+ * - Don't know (Gal Baras tested it: @see https://wordpress.org/support/topic/completely-broke-wp-rocket-plugin/#post-15377538)
181
+ * - W3 Total Cache v2.2.1:
182
+ * - Page Cache: Disk (basic)
183
+ * - Database/Object Cache: Off
184
+ * - JS/CSS minify/combine: On
185
+ * - WP Fastest Cache v0.9.5
186
+ * - JS/CSS minify/combine: On
187
+ * - Page Cache: On
188
+ * - WP Rocket v3.8.8:
189
+ * - Page Cache: Enabled
190
+ * - JS/CSS minify/combine: Enabled
191
+ * - WP Super Cache v1.7.4
192
+ * - Page Cache: Enabled
193
+ *
194
+ * @todo Not tested (yet):
195
+ * - Asset Cleanup Pro
196
+ * - Kinsta Cache (Same as Cache Enabler?)
197
+ * - Swift Performance
198
+ *
199
+ * @return void
200
+ */
201
+ public function return_buffer($html)
202
+ {
203
+ if (!$html) {
204
+ return $html;
205
+ }
206
+
207
+ return apply_filters('omgf_buffer_output', $html);
208
+ }
209
+
210
+ /**
211
+ * This method uses Regular Expressions to parse the HTML. It's tested to be at least
212
+ * twice as fast compared to using Xpath.
213
+ *
214
+ * Test results (in seconds, with XDebug enabled)
215
+ *
216
+ * Uncached: 17.81094789505
217
+ * 18.687641859055
218
+ * 18.301512002945
219
+ * Cached: 0.00046515464782715
220
+ * 0.00037288665771484
221
+ * 0.00053095817565918
222
+ *
223
+ * Using Xpath proved to be untestable, because it varied anywhere between 38 seconds and, well, timeouts.
224
+ *
225
+ * @param string $html
226
+ *
227
+ * @return string
228
+ */
229
+ public function parse($html)
230
+ {
231
+ preg_match_all('/<link.*fonts\.googleapis\.com\/css.*?[\/]?>/', $html, $links);
232
+
233
+ if (!isset($links[0]) || empty($links[0])) {
234
+ return $html;
235
+ }
236
+
237
+ $google_fonts = $this->build_fonts_set($links[0]);
238
+ $search_replace = $this->build_search_replace($google_fonts);
239
+
240
+ if (empty($search_replace['search']) || empty($search_replace['replace'])) {
241
+ return $html;
242
+ }
243
+
244
+ $html = str_replace($search_replace['search'], $search_replace['replace'], $html);
245
+
246
+ return apply_filters('omgf_processed_html', $html, $this);
247
+ }
248
+
249
+ /**
250
+ * Builds a processable array of Google Fonts' ID and (external) URL.
251
+ *
252
+ * @param array $links
253
+ * @param string $handle If an ID attribute is not defined, this will be used instead.
254
+ *
255
+ * @return array [ 0 => [ 'id' => (string), 'href' => (string) ] ]
256
+ */
257
+ public function build_fonts_set($links, $handle = 'omgf-stylesheet')
258
+ {
259
+ $google_fonts = [];
260
+
261
+ OMGF::debug(sprintf(__('Building fonts set for handle %s, using $s', 'host-webfonts-local'), $handle, print_r($links, true)));
262
+
263
+ foreach ($links as $key => $link) {
264
+ preg_match('/id=[\'"](?P<id>.*?)[\'"]/', $link, $id);
265
+
266
+ $id = $id['id'] ?? "$handle-$key";
267
+
268
+ preg_match('/href=[\'"](?P<href>.*?)[\'"]/', $link, $href);
269
+
270
+ if (!isset($href['href'])) {
271
+ continue;
272
+ }
273
+
274
+ $google_fonts[$key]['id'] = $id;
275
+ $google_fonts[$key]['href'] = $href['href'];
276
+ }
277
+
278
+ OMGF::debug(sprintf(__('Built set: %s', 'host-webfonts-local'), print_r($google_fonts, true)));
279
+
280
+ return $google_fonts;
281
+ }
282
+
283
+ /**
284
+ * Build a Search/Replace array for all found Google Fonts.
285
+ *
286
+ * @param mixed $google_fonts A processable set generated by $this->build_fonts_set().
287
+ *
288
+ * @return array
289
+ *
290
+ * @throws SodiumException
291
+ * @throws SodiumException
292
+ * @throws TypeError
293
+ * @throws TypeError
294
+ * @throws TypeError
295
+ */
296
+ public function build_search_replace($google_fonts)
297
+ {
298
+ $search = [];
299
+ $replace = [];
300
+
301
+ OMGF::debug(__('Building Search/Replace set...', 'host-webfonts-local'));
302
+
303
+ foreach ($google_fonts as $key => $stack) {
304
+ $handle = $stack['id'];
305
+
306
+ /**
307
+ * If stylesheet with $handle is completely marked for unload, just clean the 'href'
308
+ * attribute to prevent it from loading.
309
+ */
310
+ if (OMGF::unloaded_stylesheets() && in_array($handle, OMGF::unloaded_stylesheets())) {
311
+ $search[$key] = $stack['href'];
312
+ $replace[$key] = '';
313
+
314
+ continue;
315
+ }
316
+
317
+ /**
318
+ * $cache_key is used for caching. $handle contains the original handle.
319
+ */
320
+ if ((OMGF::unloaded_fonts() && $cache_key = OMGF::get_cache_key($stack['id']))
321
+ || apply_filters('omgf_frontend_update_cache_key', false)
322
+ ) {
323
+ $handle = $cache_key;
324
+ }
325
+
326
+ /**
327
+ * Regular requests (in the frontend) will end here if the file exists.
328
+ */
329
+ if (!isset($_GET['omgf_optimize']) && file_exists(OMGF_CACHE_PATH . "/$handle/$handle.css")) {
330
+ $search[$key] = $stack['href'];
331
+ $replace[$key] = content_url(OMGF_CACHE_DIR . "/$handle/$handle.css");
332
+
333
+ continue;
334
+ }
335
+
336
+ $api_url = $this->build_request_url(urldecode($stack['href']), $handle, $stack['id']);
337
+ $api_params = parse_url($api_url);
338
+
339
+ parse_str($api_params['query'], $post_query);
340
+
341
+ if (isset($api_params['fragment'])) {
342
+ parse_str($api_params['fragment'], $additional_query);
343
+
344
+ $post_query = array_merge($post_query, $additional_query);
345
+ }
346
+
347
+ /**
348
+ * Required parameters.
349
+ */
350
+ if (!isset($post_query['family']) || !isset($post_query['handle']) || !isset($post_query['original_handle'])) {
351
+ continue;
352
+ }
353
+
354
+ $optimize = new OMGF_Optimize($post_query['family'], $post_query['handle'], $post_query['original_handle'], $post_query['subset'] ?? '');
355
+ $cached_url = $optimize->process();
356
+
357
+ if (!$cached_url) {
358
+ continue;
359
+ }
360
+
361
+ $search[$key] = $stack['href'];
362
+ $replace[$key] = $cached_url;
363
+ }
364
+
365
+ return ['search' => $search, 'replace' => $replace];
366
+ }
367
+
368
+ /**
369
+ * The generated request URL includes all required parameters for OMGF's Download API.
370
+ *
371
+ * @param string $url e.g. https://fonts.googleapis.com/css?family=Open+Sans:100,200,300|Roboto:100,200,300 etc.
372
+ * @param string $updated_handle e.g. example-handle-xvfdo
373
+ * @param string $handle e.g. example-handle
374
+ *
375
+ * @return string
376
+ */
377
+ public function build_request_url($url, $updated_handle, $handle)
378
+ {
379
+ $parsed_url = parse_url($url);
380
+ $query = $parsed_url['query'] ?? '';
381
+
382
+ if ($parsed_url['path'] == '/css2') {
383
+ // Request to fonts.googleapis.com/css2?etc.
384
+ $original_query = $this->parse_css2($query);
385
+ } elseif (strpos($parsed_url['path'], 'earlyaccess') !== false) {
386
+ // Request to https://fonts.googleapis.com/earlyaccess/etc. should be left for OMGF Pro to deal with.
387
+ $original_query = ['family' => ''];
388
+ } else {
389
+ /**
390
+ * Request to fonts.googleapis.com/css?etc. (default)
391
+ *
392
+ * Decode, just to be sure.
393
+ */
394
+ parse_str(html_entity_decode($query), $original_query);
395
+ }
396
+
397
+ $params = http_build_query(
398
+ array_merge(
399
+ $original_query,
400
+ [
401
+ 'handle' => $updated_handle,
402
+ 'original_handle' => $handle,
403
+ ]
404
+ )
405
+ );
406
+
407
+ $request = 'https://fonts.googleapis.com/css?' . $params;
408
+
409
+ return apply_filters('omgf_request_url', $request);
410
+ }
411
+
412
+ /**
413
+ * Convert CSS2 query to regular CSS API query.
414
+ *
415
+ * @param string $query
416
+ *
417
+ * @return array
418
+ */
419
+ private function parse_css2($query)
420
+ {
421
+ // array_filter() removes empty elements.
422
+ $families = array_filter(explode('&', $query));
423
+
424
+ foreach ($families as $param) {
425
+ if (strpos($param, 'family') === false) {
426
+ continue;
427
+ }
428
+
429
+ parse_str($param, $parts);
430
+
431
+ $font_families[] = $parts['family'];
432
+ }
433
+
434
+ if (empty($font_families)) {
435
+ return $query;
436
+ }
437
+
438
+ $weights = '';
439
+
440
+ foreach ($font_families as $font_family) {
441
+ if (strpos($font_family, ':') !== false) {
442
+ list($family, $weights) = explode(':', $font_family);
443
+ } else {
444
+ $family = $font_family;
445
+ $weights = '';
446
+ }
447
+
448
+ /**
449
+ * @var array|string $weights [ '300', '400', '500', etc. ] | ''
450
+ */
451
+ $weights = strpos($weights, ';') !== false ? explode(';', substr($weights, strpos($weights, '@') + 1)) : '';
452
+
453
+ if (!$weights) {
454
+ $fonts[] = $family;
455
+
456
+ continue;
457
+ }
458
+
459
+ foreach ($weights as &$weight) {
460
+ $properties = explode(',', $weight);
461
+ $weight = $properties[0] == '1' && isset($properties[1]) ? $properties[1] . 'italic' : ($properties[0] != '0' ? $properties[0] : $properties[1]);
462
+ }
463
+
464
+ $fonts[] = $family . ':' . implode(',', $weights);
465
+ }
466
+
467
+ return ['family' => implode('|', $fonts)];
468
+ }
469
+ }
includes/optimization-mode/class-manual.php DELETED
@@ -1,271 +0,0 @@
1
- <?php
2
- defined('ABSPATH') || exit;
3
-
4
- /* * * * * * * * * * * * * * * * * * * * *
5
- *
6
- * ██████╗ ███╗ ███╗ ██████╗ ███████╗
7
- * ██╔═══██╗████╗ ████║██╔════╝ ██╔════╝
8
- * ██║ ██║██╔████╔██║██║ ███╗█████╗
9
- * ██║ ██║██║╚██╔╝██║██║ ██║██╔══╝
10
- * ╚██████╔╝██║ ╚═╝ ██║╚██████╔╝██║
11
- * ╚═════╝ ╚═╝ ╚═╝ ╚═════╝ ╚═╝
12
- *
13
- * @package : OMGF
14
- * @author : Daan van den Bergh
15
- * @copyright: (c) 2021 Daan van den Bergh
16
- * @url : https://daan.dev
17
- * * * * * * * * * * * * * * * * * * * */
18
-
19
- class OMGF_OptimizationMode_Manual
20
- {
21
- /** @var string */
22
- private $plugin_text_domain = 'host-webfonts-local';
23
-
24
- /**
25
- * Build class.
26
- *
27
- * @return void
28
- */
29
- public function __construct()
30
- {
31
- $this->run();
32
- }
33
-
34
- /**
35
- * Run Force mode.
36
- *
37
- * @return void
38
- */
39
- private function run()
40
- {
41
- $url = esc_url_raw(OMGF_MANUAL_OPTIMIZE_URL);
42
- $front_html = $this->get_front_html($url);
43
- $error = false;
44
-
45
- if (is_wp_error($front_html) || wp_remote_retrieve_response_code($front_html) != 200) {
46
- $this->frontend_fetch_failed($front_html);
47
-
48
- $error = true;
49
- }
50
-
51
- $api_request_urls = [];
52
- $document = new DOMDocument();
53
-
54
- libxml_use_internal_errors(true);
55
- @$document->loadHtml(wp_remote_retrieve_body($front_html));
56
-
57
- foreach ($document->getElementsByTagName('link') as $link) {
58
- /** @var DOMElement $link */
59
- if ($link->hasAttribute('href') && strpos($link->getAttribute('href'), '/omgf/v1/download/')) {
60
- $api_request_urls[] = $link->getAttribute('href');
61
- }
62
- }
63
-
64
- if (empty($api_request_urls)) {
65
- $this->no_urls_found();
66
-
67
- $error = true;
68
- }
69
-
70
- foreach ($api_request_urls as $url) {
71
- if (strpos($url, 'css2') !== false) {
72
- $url = $this->convert($url);
73
- }
74
-
75
- $download = $this->do_rest_request($url);
76
-
77
- /** @var WP_REST_Response $download */
78
- if ($download->is_error()) {
79
- $this->download_failed($download);
80
-
81
- $error = true;
82
- }
83
- }
84
-
85
- if (!$error) {
86
- $this->optimization_succeeded();
87
- }
88
- }
89
-
90
-
91
- /**
92
- * Converts requests to Google's Variable Fonts (CSS2) API to the 'old' (CSS) API.
93
- *
94
- * @param string $css2_url
95
- */
96
- private function convert($css2_url)
97
- {
98
- $parsed_url = parse_url($css2_url);
99
- $query = $parsed_url['query'];
100
- parse_str($query, $params);
101
- $raw_params = explode('&', $query);
102
- $font_families = [];
103
- $fonts = [];
104
-
105
- foreach ($raw_params as $param) {
106
- if (strpos($param, 'family') === false) {
107
- continue;
108
- }
109
-
110
- parse_str($param, $parts);
111
-
112
- $font_families[] = $parts['family'];
113
- }
114
-
115
- if (empty($font_families)) {
116
- return $css2_url;
117
- }
118
-
119
- foreach ($font_families as $font_family) {
120
- if (strpos($font_family, ':') !== false) {
121
- list($family, $weights) = explode(':', $font_family);
122
- } else {
123
- $family = $font_family;
124
- $weights = '';
125
- }
126
-
127
- /**
128
- * @return array [ '300', '400', '500', etc. ]
129
- */
130
- $weights = explode(';', substr($weights, strpos($weights, '@') + 1));
131
-
132
- foreach ($weights as &$weight) {
133
- $properties = explode(',', $weight);
134
- $weight = $properties[0] == '1' ? $properties[1] . 'italic' : $properties[1];
135
- }
136
-
137
- $fonts[] = $family . ':' . implode(',', $weights);
138
- }
139
-
140
- $params['family'] = implode('|', $fonts);
141
-
142
- return $parsed_url['scheme'] . '://' . $parsed_url['host'] . $parsed_url['path'] . '?' . http_build_query($params);
143
- }
144
-
145
- /**
146
- * @param string $url
147
- *
148
- * @return WP_REST_Response
149
- */
150
- private function do_rest_request($url)
151
- {
152
- $parsed_url = parse_url($url);
153
- $request = new WP_REST_Request('GET', str_replace('/wp-json', '', $parsed_url['path']));
154
-
155
- parse_str($parsed_url['query'], $query_params);
156
-
157
- if (isset($query_params['_wpnonce'])) {
158
- unset($query_params['_wpnonce']);
159
- }
160
-
161
- $request->set_query_params($query_params);
162
-
163
- // TODO: Find out proper WP way to add this param to request.
164
- $_REQUEST['_wpnonce'] = wp_create_nonce('wp_rest');
165
-
166
- return rest_do_request($request);
167
- }
168
-
169
- /**
170
- * @return void
171
- */
172
- private function optimization_succeeded()
173
- {
174
- add_settings_error('general', 'omgf_optimization_success', __('Optimization completed successfully.'), 'success');
175
-
176
- OMGF_Admin_Notice::set_notice(
177
- __('If you\'re using any 3rd party optimization plugins (e.g. WP Rocket, Autoptimize, W3 Total Cache, etc.) make sure to flush their caches for OMGF\'s optimizations to take effect.', $this->plugin_text_domain),
178
- 'omgf-cache-notice',
179
- false,
180
- 'warning'
181
- );
182
- }
183
-
184
- /**
185
- * @param $response WP_REST_Response
186
- */
187
- private function download_failed($response)
188
- {
189
- add_settings_error('general', 'omgf_download_failed', __('OMGF encountered an error while downloading Google Fonts', $this->plugin_text_domain) . ': ' . $this->get_error_code($response) . ' - ' . $this->get_error_message($response), 'error');
190
- }
191
-
192
- /**
193
- * @param $response WP_Error|array
194
- */
195
- private function frontend_fetch_failed($response)
196
- {
197
- add_settings_error('general', 'omgf_frontend_fetch_failed', __('OMGF encountered an error while fetching this site\'s frontend HTML', $this->plugin_text_domain) . ': ' . $this->get_error_code($response) . ' - ' . $this->get_error_message($response), 'error');
198
- }
199
-
200
- /**
201
- * @return void
202
- */
203
- private function no_urls_found()
204
- {
205
- add_settings_error('general', 'omgf_no_urls_found', sprintf(__('No (additional) Google Fonts found to optimize. If you believe this is an error, please refer to the %stroubleshooting%s section of the documentation for possible solutions.', $this->plugin_text_domain), '<a href="https://docs.ffw.press/category/37-omgf-pro---troubleshooting">', '</a>'), 'info');
206
- }
207
-
208
- /**
209
- * Wrapper for wp_remote_get() with preset params.
210
- *
211
- * @param mixed $url
212
- * @return array|WP_Error
213
- */
214
- private function get_front_html($url)
215
- {
216
- return wp_remote_get(
217
- $this->no_cache_optimize_url($url),
218
- [
219
- 'timeout' => 30
220
- ]
221
- );
222
- }
223
-
224
- /**
225
- * @param $url
226
- *
227
- * @return string
228
- */
229
- private function no_cache_optimize_url($url)
230
- {
231
- return add_query_arg(['omgf_optimize' => 1, 'nocache' => substr(md5(microtime()), rand(0, 26), 5)], $url);
232
- }
233
-
234
- /**
235
- * @param WP_REST_Response|WP_Error|array $response
236
- *
237
- * @return int|string
238
- */
239
- private function get_error_code($response)
240
- {
241
- if ($response instanceof WP_REST_Response && $response->is_error()) {
242
- // Convert to WP_Error if WP_REST_Response
243
- $response = $response->as_error();
244
- }
245
-
246
- if (is_wp_error($response)) {
247
- return $response->get_error_code();
248
- }
249
-
250
- return wp_remote_retrieve_response_code($response);
251
- }
252
-
253
- /**
254
- * @param WP_REST_Response|WP_Error|array $response
255
- *
256
- * @return int|string
257
- */
258
- private function get_error_message($response)
259
- {
260
- if ($response instanceof WP_REST_Response && $response->is_error()) {
261
- // Convert to WP_Error if WP_REST_Response
262
- $response = $response->as_error();
263
- }
264
-
265
- if (is_wp_error($response)) {
266
- return $response->get_error_message();
267
- }
268
-
269
- return wp_remote_retrieve_response_message($response);
270
- }
271
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
includes/optimize/class-run.php ADDED
@@ -0,0 +1,146 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ defined('ABSPATH') || exit;
3
+
4
+ /* * * * * * * * * * * * * * * * * * * * *
5
+ *
6
+ * ██████╗ ███╗ ███╗ ██████╗ ███████╗
7
+ * ██╔═══██╗████╗ ████║██╔════╝ ██╔════╝
8
+ * ██║ ██║██╔████╔██║██║ ███╗█████╗
9
+ * ██║ ██║██║╚██╔╝██║██║ ██║██╔══╝
10
+ * ╚██████╔╝██║ ╚═╝ ██║╚██████╔╝██║
11
+ * ╚═════╝ ╚═╝ ╚═╝ ╚═════╝ ╚═╝
12
+ *
13
+ * @package : OMGF
14
+ * @author : Daan van den Bergh
15
+ * @copyright: © 2022 Daan van den Bergh
16
+ * @url : https://ffw.press
17
+ * * * * * * * * * * * * * * * * * * * */
18
+
19
+ class OMGF_Optimize_Run
20
+ {
21
+ /** @var string */
22
+ private $plugin_text_domain = 'host-webfonts-local';
23
+
24
+ /**
25
+ * Build class.
26
+ *
27
+ * @return void
28
+ */
29
+ public function __construct()
30
+ {
31
+ $this->run();
32
+ }
33
+
34
+ /**
35
+ * Does a quick fetch to the site_url to trigger all the action.
36
+ *
37
+ * @return void
38
+ */
39
+ private function run()
40
+ {
41
+ $front_html = $this->get_front_html(get_site_url());
42
+ $error = false;
43
+
44
+ if (is_wp_error($front_html) || wp_remote_retrieve_response_code($front_html) != 200) {
45
+ $this->frontend_fetch_failed($front_html);
46
+
47
+ $error = true;
48
+ }
49
+
50
+ if (!$error) {
51
+ $this->optimization_succeeded();
52
+ }
53
+ }
54
+
55
+ /**
56
+ * Wrapper for wp_remote_get() with preset params.
57
+ *
58
+ * @param mixed $url
59
+ * @return array|WP_Error
60
+ */
61
+ private function get_front_html($url)
62
+ {
63
+ return wp_remote_get(
64
+ $this->no_cache_optimize_url($url),
65
+ [
66
+ 'timeout' => 60
67
+ ]
68
+ );
69
+ }
70
+
71
+ /**
72
+ * @param $url
73
+ *
74
+ * @return string
75
+ */
76
+ private function no_cache_optimize_url($url)
77
+ {
78
+ return add_query_arg(['omgf_optimize' => 1, 'nocache' => substr(md5(microtime()), rand(0, 26), 5)], $url);
79
+ }
80
+
81
+ /**
82
+ * @return void
83
+ */
84
+ private function optimization_succeeded()
85
+ {
86
+ if (count(get_settings_errors())) {
87
+ global $wp_settings_errors;
88
+
89
+ $wp_settings_errors = [];
90
+ }
91
+
92
+ add_settings_error('general', 'omgf_optimization_success', __('Optimization completed successfully.'), 'success');
93
+
94
+ OMGF_Admin_Notice::set_notice(
95
+ __('If you\'re using any 3rd party optimization plugins (e.g. WP Rocket, Autoptimize, W3 Total Cache, etc.) make sure to flush their caches for OMGF\'s optimizations to take effect.', $this->plugin_text_domain),
96
+ 'omgf-cache-notice',
97
+ 'warning'
98
+ );
99
+ }
100
+
101
+ /**
102
+ * @param $response WP_Error|array
103
+ */
104
+ private function frontend_fetch_failed($response)
105
+ {
106
+ add_settings_error('general', 'omgf_frontend_fetch_failed', __('OMGF encountered an error while fetching this site\'s frontend HTML', $this->plugin_text_domain) . ': ' . $this->get_error_code($response) . ' - ' . $this->get_error_message($response), 'error');
107
+ }
108
+
109
+ /**
110
+ * @param WP_REST_Response|WP_Error|array $response
111
+ *
112
+ * @return int|string
113
+ */
114
+ private function get_error_code($response)
115
+ {
116
+ if ($response instanceof WP_REST_Response && $response->is_error()) {
117
+ // Convert to WP_Error if WP_REST_Response
118
+ $response = $response->as_error();
119
+ }
120
+
121
+ if (is_wp_error($response)) {
122
+ return $response->get_error_code();
123
+ }
124
+
125
+ return wp_remote_retrieve_response_code($response);
126
+ }
127
+
128
+ /**
129
+ * @param WP_REST_Response|WP_Error|array $response
130
+ *
131
+ * @return int|string
132
+ */
133
+ private function get_error_message($response)
134
+ {
135
+ if ($response instanceof WP_REST_Response && $response->is_error()) {
136
+ // Convert to WP_Error if WP_REST_Response
137
+ $response = $response->as_error();
138
+ }
139
+
140
+ if (is_wp_error($response)) {
141
+ return $response->get_error_message();
142
+ }
143
+
144
+ return wp_remote_retrieve_response_message($response);
145
+ }
146
+ }
readme.md CHANGED
@@ -7,47 +7,43 @@ OMGF automagically caches the Google Fonts used by your theme/plugins locally. N
7
  > How could using fonts via Google's service possibly run afoul of GDPR? The fact of the matter is that, when a font is requested by the user's browser, their IP is logged by Google and used for analytics.
8
  > — Lifehacker
9
 
10
- Leverage Browser Cache, Minimize DNS requests and serve your Google Fonts in a 100% GDPR compliant way with OMGF!
11
 
12
  OMGF is written with performance and user-friendliness in mind. It uses the Google Fonts Helper API to automatically cache the fonts your theme and plugins use to **minimize DNS requests** and speed up your WordPress website.
13
 
14
- ### How Does It Work?
15
 
16
- After installing the plugin, OMGF runs silently in the background and captures any requests made to fonts.googleapis.com or fonts.gstatic.com. When a webpage is first loaded, it reroutes these requests to its own Download API and copies the fonts over to your server. Then it generates a stylesheet for your fonts including EOT, TTF, WOFF and WOFF2 formats to guarantee maximum cross browser compatibility!
17
 
18
- When the fonts are downloaded and the stylesheet is generated, it rewrites every URL pointing to fonts.googleapis.com or fonts.gstatic.com to the locally hosted variant.
19
 
20
- Please keep in mind that, although I try to make the configuration of this plugin as easy as possible, the concept of locally hosting a file or optimizing Google Fonts for *Pagespeed Insights* or *GT Metrix* has proven to be confusing for some people. If you're not sure of what your doing, please consult a SEO expert or Webdeveloper to help you with the configuration of this plugin or [hire me to do it for you](https://ffw.press/wordpress/omgf-expert-configuration/).
 
 
 
21
 
22
- ### Features
23
- - Automatically replace registered/enqueued Google Fonts in wp_head() with local copies,
24
- - Automatically remove registered/enqueued Google Fonts from wp_head(),
25
- - Manage Optimized Google Fonts,
26
- - Preload above the fold fonts,
27
- - Don't load certain fonts or entire stylesheets.
28
- - Leverage the font-display (swap) option.
29
 
30
- ### Features in the PRO version
31
- Everything in the free version, plus:
32
- - Specify a Fallback Font Stack for every Google Font, to reduce Cumulative Layout Shift,
33
- - Automatically remove/replace all Google Fonts throughout the entire document/page,
34
- - Also supports WebFont Loader (webfont.js), Early Access Google Fonts and requests in stylesheets using @import and @font-face statements.
35
- - Automatically generate different stylesheets for pages with different Google Fonts configurations.
 
 
 
 
 
36
  - Material Icons support.
37
- - Combine all Google Fonts stylesheets (requested by your theme and/or plugins) into one file,
38
- - Deduplicate Google Fonts stylesheets,
39
- - Rewrite stylesheets added by other plugins and/or themes to include the configured font-display (e.g. swap) option, this will remove *the ensure text remains visible during webfont load* optimization suggestion from Google PageSpeed Insights,
40
- - Define file types to include in stylesheet (WOFF, WOFF2, EOT, TTF, SVG),
41
- - Reduce loading time and page size, by forcing the used subset(s) for all Google Fonts requests,
42
- - Remove Resource Hints (preload, preconnect, dns-prefetch) pointing to fonts.googleapis.com or fonts.gstatic.com,
43
- - Modify `src` attribute for fonts in stylesheet using the Fonts Source URL option to fully integrate with your configuration,
44
  - Use this to serve fonts and the stylesheets from your CDN, or
45
  - To serve fonts from an alternative path (e.g. when you're using Security through Obscurity plugins like WP Hide, etc.), or
 
46
  - Anything you like!
47
  - Proper handling for AMP pages (Fallback to or remove Google Fonts).
48
 
49
- **[Documentation](https://docs.ffw.press/category/4-omgf-pro/) | [Purchase OMGF Pro](https://ffw.press/wordpress/omgf-pro/)**
50
-
51
 
52
  ## Installation
53
 
@@ -65,7 +61,7 @@ Everything in the free version, plus:
65
 
66
  ## Frequently Asked Questions
67
 
68
- Visit the [FAQ at Wordpress.org](https://wordpress.org/plugins/host-webfonts-local/#faq)
69
 
70
  ## Support
71
 
7
  > How could using fonts via Google's service possibly run afoul of GDPR? The fact of the matter is that, when a font is requested by the user's browser, their IP is logged by Google and used for analytics.
8
  > — Lifehacker
9
 
10
+ **Leverage Browser Cache**, **reduce DNS lookups/requests**, **reduce Cumulative Layout Shift** and make your Google Fonts **100% GDPR compliant** with OMGF!
11
 
12
  OMGF is written with performance and user-friendliness in mind. It uses the Google Fonts Helper API to automatically cache the fonts your theme and plugins use to **minimize DNS requests** and speed up your WordPress website.
13
 
14
+ ## How Does It Work?
15
 
16
+ After installing the plugin, OMGF will automatically start looking for Google Fonts whenever a page is requested on your website.
17
 
18
+ All Google Fonts are listed in the **Manage Optimized Fonts** section of OMGF's settings screen. There, you can choose to:
19
 
20
+ - *Preload* fonts to **reduce Cumulative Layout Shift** above the fold,
21
+ - *Unload* fonts that're not used by you, your theme and/or plugins,
22
+ - Set a *Fallback Font Stack* (OMGF Pro required), to further **reduce Cumulative Layout Shift**, or
23
+ - *Replace* (OMGF Pro required) font-families with system fonts to **speed up page loading times**!
24
 
25
+ ### Other Features include
 
 
 
 
 
 
26
 
27
+ - **Remove Resource Hints** (preload, preconnect, dns-prefetch) pointing to `fonts.googleapis.com` or `fonts.gstatic.com`,
28
+ - **Ensure text remains visible during webfont load** by forcing the *font-display* attribute to your Google Fonts,
29
+ - **Ensure text remains visible during webfont load** by forcing the *font-display* attribute to all your other fonts! (OMGF Pro required),
30
+ - **Reduce the filesize** of your fonts and stylesheets, by using the *Force subset* and *Include File Types* feature (OMGF Pro required),
31
+
32
+ ### Additional Features in OMGF Pro
33
+ - "Dig deeper" to find Google Fonts and optimize further. OMGF Pro supports:
34
+ - `@font-face` and `@import` statements inside **inline `<style>` blocks**,
35
+ - `@font-face` and `@import` statements inside **local stylesheets** loaded by e.g. your theme and/or plugins,
36
+ - Web Font Loader (`webfont.js`),
37
+ - Early Access Google Fonts.
38
  - Material Icons support.
39
+ - Modify your fonts' `src: url()` attribute to fully integrate with your configuration,
 
 
 
 
 
 
40
  - Use this to serve fonts and the stylesheets from your CDN, or
41
  - To serve fonts from an alternative path (e.g. when you're using Security through Obscurity plugins like WP Hide, etc.), or
42
+ - Set a relative path to easily migrate from development/staging areas to production/live, or
43
  - Anything you like!
44
  - Proper handling for AMP pages (Fallback to or remove Google Fonts).
45
 
46
+ *[Purchase OMGF Pro](https://ffw.press/wordpress/omgf-pro/) | [Documentation](https://docs.ffw.press/category/4-omgf-pro/) | [Tested Plugins & Themes](https://docs.ffw.press/article/40-list-of-compatible-themes-and-plugins-omgf-pro)*
 
47
 
48
  ## Installation
49
 
61
 
62
  ## Frequently Asked Questions
63
 
64
+ For the FAQ, [click here](https://docs.ffw.press/category/76-omgf-pro---faq).
65
 
66
  ## Support
67
 
readme.txt CHANGED
@@ -3,7 +3,7 @@ Contributors: DaanvandenBergh
3
  Tags: google, fonts, gdpr, cache, speed, preload, font-display, webfonts, subsets, remove, minimize, external, requests
4
  Requires at least: 4.6
5
  Tested up to: 5.9
6
- Stable tag: 4.6.0
7
  Requires PHP: 7.0
8
  License: GPLv2 or later
9
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
@@ -15,48 +15,39 @@ OMGF automagically caches the Google Fonts used by your theme/plugins locally. N
15
  > How could using fonts via Google's service possibly run afoul of GDPR? The fact of the matter is that, when a font is requested by the user's browser, their IP is logged by Google and used for analytics.
16
  > — Lifehacker
17
 
18
- Leverage Browser Cache, Minimize DNS requests, reduce Cumulative Layout Shift and serve your Google Fonts in a 100% GDPR compliant way with OMGF!
19
 
20
  OMGF is written with performance and user-friendliness in mind. It uses the Google Fonts Helper API to automatically cache the fonts your theme and plugins use to **minimize DNS requests** and speed up your WordPress website.
21
 
22
  = How Does It Work? =
23
 
24
- After installing the plugin, choose your Optimization Mode: Force (default) or Scan Posts/Pages (only available in Pro).
25
 
26
- When *Force* is selected, you can simply configure OMGF to work in the way you want, and run its detection mechanism on an address of your choosing. Tweak the stylesheet(s) as you wish and these will be used throughout your site.
27
 
28
- In *Automatic* (Pro) Mode, OMGF runs silently in the background and captures any requests made to fonts.googleapis.com or fonts.gstatic.com. When a webpage is first loaded, it reroutes these requests to its own Download API and copies the fonts over to your server. Then it generates a stylesheet for your fonts including SVG, EOT, TTF, WOFF and WOFF2 formats to guarantee maximum cross browser compatibility!
 
 
 
29
 
30
- When the fonts are downloaded and the stylesheet is generated, it rewrites every URL (pointing to fonts.googleapis.com or fonts.gstatic.com) to the locally hosted stylesheet and/or font.
31
 
32
- Please keep in mind that, although I try to make the configuration of this plugin as easy as possible, the concept of locally hosting a file or optimizing Google Fonts for *Pagespeed Insights* or *GT Metrix* has proven to be confusing for some people. If you're not sure of what your doing, please consult a SEO expert or Webdeveloper to help you with the configuration of this plugin or [hire me to do it for you](https://ffw.press/wordpress/omgf-expert-configuration/).
33
-
34
- = Features =
35
- - Automatically replace registered/enqueued Google Fonts in wp_head() with local copies,
36
- - Automatically remove registered/enqueued Google Fonts from wp_head(),
37
- - Manage Optimized Google Fonts,
38
- - Preload above the fold fonts,
39
- - Don't load certain fonts or entire stylesheets.
40
- - Leverage the font-display (swap) option.
41
 
42
  = Additional Features in OMGF Pro =
43
-
44
- Everything in the free version, plus:
45
-
46
- - Specify a Fallback Font Stack for every Google Font, to reduce Cumulative Layout Shift,
47
- - Automatically remove/replace all Google Fonts throughout the entire document/page,
48
- - Also supports WebFont Loader (webfont.js), Early Access Google Fonts and requests in stylesheets using @import and @font-face statements.
49
- - Automatically generate different stylesheets for pages with different Google Fonts configurations.
50
  - Material Icons support.
51
- - Combine all Google Fonts stylesheets (requested by your theme and/or plugins) into one file,
52
- - Deduplicate Google Fonts stylesheets,
53
- - Rewrite stylesheets added by other plugins and/or themes to include the configured font-display (e.g. swap) option, this will remove *the ensure text remains visible during webfont load* optimization suggestion from Google PageSpeed Insights.
54
- - Define file types to include in stylesheet (WOFF, WOFF2, EOT, TTF, SVG),
55
- - Reduce loading time and page size, by forcing a certain subset(s) to be used for all Google Fonts requests,
56
- - Remove Resource Hints (preload, preconnect, dns-prefetch) pointing to fonts.googleapis.com or fonts.gstatic.com,
57
- - Modify `src` attribute for fonts in stylesheet using the Fonts Source URL option to fully integrate with your configuration,
58
  - Use this to serve fonts and the stylesheets from your CDN, or
59
  - To serve fonts from an alternative path (e.g. when you're using Security through Obscurity plugins like WP Hide, etc.), or
 
60
  - Anything you like!
61
  - Proper handling for AMP pages (Fallback to or remove Google Fonts).
62
 
@@ -77,12 +68,27 @@ For the FAQ, [click here](https://docs.ffw.press/category/76-omgf-pro---faq).
77
  == Screenshots ==
78
 
79
  1. OMGF's Optimize Fonts screen. These settings affect the downloaded files and generated stylesheet(s).
80
- 2. After you've saved your changes, the Manage Optimized Google Fonts overview will show a list of detected fonts and will allowing you to easily unload and preload fonts.
81
- 3. Tweak how OMGF's detection mechanism will work and how it'll treat detected fonts.
82
- 4. Advanced Settings. Change these to make OMGF work with your configuration (if needed). The default settings will suffice for most configurations.
 
83
 
84
  == Changelog ==
85
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
86
  = 4.6.0 | February 16th, 2022 =
87
  * Fixed: Loading spinner wasn't center aligned.
88
  * Added: Force Optimization Mode Task Manager.
3
  Tags: google, fonts, gdpr, cache, speed, preload, font-display, webfonts, subsets, remove, minimize, external, requests
4
  Requires at least: 4.6
5
  Tested up to: 5.9
6
+ Stable tag: 5.0.0
7
  Requires PHP: 7.0
8
  License: GPLv2 or later
9
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
15
  > How could using fonts via Google's service possibly run afoul of GDPR? The fact of the matter is that, when a font is requested by the user's browser, their IP is logged by Google and used for analytics.
16
  > — Lifehacker
17
 
18
+ **Leverage Browser Cache**, **reduce DNS lookups/requests**, **reduce Cumulative Layout Shift** and make your Google Fonts **100% GDPR compliant** with OMGF!
19
 
20
  OMGF is written with performance and user-friendliness in mind. It uses the Google Fonts Helper API to automatically cache the fonts your theme and plugins use to **minimize DNS requests** and speed up your WordPress website.
21
 
22
  = How Does It Work? =
23
 
24
+ After installing the plugin, OMGF will automatically start looking for Google Fonts whenever a page is requested on your website.
25
 
26
+ All Google Fonts are listed in the **Manage Optimized Fonts** section of OMGF's settings screen. There, you can choose to:
27
 
28
+ - *Preload* fonts to **reduce Cumulative Layout Shift** above the fold,
29
+ - *Unload* fonts that're not used by you, your theme and/or plugins,
30
+ - Set a *Fallback Font Stack* (OMGF Pro required), to further **reduce Cumulative Layout Shift**, or
31
+ - *Replace* (OMGF Pro required) font-families with system fonts to **speed up loading times**!
32
 
33
+ = Other Features include =
34
 
35
+ - **Remove Resource Hints** (preload, preconnect, dns-prefetch) pointing to `fonts.googleapis.com` or `fonts.gstatic.com`,
36
+ - **Ensure text remains visible during webfont load** by forcing the *font-display* attribute to your Google Fonts,
37
+ - **Ensure text remains visible during webfont load** by forcing the *font-display* attribute to all your other fonts! (OMGF Pro required),
38
+ - **Reduce the file size** of your fonts and stylesheets, by using the *Force subset* and *Include File Types* feature (OMGF Pro required),
 
 
 
 
 
39
 
40
  = Additional Features in OMGF Pro =
41
+ - "Dig deeper" to find Google Fonts and optimize further. OMGF Pro supports:
42
+ - `@font-face` and `@import` statements inside **inline `<style>` blocks**,
43
+ - `@font-face` and `@import` statements inside **local stylesheets** loaded by your theme and/or plugins,
44
+ - Web Font Loader (`webfont.js`),
45
+ - Early Access Google Fonts.
 
 
46
  - Material Icons support.
47
+ - Modify your fonts' `src: url()` attribute fully integrate with your configuration,
 
 
 
 
 
 
48
  - Use this to serve fonts and the stylesheets from your CDN, or
49
  - To serve fonts from an alternative path (e.g. when you're using Security through Obscurity plugins like WP Hide, etc.), or
50
+ - Set a relative path to easily migrate from development/staging areas to production/live, or
51
  - Anything you like!
52
  - Proper handling for AMP pages (Fallback to or remove Google Fonts).
53
 
68
  == Screenshots ==
69
 
70
  1. OMGF's Optimize Fonts screen. These settings affect the downloaded files and generated stylesheet(s).
71
+ 2. The task manager offers a quick overview of the currently detected stylesheets and their status (e.g. loaded, stale or missing) along with quick links to simple management tasks, e.g. Empty Cache and Configure/Remove.
72
+ 3. After you've completed configuring OMGF, the Manage Optimized Fonts section will allow you to tweak all of your Google Fonts stylesheets, by e.g. unloading unused fonts and/or preloading fonts above the fold.
73
+ 4. OMGF Pro users can further tweak its level of detection under Detection Settings.
74
+ 5. Advanced Settings. Change these to make OMGF work with your configuration (if needed). The default settings will suffice for most configurations.
75
 
76
  == Changelog ==
77
 
78
+ = 5.0.0 - **The Better, Bigger, Faster, Stronger, Cooler, Awesomer Edition** | March 4th, 2022 =
79
+ * Added: Parse entire HTML document for Google Fonts stylesheets (instead of just wp_head())
80
+ * Added: Merged both Optimization Modes option into one automatically running option:
81
+ - A first scan is done upon Save & Optimize,
82
+ - A quick check is done on pageload, to see if other Google Fonts are found than the ones already found, and if so, they're downloaded and replaced on-the-fly.
83
+ * Enhanced: The Download API is replaced for an easier, leaner and faster alternative and no longer uses the WordPress API.
84
+ - If the first request fails, a mirror is used to retry the request, before throwing an error.
85
+ - Fixes rest_no_route errors in some configurations.
86
+ * Enhanced: The Task Manager now offers a quick overview of downloaded stylesheets and their status, along with simple management tasks, e.g. cache flush, configure stylesheet and/or remove.
87
+ - When cache is marked as stale, it's now possible to refresh the cache and maintain your stylesheet configuration.
88
+ * Added: Resource hints enqueued in wp_resource_hints() are now properly removed.
89
+ * Fixed: Smart Slider 3 compatibility.
90
+ * Several bugfixes, UX improvements and code optimizations.
91
+
92
  = 4.6.0 | February 16th, 2022 =
93
  * Fixed: Loading spinner wasn't center aligned.
94
  * Added: Force Optimization Mode Task Manager.