Version Description
- Tweak: Implemented internal settings API
Download this release
Release Info
Developer | dfactory |
Plugin | Post Views Counter |
Version | 1.3.7 |
Comparing to | |
See all releases |
Code changes from version 1.3.6 to 1.3.7
- css/admin.css +8 -372
- includes/dashboard.php +17 -5
- includes/settings-api.php +666 -0
- includes/settings.php +679 -601
- js/admin-dashboard.js +5 -0
- js/admin-settings.js +64 -65
- post-views-counter.php +140 -82
- readme.txt +6 -3
css/admin.css
CHANGED
@@ -25,6 +25,14 @@
|
|
25 |
margin-bottom: 3px;
|
26 |
}
|
27 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
28 |
.df-credits {
|
29 |
float: right;
|
30 |
width: 280px;
|
@@ -111,378 +119,6 @@
|
|
111 |
width: auto;
|
112 |
}
|
113 |
|
114 |
-
/*
|
115 |
-
* checkBo lightweight jQuery plugin v0.1.4 by @ElmahdiMahmoud
|
116 |
-
* Licensed under the MIT license - https://github.com/elmahdim/checkbo/blob/master/LICENSE
|
117 |
-
*
|
118 |
-
* Custom checkbox and radio
|
119 |
-
* Author URL: elmahdim.com
|
120 |
-
*/
|
121 |
-
.cb-checkbox .cb-inner, .cb-checkbox i {
|
122 |
-
width:18px;
|
123 |
-
height:18px;
|
124 |
-
-moz-border-radius:3px;
|
125 |
-
-webkit-border-radius:3px;
|
126 |
-
border-radius:3px
|
127 |
-
}
|
128 |
-
.cb-checkbox.cb-sm i, .cb-checkbox.cb-sm .cb-inner {
|
129 |
-
width:14px;
|
130 |
-
height:14px
|
131 |
-
}
|
132 |
-
.cb-checkbox.cb-md i, .cb-checkbox.cb-md .cb-inner {
|
133 |
-
width:24px;
|
134 |
-
height:24px;
|
135 |
-
-moz-border-radius:4px;
|
136 |
-
-webkit-border-radius:4px;
|
137 |
-
border-radius:4px
|
138 |
-
}
|
139 |
-
.cb-checkbox.cb-lg i, .cb-checkbox.cb-lg .cb-inner {
|
140 |
-
width:30px;
|
141 |
-
height:30px;
|
142 |
-
-moz-border-radius:6px;
|
143 |
-
-webkit-border-radius:6px;
|
144 |
-
border-radius:6px
|
145 |
-
}
|
146 |
-
.cb-radio .cb-inner {
|
147 |
-
width:18px;
|
148 |
-
height:18px
|
149 |
-
}
|
150 |
-
.cb-radio.cb-sm .cb-inner {
|
151 |
-
width:14px;
|
152 |
-
height:14px
|
153 |
-
}
|
154 |
-
.cb-radio.cb-md .cb-inner {
|
155 |
-
width:24px;
|
156 |
-
height:24px
|
157 |
-
}
|
158 |
-
.cb-radio.cb-lg .cb-inner {
|
159 |
-
width:30px;
|
160 |
-
height:30px
|
161 |
-
}
|
162 |
-
.cb-checkbox, .cb-radio {
|
163 |
-
color:inherit;
|
164 |
-
cursor:pointer;
|
165 |
-
overflow:hidden;
|
166 |
-
font-size:inherit;
|
167 |
-
font-weight:normal;
|
168 |
-
display:inline-block;
|
169 |
-
line-height:18px;
|
170 |
-
margin-right: 8px;
|
171 |
-
}
|
172 |
-
.form-table td fieldset label.cb-checkbox,
|
173 |
-
.form-table td fieldset label.cb-radio {
|
174 |
-
margin-right: 8px !important;
|
175 |
-
}
|
176 |
-
.cb-checkbox.disabled, .cb-checkbox.disabled *, .cb-radio.disabled, .cb-radio.disabled * {
|
177 |
-
cursor:default
|
178 |
-
}
|
179 |
-
.cb-checkbox input[type="checkbox"], .cb-radio input[type="radio"], .cb-switcher input[type="checkbox"], .cb-switcher input[type="radio"] {
|
180 |
-
display:none
|
181 |
-
}
|
182 |
-
.cb-checkbox.disabled, .cb-checkbox.disabled *, .cb-radio.disabled, .cb-radio.disabled *, .cb-switcher.disabled, .cb-switcher.disabled * {
|
183 |
-
cursor:default
|
184 |
-
}
|
185 |
-
.cb-checkbox.disabled {
|
186 |
-
color:#ddd
|
187 |
-
}
|
188 |
-
.cb-checkbox.disabled .cb-inner {
|
189 |
-
color:#ddd
|
190 |
-
}
|
191 |
-
.cb-checkbox.disabled:hover .cb-inner {
|
192 |
-
border-color:#ddd
|
193 |
-
}
|
194 |
-
.cb-checkbox.disabled.checked .cb-inner {
|
195 |
-
background-color:#ddd;
|
196 |
-
border-color:#ddd
|
197 |
-
}
|
198 |
-
.cb-radio.disabled {
|
199 |
-
color:#ddd
|
200 |
-
}
|
201 |
-
.cb-radio.disabled .cb-inner {
|
202 |
-
border-color:#ddd
|
203 |
-
}
|
204 |
-
.cb-radio.disabled i {
|
205 |
-
background-color:transparent
|
206 |
-
}
|
207 |
-
.cb-radio.disabled.checked .cb-inner {
|
208 |
-
border-color:#ddd
|
209 |
-
}
|
210 |
-
.cb-radio.disabled.checked .cb-inner i {
|
211 |
-
background-color:#ddd
|
212 |
-
}
|
213 |
-
.cb-radio.disabled:hover .cb-inner {
|
214 |
-
border-color:#ddd
|
215 |
-
}
|
216 |
-
.cb-checkbox .cb-inner {
|
217 |
-
float:left;
|
218 |
-
overflow:hidden;
|
219 |
-
margin:0 5px 0 0;
|
220 |
-
position:relative;
|
221 |
-
background:#f2f2f2;
|
222 |
-
display:inline-block;
|
223 |
-
border:1px solid #d6d6d6;
|
224 |
-
-moz-transition:all 0.5s ease;
|
225 |
-
-o-transition:all 0.5s ease;
|
226 |
-
-webkit-transition:all 0.5s ease;
|
227 |
-
transition:all 0.5s ease
|
228 |
-
}
|
229 |
-
.cb-checkbox i {
|
230 |
-
top:1px;
|
231 |
-
left:2px;
|
232 |
-
display:block;
|
233 |
-
position:absolute
|
234 |
-
}
|
235 |
-
.cb-checkbox i:before, .cb-checkbox i:after {
|
236 |
-
height:0;
|
237 |
-
width:2px;
|
238 |
-
content:"";
|
239 |
-
display:block;
|
240 |
-
position:absolute;
|
241 |
-
background-color:#fff;
|
242 |
-
-moz-transition:all 0.2s ease;
|
243 |
-
-o-transition:all 0.2s ease;
|
244 |
-
-webkit-transition:all 0.2s ease;
|
245 |
-
transition:all 0.2s ease
|
246 |
-
}
|
247 |
-
.cb-checkbox i:before {
|
248 |
-
top:0;
|
249 |
-
left:0;
|
250 |
-
-moz-transform:rotate(-45deg);
|
251 |
-
-ms-transform:rotate(-45deg);
|
252 |
-
-webkit-transform:rotate(-45deg);
|
253 |
-
transform:rotate(-45deg)
|
254 |
-
}
|
255 |
-
.cb-checkbox i:after {
|
256 |
-
left:7px;
|
257 |
-
bottom:5px;
|
258 |
-
-moz-transition-delay:0.3s;
|
259 |
-
-o-transition-delay:0.3s;
|
260 |
-
-webkit-transition-delay:0.3s;
|
261 |
-
transition-delay:0.3s;
|
262 |
-
-moz-transform:rotate(30deg);
|
263 |
-
-ms-transform:rotate(30deg);
|
264 |
-
-webkit-transform:rotate(30deg);
|
265 |
-
transform:rotate(30deg)
|
266 |
-
}
|
267 |
-
.cb-radio .cb-inner {
|
268 |
-
float:left;
|
269 |
-
overflow:hidden;
|
270 |
-
margin:0 5px 0 0;
|
271 |
-
position:relative;
|
272 |
-
display:inline-block;
|
273 |
-
border:1px solid #d7d7d7;
|
274 |
-
background-color:#f2f2f2;
|
275 |
-
-moz-border-radius:100%;
|
276 |
-
-webkit-border-radius:100%;
|
277 |
-
border-radius:100%;
|
278 |
-
-moz-transition:all 0.1s ease;
|
279 |
-
-o-transition:all 0.1s ease;
|
280 |
-
-webkit-transition:all 0.1s ease;
|
281 |
-
transition:all 0.1s ease
|
282 |
-
}
|
283 |
-
.cb-radio i {
|
284 |
-
top:50%;
|
285 |
-
left:50%;
|
286 |
-
width:6px;
|
287 |
-
height:6px;
|
288 |
-
margin-top:-3px;
|
289 |
-
margin-left:-3px;
|
290 |
-
position:absolute;
|
291 |
-
background-color:transparent;
|
292 |
-
-moz-border-radius:100%;
|
293 |
-
-webkit-border-radius:100%;
|
294 |
-
border-radius:100%;
|
295 |
-
-moz-transform:scale(0.05, 5);
|
296 |
-
-ms-transform:scale(0.05, 5);
|
297 |
-
-webkit-transform:scale(0.05, 5);
|
298 |
-
transform:scale(0.05, 5);
|
299 |
-
-moz-transition:all 0.2s ease;
|
300 |
-
-o-transition:all 0.2s ease;
|
301 |
-
-webkit-transition:all 0.2s ease;
|
302 |
-
transition:all 0.2s ease
|
303 |
-
}
|
304 |
-
.cb-checkbox.cb-sm, .cb-radio.cb-sm {
|
305 |
-
line-height:14px
|
306 |
-
}
|
307 |
-
.cb-checkbox.cb-md, .cb-radio.cb-md {
|
308 |
-
line-height:24px
|
309 |
-
}
|
310 |
-
.cb-checkbox.cb-lg, .cb-radio.cb-lg {
|
311 |
-
line-height:30px
|
312 |
-
}
|
313 |
-
.cb-checkbox.cb-sm i:before {
|
314 |
-
top:4px;
|
315 |
-
left:1px
|
316 |
-
}
|
317 |
-
.cb-checkbox.cb-sm i:after {
|
318 |
-
left:5px
|
319 |
-
}
|
320 |
-
.cb-checkbox.cb-md i:before {
|
321 |
-
top:10px;
|
322 |
-
left:5px
|
323 |
-
}
|
324 |
-
.cb-checkbox.cb-md i:after {
|
325 |
-
bottom:6px;
|
326 |
-
left:11px
|
327 |
-
}
|
328 |
-
.cb-checkbox.checked .cb-inner {
|
329 |
-
border-color:#0073aa;
|
330 |
-
background-color:#00a0d2;
|
331 |
-
box-shadow: 0 1px 0 rgba(120, 200, 230, 0.5) inset, 0 1px 0 rgba(0, 0, 0, 0.15);
|
332 |
-
}
|
333 |
-
.cb-checkbox.checked:hover .cb-inner {
|
334 |
-
background-color:#0091cd
|
335 |
-
}
|
336 |
-
.cb-checkbox.checked.cb-sm i:before {
|
337 |
-
top:4px;
|
338 |
-
left:1px
|
339 |
-
}
|
340 |
-
.cb-checkbox.checked.cb-sm i:after {
|
341 |
-
height:9px
|
342 |
-
}
|
343 |
-
.cb-checkbox.checked.cb-md i:before {
|
344 |
-
top:10px;
|
345 |
-
left:4px;
|
346 |
-
height:8px
|
347 |
-
}
|
348 |
-
.cb-checkbox.checked.cb-md i:after {
|
349 |
-
bottom:6px;
|
350 |
-
left:11px;
|
351 |
-
height:16px
|
352 |
-
}
|
353 |
-
.cb-checkbox.checked.cb-lg i:before {
|
354 |
-
top:11px;
|
355 |
-
left:6px;
|
356 |
-
height:12px
|
357 |
-
}
|
358 |
-
.cb-checkbox.checked.cb-lg i:after {
|
359 |
-
left:14px;
|
360 |
-
bottom:7px;
|
361 |
-
height:20px
|
362 |
-
}
|
363 |
-
.cb-checkbox.checked i:before {
|
364 |
-
top:6px;
|
365 |
-
left:2px;
|
366 |
-
height:6px
|
367 |
-
}
|
368 |
-
.cb-checkbox.checked i:after {
|
369 |
-
height:12px
|
370 |
-
}
|
371 |
-
.cb-radio.checked .cb-inner {
|
372 |
-
background:#fff;
|
373 |
-
box-shadow:0 0 3px #efefef
|
374 |
-
}
|
375 |
-
.cb-radio.checked i {
|
376 |
-
-moz-transform:scale(1.1, 1.1);
|
377 |
-
-ms-transform:scale(1.1, 1.1);
|
378 |
-
-webkit-transform:scale(1.1, 1.1);
|
379 |
-
transform:scale(1.1, 1.1);
|
380 |
-
background-color:#00a0d2
|
381 |
-
}
|
382 |
-
.cb-checkbox:hover .cb-inner, .cb-radio:hover .cb-inner {
|
383 |
-
border-color:#0073aa
|
384 |
-
}
|
385 |
-
.cb-switcher {
|
386 |
-
display:inline-block;
|
387 |
-
border:1px solid #eee;
|
388 |
-
background-color:#fff;
|
389 |
-
width:95px;
|
390 |
-
height:35px;
|
391 |
-
position:relative;
|
392 |
-
-moz-border-radius:20px;
|
393 |
-
-webkit-border-radius:20px;
|
394 |
-
border-radius:20px;
|
395 |
-
-moz-transition:background 0.4s ease;
|
396 |
-
-o-transition:background 0.4s ease;
|
397 |
-
-webkit-transition:background 0.4s ease;
|
398 |
-
transition:background 0.4s ease
|
399 |
-
}
|
400 |
-
.cb-switcher, .cb-switcher * {
|
401 |
-
cursor:pointer
|
402 |
-
}
|
403 |
-
.cb-switcher ::-moz-selection {
|
404 |
-
background-color:transparent
|
405 |
-
}
|
406 |
-
.cb-switcher ::selection {
|
407 |
-
background-color:transparent
|
408 |
-
}
|
409 |
-
.cb-switcher .cb-state {
|
410 |
-
z-index:1;
|
411 |
-
text-align:center;
|
412 |
-
font-size:12px
|
413 |
-
}
|
414 |
-
.cb-switcher .cb-state, .cb-switcher:before {
|
415 |
-
width:34px;
|
416 |
-
height:34px;
|
417 |
-
line-height:34px;
|
418 |
-
position:absolute;
|
419 |
-
left:0;
|
420 |
-
top:-1px;
|
421 |
-
-moz-border-radius:100%;
|
422 |
-
-webkit-border-radius:100%;
|
423 |
-
border-radius:100%;
|
424 |
-
-moz-transition:all 0.4s ease;
|
425 |
-
-o-transition:all 0.4s ease;
|
426 |
-
-webkit-transition:all 0.4s ease;
|
427 |
-
transition:all 0.4s ease
|
428 |
-
}
|
429 |
-
.cb-switcher:before {
|
430 |
-
content:"";
|
431 |
-
background-color:#eee;
|
432 |
-
-moz-box-shadow:1px 1px 1px rgba(0, 0, 0, 0.1);
|
433 |
-
-webkit-box-shadow:1px 1px 1px rgba(0, 0, 0, 0.1);
|
434 |
-
box-shadow:1px 1px 1px rgba(0, 0, 0, 0.1)
|
435 |
-
}
|
436 |
-
.cb-switcher.checked {
|
437 |
-
background-color:#00a0d2
|
438 |
-
}
|
439 |
-
.cb-switcher.checked .cb-state, .cb-switcher.checked:before {
|
440 |
-
left:60px;
|
441 |
-
color:#00a0d2
|
442 |
-
}
|
443 |
-
.cb-switcher.checked:before {
|
444 |
-
background-color:#fff;
|
445 |
-
-moz-box-shadow:-1px 1px 1px rgba(0, 0, 0, 0.1);
|
446 |
-
-webkit-box-shadow:-1px 1px 1px rgba(0, 0, 0, 0.1);
|
447 |
-
box-shadow:-1px 1px 1px rgba(0, 0, 0, 0.1)
|
448 |
-
}
|
449 |
-
.cb-switcher.checked .inner-switcher:before {
|
450 |
-
border-top-color:#0073aa
|
451 |
-
}
|
452 |
-
.cb-switcher.checked .inner-switcher:after {
|
453 |
-
border-bottom-color:#0073aa
|
454 |
-
}
|
455 |
-
.cb-switcher .inner-switcher:before, .cb-switcher .inner-switcher:after {
|
456 |
-
content:"";
|
457 |
-
position:absolute;
|
458 |
-
left:50%;
|
459 |
-
width:0;
|
460 |
-
height:0;
|
461 |
-
z-index:2;
|
462 |
-
margin-left:-20px;
|
463 |
-
border-left:20px solid transparent;
|
464 |
-
border-right:20px solid transparent;
|
465 |
-
-moz-transition:border 0.4s ease;
|
466 |
-
-o-transition:border 0.4s ease;
|
467 |
-
-webkit-transition:border 0.4s ease;
|
468 |
-
transition:border 0.4s ease
|
469 |
-
}
|
470 |
-
.cb-switcher .inner-switcher:before {
|
471 |
-
border-top:17px solid #fff;
|
472 |
-
top:0
|
473 |
-
}
|
474 |
-
.cb-switcher .inner-switcher:after {
|
475 |
-
border-bottom:17px solid #fff;
|
476 |
-
bottom:0
|
477 |
-
}
|
478 |
-
.cb-state {
|
479 |
-
color:#ccc;
|
480 |
-
display:inline-block
|
481 |
-
}
|
482 |
-
.cb-switcher-group .cb-state {
|
483 |
-
position:relative;
|
484 |
-
top:7px
|
485 |
-
}
|
486 |
.is-hidden {
|
487 |
display:none !important;
|
488 |
visibility:hidden !important
|
25 |
margin-bottom: 3px;
|
26 |
}
|
27 |
|
28 |
+
.post-views-counter-settings select {
|
29 |
+
vertical-align: top;
|
30 |
+
}
|
31 |
+
|
32 |
+
.pvc_user_roles {
|
33 |
+
margin-top: 12px;
|
34 |
+
}
|
35 |
+
|
36 |
.df-credits {
|
37 |
float: right;
|
38 |
width: 280px;
|
119 |
width: auto;
|
120 |
}
|
121 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
122 |
.is-hidden {
|
123 |
display:none !important;
|
124 |
visibility:hidden !important
|
includes/dashboard.php
CHANGED
@@ -238,8 +238,14 @@ class Post_Views_Counter_Dashboard {
|
|
238 |
foreach ( $post_types as $id => $post_type ) {
|
239 |
$post_type_obj = get_post_type_object( $post_type );
|
240 |
|
241 |
-
|
242 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
243 |
$data['data']['datasets'][$id]['data'] = array();
|
244 |
|
245 |
// get month views
|
@@ -325,9 +331,15 @@ class Post_Views_Counter_Dashboard {
|
|
325 |
foreach ( $post_types as $id => $post_type ) {
|
326 |
$post_type_obj = get_post_type_object( $post_type );
|
327 |
|
328 |
-
|
329 |
-
|
330 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
331 |
$data['data']['datasets'][$id]['data'] = array();
|
332 |
|
333 |
// get month views
|
238 |
foreach ( $post_types as $id => $post_type ) {
|
239 |
$post_type_obj = get_post_type_object( $post_type );
|
240 |
|
241 |
+
// unrecognized post type? (mainly from deactivated plugins)
|
242 |
+
if ( empty( $post_type_obj ) )
|
243 |
+
$label = __( 'Unknown', 'post-views-counter' ) . ' #' . $id;
|
244 |
+
else
|
245 |
+
$label = $post_type_obj->labels->name;
|
246 |
+
|
247 |
+
$data['data']['datasets'][$id]['label'] = $label;
|
248 |
+
$data['data']['datasets'][$id]['post_type'] = $post_type;
|
249 |
$data['data']['datasets'][$id]['data'] = array();
|
250 |
|
251 |
// get month views
|
331 |
foreach ( $post_types as $id => $post_type ) {
|
332 |
$post_type_obj = get_post_type_object( $post_type );
|
333 |
|
334 |
+
// unrecognized post type? (mainly from deactivated plugins)
|
335 |
+
if ( empty( $post_type_obj ) )
|
336 |
+
$label = __( 'Unknown', 'post-views-counter' ) . ' #' . $id;
|
337 |
+
else
|
338 |
+
$label = $post_type_obj->labels->name;
|
339 |
+
|
340 |
+
$data['data']['datasets'][$id]['label'] = $label;
|
341 |
+
$data['data']['datasets'][$id]['post_type'] = $post_type;
|
342 |
+
$data['data']['datasets'][$id]['hidden'] = in_array( $post_type, $user_options, true );
|
343 |
$data['data']['datasets'][$id]['data'] = array();
|
344 |
|
345 |
// get month views
|
includes/settings-api.php
ADDED
@@ -0,0 +1,666 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
// exit if accessed directly
|
3 |
+
if ( ! defined( 'ABSPATH' ) )
|
4 |
+
exit;
|
5 |
+
|
6 |
+
/**
|
7 |
+
* Post_Views_Counter_Settings_API class.
|
8 |
+
*
|
9 |
+
* @class Post_Views_Counter_Settings_API
|
10 |
+
*/
|
11 |
+
class Post_Views_Counter_Settings_API {
|
12 |
+
|
13 |
+
private $settings;
|
14 |
+
private $pages;
|
15 |
+
private $page_types;
|
16 |
+
private $prefix;
|
17 |
+
private $slug;
|
18 |
+
private $domain;
|
19 |
+
private $short;
|
20 |
+
private $object;
|
21 |
+
private $plugin;
|
22 |
+
private $plugin_url;
|
23 |
+
|
24 |
+
/**
|
25 |
+
* Class constructor.
|
26 |
+
*
|
27 |
+
* @return void
|
28 |
+
*/
|
29 |
+
public function __construct( $args ) {
|
30 |
+
// set initial data
|
31 |
+
$this->prefix = $args['prefix'];
|
32 |
+
$this->domain = $args['domain'];
|
33 |
+
|
34 |
+
// empty slug?
|
35 |
+
if ( empty( $args['slug'] ) )
|
36 |
+
$this->slug = $args['domain'];
|
37 |
+
else
|
38 |
+
$this->slug = $args['slug'];
|
39 |
+
|
40 |
+
// empty short name?
|
41 |
+
if ( empty( $args['short'] ) ) {
|
42 |
+
$short = '';
|
43 |
+
|
44 |
+
// prepare short name based on prefix
|
45 |
+
$parts = explode( '_', $this->prefix );
|
46 |
+
|
47 |
+
foreach ( $parts as $string ) {
|
48 |
+
$short .= substr( $string, 0, 1 );
|
49 |
+
}
|
50 |
+
|
51 |
+
// set short name
|
52 |
+
$this->short = $short;
|
53 |
+
} else
|
54 |
+
$this->short = $args['short'];
|
55 |
+
|
56 |
+
$this->object = $args['object'];
|
57 |
+
$this->plugin = $args['plugin'];
|
58 |
+
$this->plugin_url = $args['plugin_url'];
|
59 |
+
|
60 |
+
// actions
|
61 |
+
add_action( 'admin_menu', [ $this, 'admin_menu_options' ], 11 );
|
62 |
+
add_action( 'admin_init', [ $this, 'register_settings' ], 11 );
|
63 |
+
}
|
64 |
+
|
65 |
+
/**
|
66 |
+
* Get prefix.
|
67 |
+
*
|
68 |
+
* @return string
|
69 |
+
*/
|
70 |
+
public function get_prefix() {
|
71 |
+
return $this->prefix;
|
72 |
+
}
|
73 |
+
|
74 |
+
/**
|
75 |
+
* Get settings.
|
76 |
+
*
|
77 |
+
* @return array
|
78 |
+
*/
|
79 |
+
public function get_settings() {
|
80 |
+
return $this->settings;
|
81 |
+
}
|
82 |
+
|
83 |
+
/**
|
84 |
+
* Add menu pages.
|
85 |
+
*
|
86 |
+
* @return void
|
87 |
+
*/
|
88 |
+
public function admin_menu_options() {
|
89 |
+
$this->pages = apply_filters( $this->prefix . '_settings_pages', [] );
|
90 |
+
$types = [
|
91 |
+
'page' => [],
|
92 |
+
'subpage' => [],
|
93 |
+
'settings_page' => []
|
94 |
+
];
|
95 |
+
|
96 |
+
foreach ( $this->pages as $page => $data ) {
|
97 |
+
// skip invalid page types
|
98 |
+
if ( empty( $data['type'] ) || ! array_key_exists( $data['type'], $types ) )
|
99 |
+
continue;
|
100 |
+
|
101 |
+
// menu subpage?
|
102 |
+
if ( $data['type'] === 'subpage' ) {
|
103 |
+
add_submenu_page( $data['parent_slug'], $data['page_title'], $data['menu_title'], $data['capability'], $data['menu_slug'], ! empty( $data['callback'] ) ? $data['callback'] : [ $this, 'options_page' ] );
|
104 |
+
|
105 |
+
// add subpage type
|
106 |
+
$types['subpage'][$data['menu_slug']] = $page;
|
107 |
+
// menu settings page?
|
108 |
+
} elseif ( $data['type'] === 'settings_page' ) {
|
109 |
+
add_options_page( $data['page_title'], $data['menu_title'], $data['capability'], $data['menu_slug'], ! empty( $data['callback'] ) ? $data['callback'] : [ $this, 'options_page' ] );
|
110 |
+
|
111 |
+
// add settings type
|
112 |
+
$types['settings_page'][$data['menu_slug']] = $page;
|
113 |
+
}
|
114 |
+
}
|
115 |
+
|
116 |
+
// set page types
|
117 |
+
$this->page_types = $types;
|
118 |
+
}
|
119 |
+
|
120 |
+
/**
|
121 |
+
* Render settings.
|
122 |
+
*
|
123 |
+
* @return void
|
124 |
+
*/
|
125 |
+
public function options_page() {
|
126 |
+
global $pagenow;
|
127 |
+
|
128 |
+
$valid_page = false;
|
129 |
+
|
130 |
+
// get current screen
|
131 |
+
$screen = get_current_screen();
|
132 |
+
|
133 |
+
// display sub level settings page?
|
134 |
+
if ( $pagenow === 'admin.php' && preg_match( '/^(?:toplevel|' . $this->prefix . ')_page_' . $this->prefix . '-(' . implode( '|', $this->page_types['subpage'] ) . ')-settings$/', $screen->base, $matches ) === 1 && ! empty( $matches[1] ) ) {
|
135 |
+
$valid_page = true;
|
136 |
+
$page_type = 'subpage';
|
137 |
+
$url_page = 'admin.php';
|
138 |
+
}
|
139 |
+
|
140 |
+
// display settings page?
|
141 |
+
if ( ! $valid_page && $pagenow === 'options-general.php' && preg_match( '/^(?:settings_page_)(' . implode( '|', array_keys( $this->page_types['settings_page'] ) ) . ')$/', $screen->base, $matches ) === 1 ) {
|
142 |
+
$valid_page = true;
|
143 |
+
$page_type = 'settings_page';
|
144 |
+
$url_page = 'options-general.php';
|
145 |
+
}
|
146 |
+
|
147 |
+
// skip invalid pages
|
148 |
+
if ( ! $valid_page )
|
149 |
+
return;
|
150 |
+
|
151 |
+
echo '
|
152 |
+
<div class="wrap">
|
153 |
+
<h2>' . esc_html( $this->settings[$matches[1]]['label'] ) . '</h2>';
|
154 |
+
|
155 |
+
// any tabs?
|
156 |
+
if ( array_key_exists( 'tabs', $this->pages[$this->page_types[$page_type][$matches[1]]] ) ) {
|
157 |
+
// get tabs
|
158 |
+
$tabs = $this->pages[$this->page_types[$page_type][$matches[1]]]['tabs'];
|
159 |
+
|
160 |
+
// reset tabs
|
161 |
+
reset( $tabs );
|
162 |
+
|
163 |
+
// get first default tab
|
164 |
+
$first_tab = key( $tabs );
|
165 |
+
|
166 |
+
// get current tab
|
167 |
+
$tab_key = ! empty( $_GET['tab'] ) && array_key_exists( $_GET['tab'], $tabs ) ? $_GET['tab'] : $first_tab;
|
168 |
+
|
169 |
+
echo '
|
170 |
+
<h2 class="nav-tab-wrapper">';
|
171 |
+
|
172 |
+
foreach ( $tabs as $key => $tab ) {
|
173 |
+
echo '
|
174 |
+
<a class="nav-tab ' . ( $tab_key === $key ? 'nav-tab-active' : '' ) . '" href="' . esc_url( admin_url( $url_page . '?page=' . $matches[1] . '&tab=' . $key ) ) . '">' . esc_html( $tab['label'] ) . '</a>';
|
175 |
+
}
|
176 |
+
|
177 |
+
echo '
|
178 |
+
</h2>';
|
179 |
+
}
|
180 |
+
|
181 |
+
// skip for internal options page
|
182 |
+
if ( $page_type !== 'settings_page' )
|
183 |
+
settings_errors();
|
184 |
+
|
185 |
+
echo '
|
186 |
+
<div class="' . $this->slug . '-settings">
|
187 |
+
<div class="df-credits">
|
188 |
+
<h3 class="hndle">' . $this->plugin . ' ' . $this->object->defaults['version'] . '</h3>
|
189 |
+
<div class="inside">
|
190 |
+
<h4 class="inner">' . __( 'Need support?', $this->domain ) . '</h4>
|
191 |
+
<p class="inner">' . sprintf( __( 'If you are having problems with this plugin, please browse it\'s <a href="%s" target="_blank">Documentation</a> or talk about them in the <a href="%s" target="_blank">Support forum</a>', $this->domain ), 'https://www.dfactory.eu/docs/' . $this->slug . '/?utm_source=' . $this->slug . '-settings&utm_medium=link&utm_campaign=docs', 'https://www.dfactory.eu/support/?utm_source=' . $this->slug . '-settings&utm_medium=link&utm_campaign=support' ) . '</p>
|
192 |
+
<hr />
|
193 |
+
<h4 class="inner">' . __( 'Do you like this plugin?', $this->domain ) . '</h4>
|
194 |
+
<p class="inner">' . sprintf( __( '<a href="%s" target="_blank">Rate it 5</a> on WordPress.org', $this->domain ), 'https://wordpress.org/support/plugin/' . $this->slug . '/reviews/?filter=5' ) . '<br />' .
|
195 |
+
sprintf( __( 'Blog about it & link to the <a href="%s" target="_blank">plugin page</a>.', $this->domain ), 'https://dfactory.eu/plugins/' . $this->slug . '/?utm_source=' . $this->slug . '-settings&utm_medium=link&utm_campaign=blog-about' ) . '<br />' .
|
196 |
+
sprintf( __( 'Check out our other <a href="%s" target="_blank">WordPress plugins</a>.', $this->domain ), 'https://dfactory.eu/plugins/?utm_source=' . $this->slug . '-settings&utm_medium=link&utm_campaign=other-plugins' ) . '
|
197 |
+
</p>
|
198 |
+
<hr />
|
199 |
+
<p class="df-link inner"><a href="http://www.dfactory.eu/?utm_source=' . $this->slug . '-settings&utm_medium=link&utm_campaign=created-by" target="_blank" title="Digital Factory"><img src="//pvc-53eb.kxcdn.com/df-black-sm.png" alt="Digital Factory"></a></p>
|
200 |
+
</div>
|
201 |
+
</div>
|
202 |
+
<form action="options.php" method="post">';
|
203 |
+
|
204 |
+
// any tabs?
|
205 |
+
if ( ! empty( $tab_key ) ) {
|
206 |
+
if ( ! empty( $tabs[$tab_key]['option_name'] ) )
|
207 |
+
$setting = $tabs[$tab_key]['option_name'];
|
208 |
+
else
|
209 |
+
$setting = $this->prefix . '_' . $tab_key . '_settings';
|
210 |
+
} else
|
211 |
+
$setting = $this->prefix . '_' . $matches[1] . '_settings';
|
212 |
+
|
213 |
+
settings_fields( $setting );
|
214 |
+
do_settings_sections( $setting );
|
215 |
+
|
216 |
+
echo '
|
217 |
+
<p class="submit">';
|
218 |
+
|
219 |
+
submit_button( '', 'primary', 'save_' . $setting, false );
|
220 |
+
|
221 |
+
echo ' ';
|
222 |
+
|
223 |
+
submit_button( __( 'Reset to defaults', $this->domain ), 'secondary reset_' . $setting . ' reset_' . $this->short . '_settings', 'reset_' . $setting, false );
|
224 |
+
|
225 |
+
echo '
|
226 |
+
</p>
|
227 |
+
</form>
|
228 |
+
</div>
|
229 |
+
<div class="clear"></div>
|
230 |
+
</div>';
|
231 |
+
}
|
232 |
+
|
233 |
+
/**
|
234 |
+
* Register settings.
|
235 |
+
*
|
236 |
+
* @return void
|
237 |
+
*/
|
238 |
+
public function register_settings() {
|
239 |
+
$this->settings = apply_filters( $this->prefix . '_settings_data', [] );
|
240 |
+
|
241 |
+
// check settings
|
242 |
+
foreach ( $this->settings as $setting_id => $setting ) {
|
243 |
+
// tabs?
|
244 |
+
if ( is_array( $setting['option_name'] ) ) {
|
245 |
+
foreach ( $setting['option_name'] as $tab => $option_name ) {
|
246 |
+
$this->register_setting_fields( $tab, $setting, $option_name );
|
247 |
+
}
|
248 |
+
} else
|
249 |
+
$this->register_setting_fields( $setting_id, $setting );
|
250 |
+
}
|
251 |
+
}
|
252 |
+
|
253 |
+
public function register_setting_fields( $setting_id, $setting, $option_name = '' ) {
|
254 |
+
if ( empty( $option_name ) )
|
255 |
+
$option_name = $setting['option_name'];
|
256 |
+
|
257 |
+
// register setting
|
258 |
+
register_setting( $option_name, $option_name, ! empty( $setting['validate'] ) ? $setting['validate'] : [ $this, 'validate_settings' ] );
|
259 |
+
|
260 |
+
// register setting sections
|
261 |
+
if ( ! empty( $setting['sections'] ) ) {
|
262 |
+
foreach ( $setting['sections'] as $section_id => $section ) {
|
263 |
+
add_settings_section(
|
264 |
+
$section_id,
|
265 |
+
! empty( $section['title'] ) ? esc_html( $section['title'] ) : '',
|
266 |
+
! empty( $section['callback'] ) ? $section['callback'] : null,
|
267 |
+
! empty( $section['page'] ) ? $section['page'] : $option_name
|
268 |
+
);
|
269 |
+
}
|
270 |
+
}
|
271 |
+
|
272 |
+
// register setting fields
|
273 |
+
if ( ! empty( $setting['fields'] ) ) {
|
274 |
+
foreach ( $setting['fields'] as $field_key => $field ) {
|
275 |
+
if ( ! empty( $field['tab'] ) && $field['tab'] !== $setting_id )
|
276 |
+
continue;
|
277 |
+
|
278 |
+
// set field ID
|
279 |
+
$field_id = implode( '_', [ $this->prefix, $setting_id, $field_key ] );
|
280 |
+
|
281 |
+
// skip rendering this field?
|
282 |
+
if ( ! empty( $field['skip_rendering'] ) )
|
283 |
+
continue;
|
284 |
+
|
285 |
+
add_settings_field(
|
286 |
+
$field_id,
|
287 |
+
! empty( $field['title'] ) ? esc_html( $field['title'] ) : '',
|
288 |
+
[ $this, 'render_field' ],
|
289 |
+
$option_name,
|
290 |
+
! empty( $field['section'] ) ? esc_attr( $field['section'] ) : '',
|
291 |
+
array_merge( $this->prepare_field_args( $field, $field_id, $field_key, $setting_id, $option_name ), $field )
|
292 |
+
);
|
293 |
+
}
|
294 |
+
}
|
295 |
+
}
|
296 |
+
|
297 |
+
/**
|
298 |
+
* Prepare field arguments.
|
299 |
+
*
|
300 |
+
* @param array $args
|
301 |
+
* @return array
|
302 |
+
*/
|
303 |
+
public function prepare_field_args( $field, $field_id, $field_key, $setting_id, $setting_name ) {
|
304 |
+
// get field type
|
305 |
+
$field_type = ! empty( $field['type'] ) ? $field['type'] : '';
|
306 |
+
|
307 |
+
return [
|
308 |
+
'id' => $field_id,
|
309 |
+
'name' => $setting_name . '[' . $field_key . ']',
|
310 |
+
'class' => ! empty( $field['class'] ) ? $field['class'] : '',
|
311 |
+
'type' => $field_type,
|
312 |
+
'label' => ! empty( $field['label'] ) ? $field['label'] : '',
|
313 |
+
'description' => ! empty( $field['description'] ) ? $field['description'] : '',
|
314 |
+
'text' => ! empty( $field['text'] ) ? $field['text'] : '',
|
315 |
+
'min' => ! empty( $field['min'] ) ? (int) $field['min'] : 0,
|
316 |
+
'max' => ! empty( $field['max'] ) ? (int) $field['max'] : 0,
|
317 |
+
'options' => ! empty( $field['options'] ) ? $field['options'] : [],
|
318 |
+
'callback' => ! empty( $field['callback'] ) ? $field['callback'] : null,
|
319 |
+
'validate' => ! empty( $field['validate'] ) ? $field['validate'] : null,
|
320 |
+
'callback_args' => ! empty( $field['callback_args'] ) ? $field['callback_args'] : [],
|
321 |
+
'default' => $field_type !== 'custom' ? $this->object->defaults[$setting_id][$field_key] : null,
|
322 |
+
'value' => $field_type !== 'custom' ? $this->object->options[$setting_id][$field_key] : null
|
323 |
+
/*
|
324 |
+
after_field
|
325 |
+
before_field
|
326 |
+
*/
|
327 |
+
];
|
328 |
+
}
|
329 |
+
|
330 |
+
/**
|
331 |
+
* Render settings field.
|
332 |
+
*
|
333 |
+
* @param array $args
|
334 |
+
* @return void|string
|
335 |
+
*/
|
336 |
+
public function render_field( $args ) {
|
337 |
+
if ( empty( $args ) || ! is_array( $args ) )
|
338 |
+
return;
|
339 |
+
|
340 |
+
$html = '<div id="' . $args['id'] . '_setting"' . ( ! empty( $args['class'] ) ? ' class="' . $args['class'] . '"' : '' ) . '>';
|
341 |
+
|
342 |
+
if ( ! empty ( $args['before_field'] ) )
|
343 |
+
$html .= $args['before_field'];
|
344 |
+
|
345 |
+
switch ( $args['type'] ) {
|
346 |
+
case 'boolean':
|
347 |
+
$html .= '<input type="hidden" name="' . esc_attr( $args['name'] ) . '" value="false" />';
|
348 |
+
$html .= '<label><input id="' . esc_attr( $args['id'] ) . '" type="checkbox" name="' . esc_attr( $args['name'] ) . '" value="true" ' . checked( (bool) $args['value'], true, false ) . ' ' . disabled( empty( $args['disabled'] ), false, false ) . ' />' . esc_html( $args['label'] ) . '</label>';
|
349 |
+
break;
|
350 |
+
|
351 |
+
case 'radio':
|
352 |
+
foreach ( $args['options'] as $key => $name ) {
|
353 |
+
$html .= '<label><input id="' . esc_attr( $args['id'] . '_' . $key ) . '" type="radio" name="' . esc_attr( $args['name'] ) . '" value="' . esc_attr( $key ) . '" ' . checked( $key, $args['value'], false ) . ' ' . disabled( empty( $args['disabled'] ), false, false ) . ' />' . esc_html( $name ) . '</label> ';
|
354 |
+
}
|
355 |
+
break;
|
356 |
+
|
357 |
+
case 'checkbox':
|
358 |
+
$display_type = ! empty( $args['display_type'] ) && in_array( $args['display_type'], [ 'horizontal', 'vertical' ], true ) ? $args['display_type'] : 'horizontal';
|
359 |
+
|
360 |
+
$html .= '<input type="hidden" name="' . esc_attr( $args['name'] ) . '" value="empty" />';
|
361 |
+
|
362 |
+
foreach ( $args['options'] as $key => $name ) {
|
363 |
+
$html .= '<label><input id="' . esc_attr( $args['id'] . '_' . $key ) . '" type="checkbox" name="' . esc_attr( $args['name'] ) . '[]" value="' . esc_attr( $key ) . '" ' . checked( in_array( $key, $args['value'] ), true, false ) . ' ' . disabled( empty( $args['disabled'] ), false, false ) . ' />' . esc_html( $name ) . '</label>' . ( $display_type === 'horizontal' ? ' ' : '<br />' );
|
364 |
+
}
|
365 |
+
break;
|
366 |
+
|
367 |
+
case 'select':
|
368 |
+
$html .= '<select id="' . esc_attr( $args['id'] ) . '" name="' . esc_attr( $args['name'] ) . '" />';
|
369 |
+
|
370 |
+
foreach ( $args['options'] as $key => $name ) {
|
371 |
+
$html .= '<option value="' . esc_attr( $key ) . '" ' . selected( $args['value'], $key, false ) . '>' . esc_html( $name ) . '</option>';
|
372 |
+
}
|
373 |
+
|
374 |
+
$html .= '</select>';
|
375 |
+
break;
|
376 |
+
|
377 |
+
case 'range':
|
378 |
+
$html .= '<input id="' . esc_attr( $args['id'] . '_slider' ) . '" type="range" name="' . esc_attr( $args['name'] ) . '" value="' . esc_attr( $args['value'] ) . '" min="' . esc_attr( $args['min'] ) . '" max="' . esc_attr( $args['max'] ) . '" oninput="this.form.' . esc_attr( $args['id'] ) . '_range.value = this.value" /><output class="' . esc_attr( $this->slug ) . '-range" name="' . esc_attr( $args['id'] ) . '_range">' . ( (int) $args['value'] ) . '</output>';
|
379 |
+
break;
|
380 |
+
|
381 |
+
case 'number':
|
382 |
+
$html .= ( ! empty( $args['prepend'] ) ? '<span>' . esc_html( $args['prepend'] ) . '</span> ' : '' );
|
383 |
+
$html .= '<input id="' . $args['id'] . '" type="text" value="' . esc_attr( $args['value'] ) . '" name="' . esc_attr( $args['name'] ) . '" />';
|
384 |
+
$html .= ( ! empty( $args['append'] ) ? ' <span>' . esc_html( $args['append'] ) . '</span>' : '' );
|
385 |
+
break;
|
386 |
+
|
387 |
+
case 'custom':
|
388 |
+
$html .= call_user_func( $args['callback'], $args );
|
389 |
+
break;
|
390 |
+
|
391 |
+
case 'info':
|
392 |
+
$html .= '<span' . ( ! empty( $args['subclass'] ) ? ' class="' . esc_attr( $args['subclass'] ) . '"' : '' ) . '>' . esc_html( $args['text'] ) . '</span>';
|
393 |
+
break;
|
394 |
+
|
395 |
+
case 'input':
|
396 |
+
default:
|
397 |
+
$html .= ( ! empty( $args['prepend'] ) ? '<span>' . esc_html( $args['prepend'] ) . '</span> ' : '' );
|
398 |
+
$html .= '<input id="' . $args['id'] . '"' . ( ! empty( $args['subclass'] ) ? ' class="' . esc_attr( $args['subclass'] ) . '"' : '' ) . ' type="text" value="' . esc_attr( $args['value'] ) . '" name="' . esc_attr( $args['name'] ) . '" />';
|
399 |
+
$html .= ( ! empty( $args['append'] ) ? ' <span>' . esc_html( $args['append'] ) . '</span>' : '' );
|
400 |
+
}
|
401 |
+
|
402 |
+
if ( ! empty ( $args['after_field'] ) )
|
403 |
+
$html .= $args['after_field'];
|
404 |
+
|
405 |
+
if ( ! empty ( $args['description'] ) )
|
406 |
+
$html .= '<p class="description">' . $args['description'] . '</p>';
|
407 |
+
|
408 |
+
$html .= '</div>';
|
409 |
+
|
410 |
+
if ( ! empty( $args['return'] ) )
|
411 |
+
return $html;
|
412 |
+
else
|
413 |
+
echo $html;
|
414 |
+
}
|
415 |
+
|
416 |
+
/**
|
417 |
+
* Validate settings field.
|
418 |
+
*
|
419 |
+
* @param mixed $value
|
420 |
+
* @param string $type
|
421 |
+
* @param array $args
|
422 |
+
* @return mixed
|
423 |
+
*/
|
424 |
+
public function validate_field( $value = null, $type = '', $args = [] ) {
|
425 |
+
if ( is_null( $value ) )
|
426 |
+
return null;
|
427 |
+
|
428 |
+
switch ( $type ) {
|
429 |
+
case 'boolean':
|
430 |
+
// possible value: 'true' or 'false'
|
431 |
+
$value = ( $value === 'true' || $value === true );
|
432 |
+
break;
|
433 |
+
|
434 |
+
case 'radio':
|
435 |
+
$value = is_array( $value ) ? false : sanitize_text_field( $value );
|
436 |
+
break;
|
437 |
+
|
438 |
+
case 'checkbox':
|
439 |
+
// possible value: 'empty' or array
|
440 |
+
if ( $value === 'empty' )
|
441 |
+
$value = [];
|
442 |
+
else {
|
443 |
+
if ( is_array( $value ) && ! empty( $value ) ) {
|
444 |
+
$value = array_map( 'sanitize_text_field', $value );
|
445 |
+
$values = [];
|
446 |
+
|
447 |
+
foreach ( $value as $single_value ) {
|
448 |
+
if ( array_key_exists( $single_value, $args['options'] ) )
|
449 |
+
$values[] = $single_value;
|
450 |
+
}
|
451 |
+
|
452 |
+
$value = $values;
|
453 |
+
} else
|
454 |
+
$value = [];
|
455 |
+
}
|
456 |
+
break;
|
457 |
+
|
458 |
+
case 'number':
|
459 |
+
$value = (int) $value;
|
460 |
+
|
461 |
+
// is value lower than?
|
462 |
+
if ( isset( $args['min'] ) && $value < $args['min'] )
|
463 |
+
$value = $args['min'];
|
464 |
+
|
465 |
+
// is value greater than?
|
466 |
+
if ( isset( $args['max'] ) && $value > $args['max'] )
|
467 |
+
$value = $args['max'];
|
468 |
+
break;
|
469 |
+
|
470 |
+
case 'info':
|
471 |
+
$value = '';
|
472 |
+
break;
|
473 |
+
|
474 |
+
case 'custom':
|
475 |
+
// do nothing
|
476 |
+
break;
|
477 |
+
|
478 |
+
case 'input':
|
479 |
+
case 'select':
|
480 |
+
default:
|
481 |
+
$value = is_array( $value ) ? array_map( 'sanitize_text_field', $value ) : sanitize_text_field( $value );
|
482 |
+
break;
|
483 |
+
}
|
484 |
+
|
485 |
+
return stripslashes_deep( $value );
|
486 |
+
}
|
487 |
+
|
488 |
+
/**
|
489 |
+
* Validate settings.
|
490 |
+
*
|
491 |
+
* @param array $input
|
492 |
+
* @return array
|
493 |
+
*/
|
494 |
+
public function validate_settings( $input ) {
|
495 |
+
// check capability
|
496 |
+
//@TODO dodac tu capability
|
497 |
+
// if ( ! current_user_can( apply_filters( 'rl_lightbox_settings_capability', 'edit_lightbox_settings' ) ) )
|
498 |
+
// return $input;
|
499 |
+
|
500 |
+
// check capability
|
501 |
+
if ( ! current_user_can( 'manage_options' ) )
|
502 |
+
return $input;
|
503 |
+
|
504 |
+
// check option page
|
505 |
+
if ( empty( $_POST['option_page'] ) )
|
506 |
+
return $input;
|
507 |
+
|
508 |
+
// try to get setting name and ID
|
509 |
+
foreach ( $this->settings as $id => $setting ) {
|
510 |
+
// tabs?
|
511 |
+
if ( is_array( $setting['option_name'] ) ) {
|
512 |
+
foreach ( $setting['option_name'] as $tab => $option_name ) {
|
513 |
+
// found valid setting?
|
514 |
+
if ( $option_name === $_POST['option_page'] ) {
|
515 |
+
// assign setting ID
|
516 |
+
$setting_id = $tab;
|
517 |
+
|
518 |
+
// assign setting name
|
519 |
+
$setting_name = $option_name;
|
520 |
+
|
521 |
+
// assign setting key
|
522 |
+
$setting_key = $id;
|
523 |
+
|
524 |
+
// already found setting, no need to check the rest
|
525 |
+
break 2;
|
526 |
+
}
|
527 |
+
}
|
528 |
+
} else {
|
529 |
+
// found valid setting?
|
530 |
+
if ( $setting['option_name'] === $_POST['option_page'] ) {
|
531 |
+
// assign setting ID and key
|
532 |
+
$setting_key = $setting_id = $id;
|
533 |
+
|
534 |
+
// assign setting name
|
535 |
+
$setting_name = $setting['option_name'];
|
536 |
+
|
537 |
+
// already found setting, no need to check the rest
|
538 |
+
break;
|
539 |
+
}
|
540 |
+
}
|
541 |
+
}
|
542 |
+
|
543 |
+
// check setting id, no need to check $setting_name since it was at the same stage
|
544 |
+
if ( empty( $setting_id ) )
|
545 |
+
return $input;
|
546 |
+
|
547 |
+
// save settings
|
548 |
+
if ( isset( $_POST['save_' . $setting_name] ) ) {
|
549 |
+
$input = $this->validate_input_settings( $setting_id, $setting_key, $input );
|
550 |
+
|
551 |
+
add_settings_error( $setting_name, 'settings_saved', __( 'Settings saved.', $this->domain ), 'updated' );
|
552 |
+
// reset settings
|
553 |
+
} elseif ( isset( $_POST['reset_' . $setting_name] ) ) {
|
554 |
+
// get default values
|
555 |
+
$input = $this->object->defaults[$setting_id];
|
556 |
+
|
557 |
+
// check custom reset functions
|
558 |
+
if ( ! empty( $this->settings[$setting_key]['fields'] ) ) {
|
559 |
+
foreach ( $this->settings[$setting_key]['fields'] as $field_id => $field ) {
|
560 |
+
// skip invalid tab field if any
|
561 |
+
if ( ! empty( $field['tab'] ) && $field['tab'] !== $setting_id )
|
562 |
+
continue;
|
563 |
+
|
564 |
+
// custom reset function?
|
565 |
+
if ( ! empty( $field['reset'] ) ) {
|
566 |
+
// valid function? no need to check "else" since all default values are already set
|
567 |
+
if ( $this->callback_function_exists( $field['reset'] ) ) {
|
568 |
+
if ( $field['type'] === 'custom' )
|
569 |
+
$input = call_user_func( $field['reset'], $input, $field );
|
570 |
+
else
|
571 |
+
$input[$field_id] = call_user_func( $field['reset'], $input[$field_id], $field );
|
572 |
+
}
|
573 |
+
}
|
574 |
+
}
|
575 |
+
}
|
576 |
+
|
577 |
+
add_settings_error( $setting_name, 'settings_restored', __( 'Settings restored to defaults.', $this->domain ), 'updated' );
|
578 |
+
}
|
579 |
+
|
580 |
+
return $input;
|
581 |
+
}
|
582 |
+
|
583 |
+
/**
|
584 |
+
* Validate input settings.
|
585 |
+
*
|
586 |
+
* @param string $setting_id
|
587 |
+
* @param array $input
|
588 |
+
* @return array
|
589 |
+
*/
|
590 |
+
public function validate_input_settings( $setting_id, $setting_key, $input ) {
|
591 |
+
if ( ! empty( $this->settings[$setting_key]['fields'] ) ) {
|
592 |
+
foreach ( $this->settings[$setting_key]['fields'] as $field_id => $field ) {
|
593 |
+
// skip saving this field?
|
594 |
+
if ( ! empty( $field['skip_saving'] ) )
|
595 |
+
continue;
|
596 |
+
|
597 |
+
// skip invalid tab field if any
|
598 |
+
if ( ! empty( $field['tab'] ) && $field['tab'] !== $setting_id )
|
599 |
+
continue;
|
600 |
+
|
601 |
+
// custom validate function?
|
602 |
+
if ( ! empty( $field['validate'] ) ) {
|
603 |
+
// valid function?
|
604 |
+
if ( $this->callback_function_exists( $field['validate'] ) ) {
|
605 |
+
if ( $field['type'] === 'custom' )
|
606 |
+
$input = call_user_func( $field['validate'], $input, $field );
|
607 |
+
else
|
608 |
+
$input[$field_id] = isset( $input[$field_id] ) ? call_user_func( $field['validate'], $input[$field_id], $field ) : $this->object->defaults[$setting_id][$field_id];
|
609 |
+
} else
|
610 |
+
$input[$field_id] = $this->object->defaults[$setting_id][$field_id];
|
611 |
+
} else {
|
612 |
+
// field data?
|
613 |
+
if ( isset( $input[$field_id] ) )
|
614 |
+
$input[$field_id] = $this->validate_field( $input[$field_id], $field['type'], $field );
|
615 |
+
else
|
616 |
+
$input[$field_id] = $this->object->defaults[$setting_id][$field_id];
|
617 |
+
}
|
618 |
+
}
|
619 |
+
}
|
620 |
+
|
621 |
+
return $input;
|
622 |
+
}
|
623 |
+
|
624 |
+
/**
|
625 |
+
* Check whether callback is a valid function.
|
626 |
+
*
|
627 |
+
* @param string|array $callback
|
628 |
+
* @return bool
|
629 |
+
*/
|
630 |
+
public function callback_function_exists( $callback ) {
|
631 |
+
// function as array?
|
632 |
+
if ( is_array( $callback ) ) {
|
633 |
+
list( $object, $function ) = $callback;
|
634 |
+
|
635 |
+
// check function existence
|
636 |
+
$function_exists = method_exists( $object, $function );
|
637 |
+
// function as string?
|
638 |
+
} elseif ( is_string( $callback ) ) {
|
639 |
+
// check function existence
|
640 |
+
$function_exists = function_exists( $callback );
|
641 |
+
} else
|
642 |
+
$function_exists = false;
|
643 |
+
|
644 |
+
return $function_exists;
|
645 |
+
}
|
646 |
+
|
647 |
+
/**
|
648 |
+
* Get value based on minimum and maximum.
|
649 |
+
*
|
650 |
+
* @param array $data
|
651 |
+
* @param string $setting_name
|
652 |
+
* @param int $default
|
653 |
+
* @param int $min
|
654 |
+
* @param int $max
|
655 |
+
* @return void
|
656 |
+
*/
|
657 |
+
public function get_int_value( $data, $setting_name, $default, $min, $max ) {
|
658 |
+
// check existence of value
|
659 |
+
$value = array_key_exists( $setting_name, $data ) ? (int) $data[$setting_name] : $default;
|
660 |
+
|
661 |
+
if ( $value > $max || $value < $min )
|
662 |
+
$value = $default;
|
663 |
+
|
664 |
+
return $value;
|
665 |
+
}
|
666 |
+
}
|
includes/settings.php
CHANGED
@@ -10,112 +10,78 @@ if ( ! defined( 'ABSPATH' ) )
|
|
10 |
*/
|
11 |
class Post_Views_Counter_Settings {
|
12 |
|
13 |
-
private $tabs;
|
14 |
-
private $choices;
|
15 |
-
private $modes;
|
16 |
private $time_types;
|
17 |
private $groups;
|
18 |
private $user_roles;
|
19 |
-
private $positions;
|
20 |
-
private $display_styles;
|
21 |
public $post_types;
|
22 |
public $page_types;
|
23 |
|
24 |
public function __construct() {
|
25 |
// actions
|
26 |
-
add_action( '
|
27 |
-
add_action( '
|
28 |
-
|
29 |
-
|
|
|
|
|
30 |
}
|
31 |
|
32 |
/**
|
33 |
* Load default settings.
|
|
|
|
|
34 |
*/
|
35 |
public function load_defaults() {
|
36 |
if ( ! is_admin() )
|
37 |
return;
|
38 |
|
39 |
-
$this->
|
40 |
-
'
|
41 |
-
'
|
42 |
-
'
|
43 |
-
)
|
44 |
-
|
45 |
-
|
46 |
-
|
47 |
-
|
48 |
-
$this->
|
49 |
-
'
|
50 |
-
'
|
51 |
-
'
|
52 |
-
'
|
53 |
-
|
54 |
-
'years' => __( 'years', 'post-views-counter' )
|
55 |
-
);
|
56 |
-
|
57 |
-
$this->groups = array(
|
58 |
-
'robots' => __( 'robots', 'post-views-counter' ),
|
59 |
-
'users' => __( 'logged in users', 'post-views-counter' ),
|
60 |
-
'guests' => __( 'guests', 'post-views-counter' ),
|
61 |
-
'roles' => __( 'selected user roles', 'post-views-counter' )
|
62 |
-
);
|
63 |
-
|
64 |
-
$this->positions = array(
|
65 |
-
'before' => __( 'before the content', 'post-views-counter' ),
|
66 |
-
'after' => __( 'after the content', 'post-views-counter' ),
|
67 |
-
'manual' => __( 'manual', 'post-views-counter' )
|
68 |
-
);
|
69 |
-
|
70 |
-
$this->display_styles = array(
|
71 |
-
'icon' => __( 'icon', 'post-views-counter' ),
|
72 |
-
'text' => __( 'label', 'post-views-counter' )
|
73 |
-
);
|
74 |
-
|
75 |
-
$this->tabs = array(
|
76 |
-
'general' => array(
|
77 |
-
'name' => __( 'General', 'post-views-counter' ),
|
78 |
-
'key' => 'post_views_counter_settings_general',
|
79 |
-
'submit' => 'save_pvc_general',
|
80 |
-
'reset' => 'reset_pvc_general'
|
81 |
-
),
|
82 |
-
'display' => array(
|
83 |
-
'name' => __( 'Display', 'post-views-counter' ),
|
84 |
-
'key' => 'post_views_counter_settings_display',
|
85 |
-
'submit' => 'save_pvc_display',
|
86 |
-
'reset' => 'reset_pvc_display'
|
87 |
-
)
|
88 |
-
);
|
89 |
|
90 |
$this->user_roles = $this->get_user_roles();
|
91 |
|
92 |
$this->page_types = apply_filters(
|
93 |
'pvc_page_types_display_options',
|
94 |
-
|
95 |
-
'home'
|
96 |
-
'archive'
|
97 |
-
'singular'
|
98 |
-
'search'
|
99 |
-
|
100 |
);
|
101 |
}
|
102 |
|
103 |
/**
|
104 |
* Get post types avaiable for counting.
|
|
|
|
|
105 |
*/
|
106 |
public function load_post_types() {
|
107 |
if ( ! is_admin() )
|
108 |
return;
|
109 |
|
110 |
-
$post_types =
|
111 |
|
112 |
// built in public post types
|
113 |
-
foreach ( get_post_types(
|
114 |
$post_types[$key] = $post_type->labels->name;
|
115 |
}
|
116 |
|
117 |
// public custom post types
|
118 |
-
foreach ( get_post_types(
|
119 |
$post_types[$key] = $post_type->labels->name;
|
120 |
}
|
121 |
|
@@ -123,7 +89,7 @@ class Post_Views_Counter_Settings {
|
|
123 |
if ( class_exists( 'bbPress' ) && isset( $post_types['reply'] ) )
|
124 |
unset( $post_types['reply'] );
|
125 |
|
126 |
-
|
127 |
|
128 |
// sort post types alphabetically with their keys
|
129 |
asort( $post_types, SORT_STRING );
|
@@ -140,7 +106,7 @@ class Post_Views_Counter_Settings {
|
|
140 |
public function get_user_roles() {
|
141 |
global $wp_roles;
|
142 |
|
143 |
-
$roles =
|
144 |
|
145 |
foreach ( apply_filters( 'editable_roles', $wp_roles->roles ) as $role => $details ) {
|
146 |
$roles[$role] = translate_user_role( $details['name'] );
|
@@ -152,687 +118,799 @@ class Post_Views_Counter_Settings {
|
|
152 |
}
|
153 |
|
154 |
/**
|
155 |
-
* Add
|
156 |
*
|
157 |
-
* @
|
|
|
158 |
*/
|
159 |
-
public function
|
160 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
161 |
}
|
162 |
|
163 |
/**
|
164 |
-
*
|
165 |
*
|
166 |
-
* @
|
|
|
167 |
*/
|
168 |
-
public function
|
169 |
-
$
|
170 |
-
|
171 |
-
|
172 |
-
|
173 |
-
|
174 |
-
|
175 |
-
|
176 |
-
|
177 |
-
|
178 |
-
|
179 |
-
|
180 |
-
|
181 |
-
|
182 |
-
|
183 |
-
|
184 |
-
|
185 |
-
|
186 |
-
|
187 |
-
|
188 |
-
|
189 |
-
<hr />
|
190 |
-
<h4 class="inner">' . __( 'Do you like this plugin?', 'post-views-counter' ) . '</h4>
|
191 |
-
<p class="inner">' . sprintf( __( '<a href="%s" target="_blank">Rate it 5</a> on WordPress.org', 'post-views-counter' ), 'https://wordpress.org/support/plugin/post-views-counter/reviews/?filter=5' ) . '<br />' .
|
192 |
-
sprintf( __( 'Blog about it & link to the <a href="%s" target="_blank">plugin page</a>.', 'post-views-counter' ), 'https://dfactory.eu/plugins/post-views-counter/?utm_source=post-views-counter-settings&utm_medium=link&utm_campaign=blog-about' ) . '<br />' .
|
193 |
-
sprintf( __( 'Check out our other <a href="%s" target="_blank">WordPress plugins</a>.', 'post-views-counter' ), 'https://dfactory.eu/plugins/?utm_source=post-views-counter-settings&utm_medium=link&utm_campaign=other-plugins' ) . '
|
194 |
-
</p>
|
195 |
-
<hr />
|
196 |
-
<p class="df-link inner"><a href="http://www.dfactory.eu/?utm_source=post-views-counter-settings&utm_medium=link&utm_campaign=created-by" target="_blank" title="Digital Factory"><img src="//pvc-53eb.kxcdn.com/df-black-sm.png' . '" alt="Digital Factory" /></a></p>
|
197 |
-
</div>
|
198 |
-
</div>
|
199 |
-
<form action="options.php" method="post">';
|
200 |
-
|
201 |
-
wp_nonce_field( 'update-options' );
|
202 |
-
settings_fields( $this->tabs[$tab_key]['key'] );
|
203 |
-
do_settings_sections( $this->tabs[$tab_key]['key'] );
|
204 |
-
|
205 |
-
echo '
|
206 |
-
<p class="submit">';
|
207 |
-
|
208 |
-
submit_button( '', 'primary', $this->tabs[$tab_key]['submit'], false );
|
209 |
-
|
210 |
-
echo ' ';
|
211 |
-
|
212 |
-
submit_button( __( 'Reset to defaults', 'post-views-counter' ), 'secondary reset_pvc_settings', $this->tabs[$tab_key]['reset'], false );
|
213 |
-
|
214 |
-
echo '
|
215 |
-
</p>
|
216 |
-
</form>
|
217 |
-
</div>
|
218 |
-
<div class="clear"></div>
|
219 |
-
</div>';
|
220 |
}
|
221 |
|
222 |
/**
|
223 |
-
*
|
|
|
|
|
|
|
224 |
*/
|
225 |
-
public function
|
226 |
-
//
|
227 |
-
|
228 |
-
|
229 |
-
add_settings_field( 'pvc_post_types_count', __( 'Post Types Count', 'post-views-counter' ), array( $this, 'post_types_count' ), 'post_views_counter_settings_general', 'post_views_counter_settings_general' );
|
230 |
-
add_settings_field( 'pvc_counter_mode', __( 'Counter Mode', 'post-views-counter' ), array( $this, 'counter_mode' ), 'post_views_counter_settings_general', 'post_views_counter_settings_general' );
|
231 |
-
add_settings_field( 'pvc_post_views_column', __( 'Post Views Column', 'post-views-counter' ), array( $this, 'post_views_column' ), 'post_views_counter_settings_general', 'post_views_counter_settings_general' );
|
232 |
-
add_settings_field( 'pvc_restrict_edit_views', __( 'Restrict Edit', 'post-views-counter' ), array( $this, 'restrict_edit_views' ), 'post_views_counter_settings_general', 'post_views_counter_settings_general' );
|
233 |
-
add_settings_field( 'pvc_time_between_counts', __( 'Count Interval', 'post-views-counter' ), array( $this, 'time_between_counts' ), 'post_views_counter_settings_general', 'post_views_counter_settings_general' );
|
234 |
-
add_settings_field( 'pvc_reset_counts', __( 'Reset Data Interval', 'post-views-counter' ), array( $this, 'reset_counts' ), 'post_views_counter_settings_general', 'post_views_counter_settings_general' );
|
235 |
-
add_settings_field( 'pvc_flush_interval', __( 'Flush Object Cache Interval', 'post-views-counter' ), array( $this, 'flush_interval' ), 'post_views_counter_settings_general', 'post_views_counter_settings_general' );
|
236 |
-
add_settings_field( 'pvc_exclude', __( 'Exclude Visitors', 'post-views-counter' ), array( $this, 'exclude' ), 'post_views_counter_settings_general', 'post_views_counter_settings_general' );
|
237 |
-
add_settings_field( 'pvc_exclude_ips', __( 'Exclude IPs', 'post-views-counter' ), array( $this, 'exclude_ips' ), 'post_views_counter_settings_general', 'post_views_counter_settings_general' );
|
238 |
-
add_settings_field( 'pvc_strict_counts', __( 'Strict counts', 'post-views-counter' ), array( $this, 'strict_counts' ), 'post_views_counter_settings_general', 'post_views_counter_settings_general' );
|
239 |
-
add_settings_field( 'pvc_wp_postviews', __( 'Tools', 'post-views-counter' ), array( $this, 'wp_postviews' ), 'post_views_counter_settings_general', 'post_views_counter_settings_general' );
|
240 |
-
add_settings_field( 'pvc_deactivation_delete', __( 'Deactivation', 'post-views-counter' ), array( $this, 'deactivation_delete' ), 'post_views_counter_settings_general', 'post_views_counter_settings_general' );
|
241 |
-
|
242 |
-
// display options
|
243 |
-
register_setting( 'post_views_counter_settings_display', 'post_views_counter_settings_display', array( $this, 'validate_settings' ) );
|
244 |
-
add_settings_section( 'post_views_counter_settings_display', __( 'Display settings', 'post-views-counter' ), '', 'post_views_counter_settings_display' );
|
245 |
-
add_settings_field( 'pvc_post_views_label', __( 'Post Views Label', 'post-views-counter' ), array( $this, 'post_views_label' ), 'post_views_counter_settings_display', 'post_views_counter_settings_display' );
|
246 |
-
add_settings_field( 'pvc_post_types_display', __( 'Post Type', 'post-views-counter' ), array( $this, 'post_types_display' ), 'post_views_counter_settings_display', 'post_views_counter_settings_display' );
|
247 |
-
add_settings_field( 'pvc_page_types_display', __( 'Page Type', 'post-views-counter' ), array( $this, 'page_types_display' ), 'post_views_counter_settings_display', 'post_views_counter_settings_display' );
|
248 |
-
add_settings_field( 'pvc_restrict_display', __( 'User Type', 'post-views-counter' ), array( $this, 'restrict_display' ), 'post_views_counter_settings_display', 'post_views_counter_settings_display' );
|
249 |
-
add_settings_field( 'pvc_position', __( 'Position', 'post-views-counter' ), array( $this, 'position' ), 'post_views_counter_settings_display', 'post_views_counter_settings_display' );
|
250 |
-
add_settings_field( 'pvc_display_style', __( 'Display Style', 'post-views-counter' ), array( $this, 'display_style' ), 'post_views_counter_settings_display', 'post_views_counter_settings_display' );
|
251 |
-
add_settings_field( 'pvc_icon_class', __( 'Icon Class', 'post-views-counter' ), array( $this, 'icon_class' ), 'post_views_counter_settings_display', 'post_views_counter_settings_display' );
|
252 |
-
add_settings_field( 'pvc_toolbar_statistics', __( 'Toolbar Chart', 'post-views-counter' ), array( $this, 'toolbar_statistics' ), 'post_views_counter_settings_display', 'post_views_counter_settings_display' );
|
253 |
-
}
|
254 |
|
255 |
-
|
256 |
-
|
257 |
-
*/
|
258 |
-
public function post_views_label() {
|
259 |
-
echo '
|
260 |
-
<div id="pvc_post_views_label">
|
261 |
-
<fieldset>
|
262 |
-
<input type="text" class="large-text" name="post_views_counter_settings_display[label]" value="' . esc_attr( Post_Views_Counter()->options['display']['label'] ) . '" />
|
263 |
-
<p class="description">' . __( 'Enter the label for the post views counter field.', 'post-views-counter' ) . '</p>
|
264 |
-
</fieldset>
|
265 |
-
</div>';
|
266 |
-
}
|
267 |
|
268 |
-
|
269 |
-
|
270 |
-
*/
|
271 |
-
public function post_types_count() {
|
272 |
-
echo '
|
273 |
-
<div id="pvc_post_types_count">';
|
274 |
|
275 |
-
|
276 |
-
|
277 |
-
|
278 |
-
|
279 |
|
280 |
-
|
281 |
-
<p class="description">' . __( 'Select post types for which post views will be counted.', 'post-views-counter' ) . '</p>
|
282 |
-
</div>';
|
283 |
-
}
|
284 |
|
285 |
-
|
286 |
-
|
287 |
-
|
288 |
-
|
289 |
-
|
290 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
291 |
|
292 |
-
|
293 |
-
|
294 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
295 |
}
|
296 |
|
297 |
-
|
298 |
-
<p class="description">' . __( 'Select post types for which the views count will be displayed.', 'post-views-counter' ) . '</p>
|
299 |
-
</div>';
|
300 |
}
|
301 |
|
302 |
/**
|
303 |
-
*
|
|
|
|
|
|
|
|
|
304 |
*/
|
305 |
-
public function
|
306 |
-
|
307 |
-
|
308 |
|
309 |
-
|
310 |
-
$
|
311 |
|
312 |
-
|
313 |
-
|
314 |
-
}
|
315 |
|
316 |
-
|
317 |
-
|
318 |
-
|
|
|
319 |
}
|
320 |
|
321 |
/**
|
322 |
-
*
|
|
|
|
|
|
|
|
|
323 |
*/
|
324 |
-
public function
|
325 |
-
|
326 |
-
|
327 |
-
|
328 |
-
|
329 |
}
|
330 |
|
331 |
/**
|
332 |
-
*
|
|
|
|
|
|
|
333 |
*/
|
334 |
-
public function
|
335 |
-
|
336 |
-
|
337 |
-
<input size="4" type="text" name="post_views_counter_settings_general[time_between_counts][number]" value="' . esc_attr( Post_Views_Counter()->options['general']['time_between_counts']['number'] ) . '" />
|
338 |
-
<select class="pvc-chosen-short" name="post_views_counter_settings_general[time_between_counts][type]">';
|
339 |
|
340 |
-
|
341 |
-
|
342 |
-
|
|
|
|
|
|
|
343 |
}
|
344 |
|
345 |
-
|
346 |
-
</select>
|
347 |
-
<p class="description">' . __( 'Enter the time between single user visit count.', 'post-views-counter' ) . '</p>
|
348 |
-
</div>';
|
349 |
}
|
350 |
|
351 |
/**
|
352 |
-
*
|
|
|
|
|
|
|
|
|
353 |
*/
|
354 |
-
public function
|
355 |
-
|
356 |
-
|
357 |
-
<input size="4" type="text" name="post_views_counter_settings_general[reset_counts][number]" value="' . esc_attr( Post_Views_Counter()->options['general']['reset_counts']['number'] ) . '" />
|
358 |
-
<select class="pvc-chosen-short" name="post_views_counter_settings_general[reset_counts][type]">';
|
359 |
|
360 |
-
|
361 |
-
|
362 |
-
|
|
|
363 |
}
|
364 |
|
365 |
-
|
366 |
-
|
367 |
-
|
368 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
369 |
}
|
370 |
|
371 |
/**
|
372 |
-
*
|
|
|
|
|
|
|
373 |
*/
|
374 |
-
public function
|
375 |
-
|
376 |
-
|
377 |
-
|
378 |
-
|
|
|
|
|
379 |
|
380 |
foreach ( $this->time_types as $type => $type_name ) {
|
381 |
-
|
382 |
-
|
383 |
}
|
384 |
|
385 |
-
|
386 |
-
|
387 |
-
|
388 |
-
|
|
|
389 |
}
|
390 |
|
391 |
/**
|
392 |
-
*
|
|
|
|
|
|
|
|
|
393 |
*/
|
394 |
-
public function
|
395 |
-
|
396 |
-
|
397 |
-
<fieldset>';
|
398 |
|
399 |
-
|
400 |
-
|
401 |
-
<label><input id="pvc_exclude-' . $type . '" type="checkbox" name="post_views_counter_settings_general[exclude][groups][' . $type . ']" value="1" ' . checked( in_array( $type, Post_Views_Counter()->options['general']['exclude']['groups'], true ), true, false ) . ' />' . esc_html( $type_name ) . '</label>';
|
402 |
-
}
|
403 |
|
404 |
-
|
405 |
-
|
406 |
-
<div class="pvc_user_roles"' . (in_array( 'roles', Post_Views_Counter()->options['general']['exclude']['groups'], true ) ? '' : ' style="display: none;"') . '>';
|
407 |
|
408 |
-
|
409 |
-
|
410 |
-
<label><input type="checkbox" name="post_views_counter_settings_general[exclude][roles][' . $role . ']" value="1" ' . checked( in_array( $role, Post_Views_Counter()->options['general']['exclude']['roles'], true ), true, false ) . '>' . esc_html( $role_name ) . '</label>';
|
411 |
-
}
|
412 |
|
413 |
-
|
414 |
-
<p class="description">' . __( 'Use it exclude specific user roles from post views count.', 'post-views-counter' ) . '</p>
|
415 |
-
</div>
|
416 |
-
</fieldset>
|
417 |
-
</div>';
|
418 |
}
|
419 |
|
420 |
/**
|
421 |
-
*
|
|
|
|
|
|
|
422 |
*/
|
423 |
-
public function
|
424 |
-
//
|
425 |
-
$
|
426 |
|
427 |
-
|
428 |
-
<
|
|
|
429 |
|
430 |
-
|
431 |
-
|
432 |
-
|
433 |
-
<div class="ip-box">
|
434 |
-
<input type="text" name="post_views_counter_settings_general[exclude_ips][]" value="' . esc_attr( $ip ) . '" /> <a href="#" class="remove-exclude-ip" title="' . esc_attr__( 'Remove', 'post-views-counter' ) . '">' . esc_attr__( 'Remove', 'post-views-counter' ) . '</a>
|
435 |
-
</div>';
|
436 |
-
}
|
437 |
-
} else {
|
438 |
-
echo '
|
439 |
-
<div class="ip-box">
|
440 |
-
<input type="text" name="post_views_counter_settings_general[exclude_ips][]" value="" /> <a href="#" class="remove-exclude-ip" title="' . esc_attr__( 'Remove', 'post-views-counter' ) . '">' . esc_attr__( 'Remove', 'post-views-counter' ) . '</a>
|
441 |
-
</div>';
|
442 |
}
|
443 |
|
444 |
-
|
445 |
-
|
446 |
-
|
447 |
-
</div>';
|
448 |
-
}
|
449 |
|
450 |
-
|
451 |
-
* Strict counts option.
|
452 |
-
*/
|
453 |
-
public function strict_counts() {
|
454 |
-
echo '
|
455 |
-
<div id="pvc_strict_counts">
|
456 |
-
<label><input id="pvc-strict-counts" type="checkbox" name="post_views_counter_settings_general[strict_counts]" value="1" ' . checked( true, Post_Views_Counter()->options['general']['strict_counts'], false ) . ' />' . __( 'Enable to prevent bypassing the counts interval (for e.g. using incognito browser window or by clearing cookies).', 'post-views-counter' ) . '</label>
|
457 |
-
</div>';
|
458 |
}
|
459 |
|
460 |
/**
|
461 |
-
*
|
|
|
|
|
|
|
|
|
462 |
*/
|
463 |
-
public function
|
464 |
-
|
465 |
-
|
466 |
-
<fieldset>
|
467 |
-
<input type="submit" class="button button-secondary" name="post_views_counter_import_wp_postviews" value="' . __( 'Import views', 'post-views-counter' ) . '"/> <label><input id="pvc-wp-postviews" type="checkbox" name="post_views_counter_import_wp_postviews_override" value="1" />' . __( 'Override existing views data.', 'post-views-counter' ) . '</label>
|
468 |
-
<p class="description">' . __( 'Import post views data from WP-PostViews plugin.', 'post-views-counter' ) . '</p>
|
469 |
-
<br /><input type="submit" class="button button-secondary" name="post_views_counter_reset_views" value="' . __( 'Delete views', 'post-views-counter' ) . '"/>
|
470 |
-
<p class="description">' . __( 'Delete ALL the existing post views data.', 'post-views-counter' ) . '</p>
|
471 |
-
</fieldset>
|
472 |
-
</div>';
|
473 |
-
}
|
474 |
|
475 |
-
|
476 |
-
|
477 |
-
*/
|
478 |
-
public function restrict_edit_views() {
|
479 |
-
echo '
|
480 |
-
<div id="pvc_restrict_edit_views">
|
481 |
-
<label><input type="checkbox" name="post_views_counter_settings_general[restrict_edit_views]" value="1" ' . checked( true, Post_Views_Counter()->options['general']['restrict_edit_views'], false ) . ' />' . __( 'Enable to restrict post views editing to admins only.', 'post-views-counter' ) . '</label>
|
482 |
-
</div>';
|
483 |
-
}
|
484 |
|
485 |
-
|
486 |
-
|
487 |
-
*/
|
488 |
-
public function deactivation_delete() {
|
489 |
-
echo '
|
490 |
-
<div id="pvc_deactivation_delete">
|
491 |
-
<label><input type="checkbox" name="post_views_counter_settings_general[deactivation_delete]" value="1" ' . checked( true, Post_Views_Counter()->options['general']['deactivation_delete'], false ) . ' />' . __( 'Enable to delete all plugin data on deactivation.', 'post-views-counter' ) . '</label>
|
492 |
-
</div>';
|
493 |
-
}
|
494 |
|
495 |
-
|
496 |
-
|
497 |
-
*/
|
498 |
-
public function page_types_display() {
|
499 |
-
echo '
|
500 |
-
<div id="pvc_post_types_display">';
|
501 |
|
502 |
-
|
503 |
-
|
504 |
-
|
505 |
-
|
|
|
506 |
|
507 |
-
|
508 |
-
<p class="description">' . __( 'Select page types where the views count will be displayed.', 'post-views-counter' ) . '</p>
|
509 |
-
</div>';
|
510 |
}
|
511 |
|
512 |
/**
|
513 |
-
*
|
|
|
|
|
|
|
514 |
*/
|
515 |
-
public function
|
516 |
-
|
517 |
-
|
518 |
-
|
519 |
-
|
520 |
-
|
521 |
-
|
522 |
-
|
|
|
|
|
|
|
523 |
}
|
524 |
|
525 |
-
|
526 |
-
|
527 |
-
|
528 |
-
|
|
|
529 |
}
|
530 |
|
531 |
/**
|
532 |
-
*
|
|
|
|
|
|
|
|
|
533 |
*/
|
534 |
-
public function
|
535 |
-
|
536 |
-
|
537 |
|
538 |
-
|
539 |
-
|
540 |
|
541 |
-
|
542 |
-
|
543 |
-
}
|
544 |
|
545 |
-
|
546 |
-
|
547 |
-
</div>';
|
548 |
-
}
|
549 |
|
550 |
-
|
551 |
-
|
552 |
-
|
553 |
-
|
554 |
-
|
555 |
-
|
556 |
-
<input type="text" name="post_views_counter_settings_display[icon_class]" class="large-text" value="' . esc_attr( Post_Views_Counter()->options['display']['icon_class'] ) . '" />
|
557 |
-
<p class="description">' . sprintf( __( 'Enter the post views icon class. Any of the <a href="%s" target="_blank">Dashicons</a> classes are available.', 'post-views-counter' ), 'https://developer.wordpress.org/resource/dashicons/' ) . '</p>
|
558 |
-
</div>';
|
559 |
-
}
|
560 |
|
561 |
-
|
562 |
-
|
563 |
-
|
564 |
-
|
565 |
-
echo '
|
566 |
-
<div id="pvc_toolbar_statistics">
|
567 |
-
<label><input type="checkbox" name="post_views_counter_settings_display[toolbar_statistics]" value="1" ' . checked( true, Post_Views_Counter()->options['display']['toolbar_statistics'], false ) . ' />' . __( 'Enable to display the post views chart at the toolbar.', 'post-views-counter' ) . '</label>
|
568 |
-
<p class="description">' . __( 'The post views chart will be displayed for the post types that are being counted.', 'post-views-counter' ) . '</p>
|
569 |
-
</div>';
|
570 |
}
|
571 |
|
572 |
/**
|
573 |
-
*
|
|
|
|
|
574 |
*/
|
575 |
-
public function
|
576 |
-
|
577 |
-
|
578 |
-
<fieldset>';
|
579 |
-
|
580 |
-
foreach ( $this->groups as $type => $type_name ) {
|
581 |
|
582 |
-
|
583 |
-
continue;
|
584 |
|
585 |
-
|
586 |
-
|
|
|
587 |
}
|
588 |
|
589 |
-
|
590 |
-
|
591 |
-
|
592 |
|
593 |
foreach ( $this->user_roles as $role => $role_name ) {
|
594 |
-
|
595 |
-
|
596 |
}
|
597 |
|
598 |
-
|
599 |
-
|
600 |
-
|
601 |
-
|
602 |
-
|
603 |
}
|
604 |
|
605 |
/**
|
606 |
-
* Validate
|
|
|
|
|
|
|
|
|
607 |
*/
|
608 |
-
public function
|
609 |
// get main instance
|
610 |
$pvc = Post_Views_Counter();
|
611 |
|
612 |
-
//
|
613 |
-
if ( isset( $
|
614 |
-
|
615 |
-
$input = $pvc->options['general'];
|
616 |
-
|
617 |
-
global $wpdb;
|
618 |
-
|
619 |
-
$meta_key = esc_attr( apply_filters( 'pvc_import_meta_key', 'views' ) );
|
620 |
|
621 |
-
|
622 |
-
|
623 |
-
|
624 |
-
$sql = array();
|
625 |
-
|
626 |
-
foreach ( $views as $view ) {
|
627 |
-
$sql[] = "(" . $view['post_id'] . ", 4, 'total', " . $view['meta_value'] . ")";
|
628 |
-
}
|
629 |
-
|
630 |
-
$wpdb->query( "INSERT INTO " . $wpdb->prefix . "post_views(id, type, period, count) VALUES " . implode( ',', $sql ) . " ON DUPLICATE KEY UPDATE count = " . ( isset( $_POST['post_views_counter_import_wp_postviews_override'] ) ? '' : 'count + ' ) . "VALUES(count)" );
|
631 |
-
|
632 |
-
add_settings_error( 'wp_postviews_import', 'wp_postviews_import', __( 'Post views data imported succesfully.', 'post-views-counter' ), 'updated' );
|
633 |
-
} else {
|
634 |
-
add_settings_error( 'wp_postviews_import', 'wp_postviews_import', __( 'There was no post views data to import.', 'post-views-counter' ), 'updated' );
|
635 |
}
|
636 |
-
// delete all post views data
|
637 |
-
} elseif ( isset( $_POST['post_views_counter_reset_views'] ) ) {
|
638 |
-
// make sure we do not change anything in the settings
|
639 |
-
$input = $pvc->options['general'];
|
640 |
-
|
641 |
-
global $wpdb;
|
642 |
-
|
643 |
-
if ( $wpdb->query( 'TRUNCATE TABLE ' . $wpdb->prefix . 'post_views' ) )
|
644 |
-
add_settings_error( 'reset_post_views', 'reset_post_views', __( 'All existing data deleted succesfully.', 'post-views-counter' ), 'updated' );
|
645 |
-
else
|
646 |
-
add_settings_error( 'reset_post_views', 'reset_post_views', __( 'Error occurred. All existing data were not deleted.', 'post-views-counter' ), 'error' );
|
647 |
-
// save general settings
|
648 |
-
} elseif ( isset( $_POST['save_pvc_general'] ) ) {
|
649 |
-
// post types count
|
650 |
-
if ( isset( $input['post_types_count'] ) ) {
|
651 |
-
$post_types = array();
|
652 |
-
|
653 |
-
foreach ( $input['post_types_count'] as $post_type => $set ) {
|
654 |
-
if ( isset( $this->post_types[$post_type] ) )
|
655 |
-
$post_types[] = $post_type;
|
656 |
-
}
|
657 |
-
|
658 |
-
$input['post_types_count'] = array_unique( $post_types );
|
659 |
-
} else
|
660 |
-
$input['post_types_count'] = array();
|
661 |
|
662 |
-
|
663 |
-
|
|
|
664 |
|
665 |
-
|
666 |
-
|
|
|
667 |
|
668 |
-
|
669 |
-
|
670 |
-
|
671 |
-
|
672 |
-
// flush interval
|
673 |
-
$input['flush_interval']['number'] = (int) ( isset( $input['flush_interval']['number'] ) ? $input['flush_interval']['number'] : $pvc->defaults['general']['flush_interval']['number'] );
|
674 |
-
$input['flush_interval']['type'] = isset( $input['flush_interval']['type'], $this->time_types[$input['flush_interval']['type']] ) ? $input['flush_interval']['type'] : $pvc->defaults['general']['flush_interval']['type'];
|
675 |
-
|
676 |
-
// Since the settings are about to be saved and cache flush interval could've changed,
|
677 |
-
// we want to make sure that any changes done on the settings page are in effect immediately
|
678 |
-
// (instead of having to wait for the previous schedule to occur).
|
679 |
-
// We achieve that by making sure to clear any previous cache flush schedules and
|
680 |
-
// schedule the new one if the specified interval is > 0
|
681 |
-
$pvc->remove_cache_flush();
|
682 |
-
|
683 |
-
if ( $input['flush_interval']['number'] > 0 )
|
684 |
-
$pvc->schedule_cache_flush();
|
685 |
|
686 |
-
|
687 |
-
|
688 |
-
$input['
|
689 |
|
690 |
-
|
691 |
-
|
692 |
-
$input['cron_update'] = ( $input['cron_run'] && ( $pvc->options['general']['reset_counts']['number'] !== $input['reset_counts']['number'] || $pvc->options['general']['reset_counts']['type'] !== $input['reset_counts']['type'] ) );
|
693 |
|
694 |
-
|
695 |
-
|
696 |
-
|
|
|
|
|
|
|
|
|
697 |
|
698 |
-
|
699 |
-
if ( isset( $this->groups[$group] ) )
|
700 |
-
$groups[] = $group;
|
701 |
-
}
|
702 |
|
703 |
-
|
704 |
-
|
705 |
-
$
|
|
|
|
|
|
|
706 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
707 |
|
708 |
-
|
709 |
-
|
|
|
710 |
|
711 |
-
|
712 |
-
|
713 |
-
$roles[] = $role;
|
714 |
-
}
|
715 |
|
716 |
-
|
717 |
-
|
718 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
719 |
|
720 |
-
|
721 |
-
|
722 |
-
|
723 |
|
724 |
-
|
725 |
-
|
726 |
-
|
727 |
|
728 |
-
|
729 |
-
$ips[] = $ip;
|
730 |
-
} elseif ( filter_var( $ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4 ) )
|
731 |
$ips[] = $ip;
|
732 |
-
}
|
733 |
-
|
734 |
-
$input['exclude_ips'] = array_unique( $ips );
|
735 |
}
|
736 |
|
737 |
-
|
738 |
-
|
739 |
-
|
740 |
-
// strict counts
|
741 |
-
$input['strict_counts'] = isset( $input['strict_counts'] );
|
742 |
-
|
743 |
-
// deactivation delete
|
744 |
-
$input['deactivation_delete'] = isset( $input['deactivation_delete'] );
|
745 |
-
|
746 |
-
$input['update_version'] = $pvc->options['general']['update_version'];
|
747 |
-
$input['update_notice'] = $pvc->options['general']['update_notice'];
|
748 |
-
// save display settings
|
749 |
-
} elseif ( isset( $_POST['save_pvc_display'] ) ) {
|
750 |
-
// post views label
|
751 |
-
$input['label'] = isset( $input['label'] ) ? $input['label'] : $pvc->defaults['display']['label'];
|
752 |
-
|
753 |
-
if ( function_exists( 'icl_register_string' ) )
|
754 |
-
icl_register_string( 'Post Views Counter', 'Post Views Label', $input['label'] );
|
755 |
-
|
756 |
-
// position
|
757 |
-
$input['position'] = isset( $input['position'], $this->positions[$input['position']] ) ? $input['position'] : $pvc->defaults['display']['position'];
|
758 |
-
|
759 |
-
// display style
|
760 |
-
$input['display_style']['icon'] = isset( $input['display_style']['icon'] );
|
761 |
-
$input['display_style']['text'] = isset( $input['display_style']['text'] );
|
762 |
|
763 |
-
|
764 |
-
|
765 |
|
766 |
-
|
767 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
768 |
|
769 |
-
|
770 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
771 |
|
772 |
-
|
773 |
-
if ( isset( $input['post_types_display'] ) ) {
|
774 |
-
$post_types = array();
|
775 |
|
776 |
-
|
777 |
-
|
778 |
-
|
779 |
-
}
|
780 |
|
781 |
-
|
782 |
-
|
783 |
-
|
784 |
|
785 |
-
|
786 |
-
|
787 |
-
|
788 |
|
789 |
-
|
790 |
-
|
791 |
-
|
792 |
-
|
793 |
|
794 |
-
|
795 |
-
|
796 |
-
|
797 |
|
798 |
-
|
799 |
-
|
800 |
-
$groups = array();
|
801 |
|
802 |
-
|
803 |
-
|
804 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
805 |
|
806 |
-
|
807 |
-
|
808 |
-
|
809 |
|
810 |
-
|
811 |
-
|
812 |
-
|
813 |
|
814 |
-
|
815 |
-
|
|
|
816 |
|
817 |
-
|
818 |
-
|
819 |
-
|
820 |
-
}
|
821 |
|
822 |
-
|
823 |
-
|
824 |
-
|
825 |
-
// reset general settings
|
826 |
-
} elseif ( isset( $_POST['reset_pvc_general'] ) ) {
|
827 |
-
$input = $pvc->defaults['general'];
|
828 |
|
829 |
-
|
830 |
-
|
831 |
-
|
832 |
-
|
833 |
|
834 |
-
|
835 |
-
}
|
|
|
836 |
|
837 |
return $input;
|
838 |
}
|
10 |
*/
|
11 |
class Post_Views_Counter_Settings {
|
12 |
|
|
|
|
|
|
|
13 |
private $time_types;
|
14 |
private $groups;
|
15 |
private $user_roles;
|
|
|
|
|
16 |
public $post_types;
|
17 |
public $page_types;
|
18 |
|
19 |
public function __construct() {
|
20 |
// actions
|
21 |
+
add_action( 'after_setup_theme', [ $this, 'load_defaults' ] );
|
22 |
+
add_action( 'wp_loaded', [ $this, 'load_post_types' ] );
|
23 |
+
|
24 |
+
// filters
|
25 |
+
add_filter( 'post_views_counter_settings_data', [ $this, 'settings_data' ] );
|
26 |
+
add_filter( 'post_views_counter_settings_pages', [ $this, 'settings_page' ] );
|
27 |
}
|
28 |
|
29 |
/**
|
30 |
* Load default settings.
|
31 |
+
*
|
32 |
+
* @return void
|
33 |
*/
|
34 |
public function load_defaults() {
|
35 |
if ( ! is_admin() )
|
36 |
return;
|
37 |
|
38 |
+
$this->time_types = [
|
39 |
+
'minutes' => __( 'minutes', 'post-views-counter' ),
|
40 |
+
'hours' => __( 'hours', 'post-views-counter' ),
|
41 |
+
'days' => __( 'days', 'post-views-counter' ),
|
42 |
+
'weeks' => __( 'weeks', 'post-views-counter' ),
|
43 |
+
'months' => __( 'months', 'post-views-counter' ),
|
44 |
+
'years' => __( 'years', 'post-views-counter' )
|
45 |
+
];
|
46 |
+
|
47 |
+
$this->groups = [
|
48 |
+
'robots' => __( 'robots', 'post-views-counter' ),
|
49 |
+
'users' => __( 'logged in users', 'post-views-counter' ),
|
50 |
+
'guests' => __( 'guests', 'post-views-counter' ),
|
51 |
+
'roles' => __( 'selected user roles', 'post-views-counter' )
|
52 |
+
];
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
53 |
|
54 |
$this->user_roles = $this->get_user_roles();
|
55 |
|
56 |
$this->page_types = apply_filters(
|
57 |
'pvc_page_types_display_options',
|
58 |
+
[
|
59 |
+
'home' => __( 'Home', 'post-views-counter' ),
|
60 |
+
'archive' => __( 'Archives', 'post-views-counter' ),
|
61 |
+
'singular' => __( 'Single pages', 'post-views-counter' ),
|
62 |
+
'search' => __( 'Search results', 'post-views-counter' ),
|
63 |
+
]
|
64 |
);
|
65 |
}
|
66 |
|
67 |
/**
|
68 |
* Get post types avaiable for counting.
|
69 |
+
*
|
70 |
+
* @return void
|
71 |
*/
|
72 |
public function load_post_types() {
|
73 |
if ( ! is_admin() )
|
74 |
return;
|
75 |
|
76 |
+
$post_types = [];
|
77 |
|
78 |
// built in public post types
|
79 |
+
foreach ( get_post_types( [ '_builtin' => true, 'public' => true ], 'objects', 'and' ) as $key => $post_type ) {
|
80 |
$post_types[$key] = $post_type->labels->name;
|
81 |
}
|
82 |
|
83 |
// public custom post types
|
84 |
+
foreach ( get_post_types( [ '_builtin' => false, 'public' => true ], 'objects', 'and' ) as $key => $post_type ) {
|
85 |
$post_types[$key] = $post_type->labels->name;
|
86 |
}
|
87 |
|
89 |
if ( class_exists( 'bbPress' ) && isset( $post_types['reply'] ) )
|
90 |
unset( $post_types['reply'] );
|
91 |
|
92 |
+
$post_types = apply_filters( 'pvc_available_post_types', $post_types );
|
93 |
|
94 |
// sort post types alphabetically with their keys
|
95 |
asort( $post_types, SORT_STRING );
|
106 |
public function get_user_roles() {
|
107 |
global $wp_roles;
|
108 |
|
109 |
+
$roles = [];
|
110 |
|
111 |
foreach ( apply_filters( 'editable_roles', $wp_roles->roles ) as $role => $details ) {
|
112 |
$roles[$role] = translate_user_role( $details['name'] );
|
118 |
}
|
119 |
|
120 |
/**
|
121 |
+
* Add settings data.
|
122 |
*
|
123 |
+
* @param array $settings
|
124 |
+
* @return array
|
125 |
*/
|
126 |
+
public function settings_data( $settings ) {
|
127 |
+
$modes = [
|
128 |
+
'php' => __( 'PHP', 'post-views-counter' ),
|
129 |
+
'js' => __( 'JavaScript', 'post-views-counter' ),
|
130 |
+
'ajax' => __( 'Fast AJAX', 'post-views-counter' )
|
131 |
+
];
|
132 |
+
|
133 |
+
// WordPress 4.4+?
|
134 |
+
if ( function_exists( 'register_rest_route' ) )
|
135 |
+
$modes['rest_api'] = __( 'REST API', 'post-views-counter' );
|
136 |
+
|
137 |
+
$settings['post-views-counter'] = [
|
138 |
+
'label' => __( 'Post Views Counter Settings', 'post-views-counter' ),
|
139 |
+
'option_name' => [
|
140 |
+
'general' => 'post_views_counter_settings_general',
|
141 |
+
'display' => 'post_views_counter_settings_display'
|
142 |
+
],
|
143 |
+
'validate' => [ $this, 'validate_settings' ],
|
144 |
+
'sections' => [
|
145 |
+
'post_views_counter_general_settings' => [],
|
146 |
+
'post_views_counter_display_settings' => []
|
147 |
+
],
|
148 |
+
'fields' => [
|
149 |
+
'post_types_count' => [
|
150 |
+
'tab' => 'general',
|
151 |
+
'title' => __( 'Post Types Count', 'post-views-counter' ),
|
152 |
+
'section' => 'post_views_counter_general_settings',
|
153 |
+
'type' => 'checkbox',
|
154 |
+
'display_type' => 'horizontal',
|
155 |
+
'description' => __( 'Select post types for which post views will be counted.', 'post-views-counter' ),
|
156 |
+
'options' => $this->post_types
|
157 |
+
],
|
158 |
+
'counter_mode' => [
|
159 |
+
'tab' => 'general',
|
160 |
+
'title' => __( 'Counter Mode', 'post-views-counter' ),
|
161 |
+
'section' => 'post_views_counter_general_settings',
|
162 |
+
'type' => 'radio',
|
163 |
+
'description' => __( 'Select the method of collecting post views data. If you are using any of the caching plugins select Javascript or REST API (if available).', 'post-views-counter' ) . '<br />' . __( 'Optionally try the Fast AJAX experimental method, usually 10+ times faster than Javascript or REST API.', 'post-views-counter' ),
|
164 |
+
'options' => $modes
|
165 |
+
],
|
166 |
+
'post_views_column' => [
|
167 |
+
'tab' => 'general',
|
168 |
+
'title' => __( 'Post Views Column', 'post-views-counter' ),
|
169 |
+
'section' => 'post_views_counter_general_settings',
|
170 |
+
'type' => 'boolean',
|
171 |
+
'description' => '',
|
172 |
+
'label' => __( 'Enable to display post views count column for each of the selected post types.', 'post-views-counter' )
|
173 |
+
],
|
174 |
+
'restrict_edit_views' => [
|
175 |
+
'tab' => 'general',
|
176 |
+
'title' => __( 'Restrict Edit', 'post-views-counter' ),
|
177 |
+
'section' => 'post_views_counter_general_settings',
|
178 |
+
'type' => 'boolean',
|
179 |
+
'description' => '',
|
180 |
+
'label' => __( 'Enable to restrict post views editing to admins only.', 'post-views-counter' )
|
181 |
+
],
|
182 |
+
'time_between_counts' => [
|
183 |
+
'tab' => 'general',
|
184 |
+
'title' => __( 'Count Interval', 'post-views-counter' ),
|
185 |
+
'section' => 'post_views_counter_general_settings',
|
186 |
+
'type' => 'custom',
|
187 |
+
'description' => '',
|
188 |
+
'min' => 0,
|
189 |
+
'max' => 999999,
|
190 |
+
'callback' => [ $this, 'setting_time_between_counts' ],
|
191 |
+
'validate' => [ $this, 'validate_time_between_counts' ]
|
192 |
+
],
|
193 |
+
'reset_counts' => [
|
194 |
+
'tab' => 'general',
|
195 |
+
'title' => __( 'Reset Data Interval', 'post-views-counter' ),
|
196 |
+
'section' => 'post_views_counter_general_settings',
|
197 |
+
'type' => 'custom',
|
198 |
+
'description' => '',
|
199 |
+
'min' => 0,
|
200 |
+
'max' => 999999,
|
201 |
+
'callback' => [ $this, 'setting_reset_counts' ],
|
202 |
+
'validate' => [ $this, 'validate_reset_counts' ]
|
203 |
+
],
|
204 |
+
'flush_interval' => [
|
205 |
+
'tab' => 'general',
|
206 |
+
'title' => __( 'Flush Object Cache Interval', 'post-views-counter' ),
|
207 |
+
'section' => 'post_views_counter_general_settings',
|
208 |
+
'type' => 'custom',
|
209 |
+
'description' => '',
|
210 |
+
'min' => 0,
|
211 |
+
'max' => 999999,
|
212 |
+
'callback' => [ $this, 'setting_flush_interval' ],
|
213 |
+
'validate' => [ $this, 'validate_flush_interval' ]
|
214 |
+
],
|
215 |
+
'exclude' => [
|
216 |
+
'tab' => 'general',
|
217 |
+
'title' => __( 'Exclude Visitors', 'post-views-counter' ),
|
218 |
+
'section' => 'post_views_counter_general_settings',
|
219 |
+
'type' => 'custom',
|
220 |
+
'description' => '',
|
221 |
+
'callback' => [ $this, 'setting_exclude' ],
|
222 |
+
'validate' => [ $this, 'validate_exclude' ]
|
223 |
+
],
|
224 |
+
'exclude_ips' => [
|
225 |
+
'tab' => 'general',
|
226 |
+
'title' => __( 'Exclude IPs', 'post-views-counter' ),
|
227 |
+
'section' => 'post_views_counter_general_settings',
|
228 |
+
'type' => 'custom',
|
229 |
+
'description' => '',
|
230 |
+
'callback' => [ $this, 'setting_exclude_ips' ],
|
231 |
+
'validate' => [ $this, 'validate_exclude_ips' ]
|
232 |
+
],
|
233 |
+
'strict_counts' => [
|
234 |
+
'tab' => 'general',
|
235 |
+
'title' => __( 'Strict counts', 'post-views-counter' ),
|
236 |
+
'section' => 'post_views_counter_general_settings',
|
237 |
+
'type' => 'boolean',
|
238 |
+
'description' => '',
|
239 |
+
'label' => __( 'Enable to prevent bypassing the counts interval (for e.g. using incognito browser window or by clearing cookies).', 'post-views-counter' )
|
240 |
+
],
|
241 |
+
'wp_postviews' => [
|
242 |
+
'tab' => 'general',
|
243 |
+
'title' => __( 'Tools', 'post-views-counter' ),
|
244 |
+
'section' => 'post_views_counter_general_settings',
|
245 |
+
'type' => 'custom',
|
246 |
+
'description' => '',
|
247 |
+
'skip_saving' => true,
|
248 |
+
'callback' => [ $this, 'setting_wp_postviews' ]
|
249 |
+
],
|
250 |
+
'deactivation_delete' => [
|
251 |
+
'tab' => 'general',
|
252 |
+
'title' => __( 'Deactivation', 'post-views-counter' ),
|
253 |
+
'section' => 'post_views_counter_general_settings',
|
254 |
+
'type' => 'boolean',
|
255 |
+
'description' => '',
|
256 |
+
'label' => __( 'Enable to delete all plugin data on deactivation.', 'post-views-counter' )
|
257 |
+
],
|
258 |
+
'label' => [
|
259 |
+
'tab' => 'display',
|
260 |
+
'title' => __( 'Post Views Label', 'post-views-counter' ),
|
261 |
+
'section' => 'post_views_counter_display_settings',
|
262 |
+
'type' => 'input',
|
263 |
+
'description' => __( 'Enter the label for the post views counter field.', 'post-views-counter' ),
|
264 |
+
'subclass' => 'regular-text',
|
265 |
+
'validate' => [ $this, 'validate_label' ],
|
266 |
+
'reset' => [ $this, 'reset_label' ]
|
267 |
+
],
|
268 |
+
'post_types_display' => [
|
269 |
+
'tab' => 'display',
|
270 |
+
'title' => __( 'Post Type', 'post-views-counter' ),
|
271 |
+
'section' => 'post_views_counter_display_settings',
|
272 |
+
'type' => 'checkbox',
|
273 |
+
'display_type' => 'horizontal',
|
274 |
+
'description' => __( 'Select post types for which the views count will be displayed.', 'post-views-counter' ),
|
275 |
+
'options' => $this->post_types
|
276 |
+
],
|
277 |
+
'page_types_display' => [
|
278 |
+
'tab' => 'display',
|
279 |
+
'title' => __( 'Page Type', 'post-views-counter' ),
|
280 |
+
'section' => 'post_views_counter_display_settings',
|
281 |
+
'type' => 'checkbox',
|
282 |
+
'display_type' => 'horizontal',
|
283 |
+
'description' => __( 'Select page types where the views count will be displayed.', 'post-views-counter' ),
|
284 |
+
'options' => $this->page_types
|
285 |
+
],
|
286 |
+
'restrict_display' => [
|
287 |
+
'tab' => 'display',
|
288 |
+
'title' => __( 'User Type', 'post-views-counter' ),
|
289 |
+
'section' => 'post_views_counter_display_settings',
|
290 |
+
'type' => 'custom',
|
291 |
+
'description' => '',
|
292 |
+
'callback' => [ $this, 'setting_restrict_display' ],
|
293 |
+
'validate' => [ $this, 'validate_restrict_display' ]
|
294 |
+
],
|
295 |
+
'position' => [
|
296 |
+
'tab' => 'display',
|
297 |
+
'title' => __( 'Position', 'post-views-counter' ),
|
298 |
+
'section' => 'post_views_counter_display_settings',
|
299 |
+
'type' => 'select',
|
300 |
+
'description' => __( 'Select where would you like to display the post views counter. Use [post-views] shortcode for manual display.', 'post-views-counter' ),
|
301 |
+
'options' => [
|
302 |
+
'before' => __( 'before the content', 'post-views-counter' ),
|
303 |
+
'after' => __( 'after the content', 'post-views-counter' ),
|
304 |
+
'manual' => __( 'manual', 'post-views-counter' )
|
305 |
+
]
|
306 |
+
],
|
307 |
+
'display_style' => [
|
308 |
+
'tab' => 'display',
|
309 |
+
'title' => __( 'Display Style', 'post-views-counter' ),
|
310 |
+
'section' => 'post_views_counter_display_settings',
|
311 |
+
'type' => 'custom',
|
312 |
+
'description' => __( 'Choose how to display the post views counter.', 'post-views-counter' ),
|
313 |
+
'callback' => [ $this, 'setting_display_style' ],
|
314 |
+
'validate' => [ $this, 'validate_display_style' ],
|
315 |
+
'options' => [
|
316 |
+
'icon' => __( 'icon', 'post-views-counter' ),
|
317 |
+
'text' => __( 'label', 'post-views-counter' )
|
318 |
+
]
|
319 |
+
],
|
320 |
+
'icon_class' => [
|
321 |
+
'tab' => 'display',
|
322 |
+
'title' => __( 'Icon Class', 'post-views-counter' ),
|
323 |
+
'section' => 'post_views_counter_display_settings',
|
324 |
+
'type' => 'input',
|
325 |
+
'description' => sprintf( __( 'Enter the post views icon class. Any of the <a href="%s" target="_blank">Dashicons</a> classes are available.', 'post-views-counter' ), 'https://developer.wordpress.org/resource/dashicons/' ),
|
326 |
+
'subclass' => 'regular-text'
|
327 |
+
],
|
328 |
+
'toolbar_statistics' => [
|
329 |
+
'tab' => 'display',
|
330 |
+
'title' => __( 'Toolbar Chart', 'post-views-counter' ),
|
331 |
+
'section' => 'post_views_counter_display_settings',
|
332 |
+
'type' => 'boolean',
|
333 |
+
'description' => __( 'The post views chart will be displayed for the post types that are being counted.', 'post-views-counter' ),
|
334 |
+
'label' => __( 'Enable to display the post views chart at the toolbar.', 'post-views-counter' )
|
335 |
+
]
|
336 |
+
]
|
337 |
+
];
|
338 |
+
|
339 |
+
return $settings;
|
340 |
}
|
341 |
|
342 |
/**
|
343 |
+
* Add settings page.
|
344 |
*
|
345 |
+
* @param array $pages
|
346 |
+
* @return array
|
347 |
*/
|
348 |
+
public function settings_page( $pages ) {
|
349 |
+
$pages['post-views-counter'] = [
|
350 |
+
'type' => 'settings_page',
|
351 |
+
'menu_slug' => 'post-views-counter',
|
352 |
+
'page_title' => __( 'Post Views Counter Settings', 'post-views-counter' ),
|
353 |
+
'menu_title' => __( 'Post Views Counter', 'post-views-counter' ),
|
354 |
+
'capability' => apply_filters( 'pvc_settings_capability', 'manage_options' ),
|
355 |
+
'callback' => null,
|
356 |
+
'tabs' => [
|
357 |
+
'general' => [
|
358 |
+
'label' => __( 'General', 'post-views-counter' ),
|
359 |
+
'option_name' => 'post_views_counter_settings_general'
|
360 |
+
],
|
361 |
+
'display' => [
|
362 |
+
'label' => __( 'Display', 'post-views-counter' ),
|
363 |
+
'option_name' => 'post_views_counter_settings_display'
|
364 |
+
]
|
365 |
+
]
|
366 |
+
];
|
367 |
+
|
368 |
+
return $pages;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
369 |
}
|
370 |
|
371 |
/**
|
372 |
+
* Validate options.
|
373 |
+
*
|
374 |
+
* @param array $input Settings data
|
375 |
+
* @return array
|
376 |
*/
|
377 |
+
public function validate_settings( $input ) {
|
378 |
+
// check capability
|
379 |
+
if ( ! current_user_can( 'manage_options' ) )
|
380 |
+
return $input;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
381 |
|
382 |
+
// get main instance
|
383 |
+
$pvc = Post_Views_Counter();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
384 |
|
385 |
+
// use internal settings API to validate settings first
|
386 |
+
$input = $pvc->settings_api->validate_settings( $input );
|
|
|
|
|
|
|
|
|
387 |
|
388 |
+
// import post views data from another plugin
|
389 |
+
if ( isset( $_POST['post_views_counter_import_wp_postviews'] ) ) {
|
390 |
+
// make sure we do not change anything in the settings
|
391 |
+
$input = $pvc->options['general'];
|
392 |
|
393 |
+
global $wpdb;
|
|
|
|
|
|
|
394 |
|
395 |
+
// get views key
|
396 |
+
$meta_key = esc_attr( apply_filters( 'pvc_import_meta_key', 'views' ) );
|
397 |
+
|
398 |
+
// get views
|
399 |
+
$views = $wpdb->get_results( "SELECT post_id, meta_value FROM " . $wpdb->postmeta . " WHERE meta_key = '" . $meta_key . "'", ARRAY_A, 0 );
|
400 |
+
|
401 |
+
// any views?
|
402 |
+
if ( ! empty( $views ) ) {
|
403 |
+
$sql = [];
|
404 |
+
|
405 |
+
foreach ( $views as $view ) {
|
406 |
+
$sql[] = "(" . $view['post_id'] . ", 4, 'total', " . ( (int) $view['meta_value'] ) . ")";
|
407 |
+
}
|
408 |
+
|
409 |
+
$wpdb->query( "INSERT INTO " . $wpdb->prefix . "post_views(id, type, period, count) VALUES " . implode( ',', $sql ) . " ON DUPLICATE KEY UPDATE count = " . ( isset( $_POST['post_views_counter_import_wp_postviews_override'] ) ? '' : 'count + ' ) . "VALUES(count)" );
|
410 |
|
411 |
+
add_settings_error( 'wp_postviews_import', 'wp_postviews_import', __( 'Post views data imported succesfully.', 'post-views-counter' ), 'updated' );
|
412 |
+
} else
|
413 |
+
add_settings_error( 'wp_postviews_import', 'wp_postviews_import', __( 'There was no post views data to import.', 'post-views-counter' ), 'updated' );
|
414 |
+
// delete all post views data
|
415 |
+
} elseif ( isset( $_POST['post_views_counter_reset_views'] ) ) {
|
416 |
+
// make sure we do not change anything in the settings
|
417 |
+
$input = $pvc->options['general'];
|
418 |
+
|
419 |
+
global $wpdb;
|
420 |
+
|
421 |
+
if ( $wpdb->query( 'TRUNCATE TABLE ' . $wpdb->prefix . 'post_views' ) )
|
422 |
+
add_settings_error( 'reset_post_views', 'reset_post_views', __( 'All existing data deleted succesfully.', 'post-views-counter' ), 'updated' );
|
423 |
+
else
|
424 |
+
add_settings_error( 'reset_post_views', 'reset_post_views', __( 'Error occurred. All existing data were not deleted.', 'post-views-counter' ), 'error' );
|
425 |
+
// save general settings
|
426 |
+
} elseif ( isset( $_POST['save_post_views_counter_settings_general'] ) ) {
|
427 |
+
$input['update_version'] = $pvc->options['general']['update_version'];
|
428 |
+
$input['update_notice'] = $pvc->options['general']['update_notice'];
|
429 |
+
$input['update_delay_date'] = $pvc->options['general']['update_delay_date'];
|
430 |
+
// reset general settings
|
431 |
+
} elseif ( isset( $_POST['reset_post_views_counter_settings_general'] ) ) {
|
432 |
+
$input['update_version'] = $pvc->options['general']['update_version'];
|
433 |
+
$input['update_notice'] = $pvc->options['general']['update_notice'];
|
434 |
+
$input['update_delay_date'] = $pvc->options['general']['update_delay_date'];
|
435 |
}
|
436 |
|
437 |
+
return $input;
|
|
|
|
|
438 |
}
|
439 |
|
440 |
/**
|
441 |
+
* Validate label.
|
442 |
+
*
|
443 |
+
* @param array $input Input POST data
|
444 |
+
* @param array $field Field options
|
445 |
+
* @return array
|
446 |
*/
|
447 |
+
public function validate_label( $input, $field ) {
|
448 |
+
// get main instance
|
449 |
+
$pvc = Post_Views_Counter();
|
450 |
|
451 |
+
if ( ! isset( $input ) )
|
452 |
+
$input = $pvc->defaults['display']['label'];
|
453 |
|
454 |
+
// use internal settings API to validate settings first
|
455 |
+
$input = $pvc->settings_api->validate_field( $input, 'input', $field );
|
|
|
456 |
|
457 |
+
if ( function_exists( 'icl_register_string' ) )
|
458 |
+
icl_register_string( 'Post Views Counter', 'Post Views Label', $input );
|
459 |
+
|
460 |
+
return $input;
|
461 |
}
|
462 |
|
463 |
/**
|
464 |
+
* Restore post views label to default value.
|
465 |
+
*
|
466 |
+
* @param array $default Default value
|
467 |
+
* @param array $field Field options
|
468 |
+
* @return array
|
469 |
*/
|
470 |
+
public function reset_label( $default, $field ) {
|
471 |
+
if ( function_exists( 'icl_register_string' ) )
|
472 |
+
icl_register_string( 'Post Views Counter', 'Post Views Label', $default );
|
473 |
+
|
474 |
+
return $default;
|
475 |
}
|
476 |
|
477 |
/**
|
478 |
+
* Setting: display style.
|
479 |
+
*
|
480 |
+
* @param array $field Field options
|
481 |
+
* @return string
|
482 |
*/
|
483 |
+
public function setting_display_style( $field ) {
|
484 |
+
// get main instance
|
485 |
+
$pvc = Post_Views_Counter();
|
|
|
|
|
486 |
|
487 |
+
$html = '
|
488 |
+
<input type="hidden" name="post_views_counter_settings_display[display_style]" value="empty" />';
|
489 |
+
|
490 |
+
foreach ( $field['options'] as $key => $label ) {
|
491 |
+
$html .= '
|
492 |
+
<label><input id="post_views_counter_display_display_style_' . esc_attr( $key ) . '" type="checkbox" name="post_views_counter_settings_display[display_style][]" value="' . esc_attr( $key ) . '" ' . checked( ! empty( $pvc->options['display']['display_style'][$key] ), true, false ) . ' />' . esc_html( $label ) . '</label> ';
|
493 |
}
|
494 |
|
495 |
+
return $html;
|
|
|
|
|
|
|
496 |
}
|
497 |
|
498 |
/**
|
499 |
+
* Validate display style.
|
500 |
+
*
|
501 |
+
* @param array $input Input POST data
|
502 |
+
* @param array $field Field options
|
503 |
+
* @return array
|
504 |
*/
|
505 |
+
public function validate_display_style( $input, $field ) {
|
506 |
+
// get main instance
|
507 |
+
$pvc = Post_Views_Counter();
|
|
|
|
|
508 |
|
509 |
+
$data = [];
|
510 |
+
|
511 |
+
foreach ( $field['options'] as $value => $label ) {
|
512 |
+
$data[$value] = false;
|
513 |
}
|
514 |
|
515 |
+
// any data?
|
516 |
+
if ( ! empty( $input['display_style'] && $input['display_style'] !== 'empty' && is_array( $input['display_style'] ) ) ) {
|
517 |
+
foreach ( $input['display_style'] as $value ) {
|
518 |
+
if ( array_key_exists( $value, $field['options'] ) )
|
519 |
+
$data[$value] = true;
|
520 |
+
}
|
521 |
+
}
|
522 |
+
|
523 |
+
$input['display_style'] = $data;
|
524 |
+
|
525 |
+
return $input;
|
526 |
}
|
527 |
|
528 |
/**
|
529 |
+
* Setting: count interval.
|
530 |
+
*
|
531 |
+
* @param array $field Field options
|
532 |
+
* @return string
|
533 |
*/
|
534 |
+
public function setting_time_between_counts( $field ) {
|
535 |
+
// get main instance
|
536 |
+
$pvc = Post_Views_Counter();
|
537 |
+
|
538 |
+
$html = '
|
539 |
+
<input size="6" type="number" min="' . ( (int) $field['min'] ) . '" max="' . ( (int) $field['max'] ) . '" name="post_views_counter_settings_general[time_between_counts][number]" value="' . esc_attr( $pvc->options['general']['time_between_counts']['number'] ) . '" />
|
540 |
+
<select class="pvc-chosen-short" name="post_views_counter_settings_general[time_between_counts][type]">';
|
541 |
|
542 |
foreach ( $this->time_types as $type => $type_name ) {
|
543 |
+
$html .= '
|
544 |
+
<option value="' . esc_attr( $type ) . '" ' . selected( $type, $pvc->options['general']['time_between_counts']['type'], false ) . '>' . esc_html( $type_name ) . '</option>';
|
545 |
}
|
546 |
|
547 |
+
$html .= '
|
548 |
+
</select>
|
549 |
+
<p class="description">' . __( 'Enter the time between single user visit count.', 'post-views-counter' ) . '</p>';
|
550 |
+
|
551 |
+
return $html;
|
552 |
}
|
553 |
|
554 |
/**
|
555 |
+
* Validate count interval.
|
556 |
+
*
|
557 |
+
* @param array $input Input POST data
|
558 |
+
* @param array $field Field options
|
559 |
+
* @return array
|
560 |
*/
|
561 |
+
public function validate_time_between_counts( $input, $field ) {
|
562 |
+
// get main instance
|
563 |
+
$pvc = Post_Views_Counter();
|
|
|
564 |
|
565 |
+
// number
|
566 |
+
$input['time_between_counts']['number'] = isset( $input['time_between_counts']['number'] ) ? (int) $input['time_between_counts']['number'] : $pvc->defaults['general']['time_between_counts']['number'];
|
|
|
|
|
567 |
|
568 |
+
if ( $input['time_between_counts']['number'] < $field['min'] || $input['time_between_counts']['number'] > $field['max'] )
|
569 |
+
$input['time_between_counts']['number'] = $pvc->defaults['general']['time_between_counts']['number'];
|
|
|
570 |
|
571 |
+
// type
|
572 |
+
$input['time_between_counts']['type'] = isset( $input['time_between_counts']['type'], $this->time_types[$input['time_between_counts']['type']] ) ? $input['time_between_counts']['type'] : $pvc->defaults['general']['time_between_counts']['type'];
|
|
|
|
|
573 |
|
574 |
+
return $input;
|
|
|
|
|
|
|
|
|
575 |
}
|
576 |
|
577 |
/**
|
578 |
+
* Setting: reset data interval.
|
579 |
+
*
|
580 |
+
* @param array $field Field options
|
581 |
+
* @return string
|
582 |
*/
|
583 |
+
public function setting_reset_counts( $field ) {
|
584 |
+
// get main instance
|
585 |
+
$pvc = Post_Views_Counter();
|
586 |
|
587 |
+
$html = '
|
588 |
+
<input size="6" type="number" min="' . ( (int) $field['min'] ) . '" max="' . ( (int) $field['max'] ) . '" name="post_views_counter_settings_general[reset_counts][number]" value="' . esc_attr( $pvc->options['general']['reset_counts']['number'] ) . '" />
|
589 |
+
<select class="pvc-chosen-short" name="post_views_counter_settings_general[reset_counts][type]">';
|
590 |
|
591 |
+
foreach ( array_slice( $this->time_types, 2, null, true ) as $type => $type_name ) {
|
592 |
+
$html .= '
|
593 |
+
<option value="' . esc_attr( $type ) . '" ' . selected( $type, $pvc->options['general']['reset_counts']['type'], false ) . '>' . esc_html( $type_name ) . '</option>';
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
594 |
}
|
595 |
|
596 |
+
$html .= '
|
597 |
+
</select>
|
598 |
+
<p class="description">' . __( 'Delete single day post views data older than specified above. Enter 0 (number zero) if you want to preserve your data regardless of its age.', 'post-views-counter' ) . '</p>';
|
|
|
|
|
599 |
|
600 |
+
return $html;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
601 |
}
|
602 |
|
603 |
/**
|
604 |
+
* Validate reset data interval.
|
605 |
+
*
|
606 |
+
* @param array $input Input POST data
|
607 |
+
* @param array $field Field options
|
608 |
+
* @return array
|
609 |
*/
|
610 |
+
public function validate_reset_counts( $input, $field ) {
|
611 |
+
// get main instance
|
612 |
+
$pvc = Post_Views_Counter();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
613 |
|
614 |
+
// number
|
615 |
+
$input['reset_counts']['number'] = isset( $input['reset_counts']['number'] ) ? (int) $input['reset_counts']['number'] : $pvc->defaults['general']['reset_counts']['number'];
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
616 |
|
617 |
+
if ( $input['reset_counts']['number'] < $field['min'] || $input['reset_counts']['number'] > $field['max'] )
|
618 |
+
$input['reset_counts']['number'] = $pvc->defaults['general']['reset_counts']['number'];
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
619 |
|
620 |
+
// type
|
621 |
+
$input['reset_counts']['type'] = isset( $input['reset_counts']['type'], $this->time_types[$input['reset_counts']['type']] ) ? $input['reset_counts']['type'] : $pvc->defaults['general']['reset_counts']['type'];
|
|
|
|
|
|
|
|
|
622 |
|
623 |
+
// run cron on next visit?
|
624 |
+
$input['cron_run'] = ( $input['reset_counts']['number'] > 0 );
|
625 |
+
|
626 |
+
// cron update?
|
627 |
+
$input['cron_update'] = ( $input['cron_run'] && ( $pvc->options['general']['reset_counts']['number'] !== $input['reset_counts']['number'] || $pvc->options['general']['reset_counts']['type'] !== $input['reset_counts']['type'] ) );
|
628 |
|
629 |
+
return $input;
|
|
|
|
|
630 |
}
|
631 |
|
632 |
/**
|
633 |
+
* Setting: flush object cache interval.
|
634 |
+
*
|
635 |
+
* @param array $field Field options
|
636 |
+
* @return string
|
637 |
*/
|
638 |
+
public function setting_flush_interval( $field ) {
|
639 |
+
// get main instance
|
640 |
+
$pvc = Post_Views_Counter();
|
641 |
+
|
642 |
+
$html = '
|
643 |
+
<input size="6" type="number" min="' . ( (int) $field['min'] ) . '" max="' . ( (int) $field['max'] ) . '" name="post_views_counter_settings_general[flush_interval][number]" value="' . esc_attr( $pvc->options['general']['flush_interval']['number'] ) . '" />
|
644 |
+
<select class="pvc-chosen-short" name="post_views_counter_settings_general[flush_interval][type]">';
|
645 |
+
|
646 |
+
foreach ( $this->time_types as $type => $type_name ) {
|
647 |
+
$html .= '
|
648 |
+
<option value="' . esc_attr( $type ) . '" ' . selected( $type, $pvc->options['general']['flush_interval']['type'], false ) . '>' . esc_html( $type_name ) . '</option>';
|
649 |
}
|
650 |
|
651 |
+
$html .= '
|
652 |
+
</select>
|
653 |
+
<p class="description">' . __( 'How often to flush cached view counts from the object cache into the database. This feature is used only if a persistent object cache is detected and the interval is greater than 0 (number zero). When used, view counts will be collected and stored in the object cache instead of the database and will then be asynchronously flushed to the database according to the specified interval.<br /><strong>Notice:</strong> Potential data loss may occur if the object cache is cleared/unavailable for the duration of the interval.', 'post-views-counter' ) . '</p>';
|
654 |
+
|
655 |
+
return $html;
|
656 |
}
|
657 |
|
658 |
/**
|
659 |
+
* Validate flush object cache interval.
|
660 |
+
*
|
661 |
+
* @param array $input Input POST data
|
662 |
+
* @param array $field Field options
|
663 |
+
* @return array
|
664 |
*/
|
665 |
+
public function validate_flush_interval( $input, $field ) {
|
666 |
+
// get main instance
|
667 |
+
$pvc = Post_Views_Counter();
|
668 |
|
669 |
+
// number
|
670 |
+
$input['flush_interval']['number'] = isset( $input['flush_interval']['number'] ) ? (int) $input['flush_interval']['number'] : $pvc->defaults['general']['flush_interval']['number'];
|
671 |
|
672 |
+
if ( $input['flush_interval']['number'] < $field['min'] || $input['flush_interval']['number'] > $field['max'] )
|
673 |
+
$input['flush_interval']['number'] = $pvc->defaults['general']['flush_interval']['number'];
|
|
|
674 |
|
675 |
+
// type
|
676 |
+
$input['flush_interval']['type'] = isset( $input['flush_interval']['type'], $this->time_types[$input['flush_interval']['type']] ) ? $input['flush_interval']['type'] : $pvc->defaults['general']['flush_interval']['type'];
|
|
|
|
|
677 |
|
678 |
+
// Since the settings are about to be saved and cache flush interval could've changed,
|
679 |
+
// we want to make sure that any changes done on the settings page are in effect immediately
|
680 |
+
// (instead of having to wait for the previous schedule to occur).
|
681 |
+
// We achieve that by making sure to clear any previous cache flush schedules and
|
682 |
+
// schedule the new one if the specified interval is > 0
|
683 |
+
$pvc->remove_cache_flush();
|
|
|
|
|
|
|
|
|
684 |
|
685 |
+
if ( $input['flush_interval']['number'] > 0 )
|
686 |
+
$pvc->schedule_cache_flush();
|
687 |
+
|
688 |
+
return $input;
|
|
|
|
|
|
|
|
|
|
|
689 |
}
|
690 |
|
691 |
/**
|
692 |
+
* Setting: exclude visitors.
|
693 |
+
*
|
694 |
+
* @return string
|
695 |
*/
|
696 |
+
public function setting_exclude() {
|
697 |
+
// get main instance
|
698 |
+
$pvc = Post_Views_Counter();
|
|
|
|
|
|
|
699 |
|
700 |
+
$html = '';
|
|
|
701 |
|
702 |
+
foreach ( $this->groups as $type => $type_name ) {
|
703 |
+
$html .= '
|
704 |
+
<label><input id="' . esc_attr( 'pvc_exclude-' . $type ) . '" type="checkbox" name="post_views_counter_settings_general[exclude][groups][' . esc_attr( $type ) . ']" value="1" ' . checked( in_array( $type, $pvc->options['general']['exclude']['groups'], true ), true, false ) . ' />' . esc_html( $type_name ) . '</label>';
|
705 |
}
|
706 |
|
707 |
+
$html .= '
|
708 |
+
<p class="description">' . __( 'Use it exclude specific user groups from post views count.', 'post-views-counter' ) . '</p>
|
709 |
+
<div class="pvc_user_roles"' . ( in_array( 'roles', $pvc->options['general']['exclude']['groups'], true ) ? '' : ' style="display: none;"' ) . '>';
|
710 |
|
711 |
foreach ( $this->user_roles as $role => $role_name ) {
|
712 |
+
$html .= '
|
713 |
+
<label><input type="checkbox" name="post_views_counter_settings_general[exclude][roles][' . $role . ']" value="1" ' . checked( in_array( $role, $pvc->options['general']['exclude']['roles'], true ), true, false ) . '>' . esc_html( $role_name ) . '</label>';
|
714 |
}
|
715 |
|
716 |
+
$html .= '
|
717 |
+
<p class="description">' . __( 'Use it exclude specific user roles from post views count.', 'post-views-counter' ) . '</p>
|
718 |
+
</div>';
|
719 |
+
|
720 |
+
return $html;
|
721 |
}
|
722 |
|
723 |
/**
|
724 |
+
* Validate exclude visitors.
|
725 |
+
*
|
726 |
+
* @param array $input Input POST data
|
727 |
+
* @param array $field Field options
|
728 |
+
* @return array
|
729 |
*/
|
730 |
+
public function validate_exclude( $input, $field ) {
|
731 |
// get main instance
|
732 |
$pvc = Post_Views_Counter();
|
733 |
|
734 |
+
// any groups?
|
735 |
+
if ( isset( $input['exclude']['groups'] ) ) {
|
736 |
+
$groups = [];
|
|
|
|
|
|
|
|
|
|
|
737 |
|
738 |
+
foreach ( $input['exclude']['groups'] as $group => $set ) {
|
739 |
+
if ( isset( $this->groups[$group] ) )
|
740 |
+
$groups[] = $group;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
741 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
742 |
|
743 |
+
$input['exclude']['groups'] = array_unique( $groups );
|
744 |
+
} else
|
745 |
+
$input['exclude']['groups'] = [];
|
746 |
|
747 |
+
// any roles?
|
748 |
+
if ( in_array( 'roles', $input['exclude']['groups'], true ) && isset( $input['exclude']['roles'] ) ) {
|
749 |
+
$roles = [];
|
750 |
|
751 |
+
foreach ( $input['exclude']['roles'] as $role => $set ) {
|
752 |
+
if ( isset( $this->user_roles[$role] ) )
|
753 |
+
$roles[] = $role;
|
754 |
+
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
755 |
|
756 |
+
$input['exclude']['roles'] = array_unique( $roles );
|
757 |
+
} else
|
758 |
+
$input['exclude']['roles'] = [];
|
759 |
|
760 |
+
return $input;
|
761 |
+
}
|
|
|
762 |
|
763 |
+
/**
|
764 |
+
* Setting: exclude IP addresses.
|
765 |
+
*
|
766 |
+
* @return string
|
767 |
+
*/
|
768 |
+
public function setting_exclude_ips() {
|
769 |
+
$ips = Post_Views_Counter()->options['general']['exclude_ips'];
|
770 |
|
771 |
+
$html = '';
|
|
|
|
|
|
|
772 |
|
773 |
+
if ( ! empty( $ips ) ) {
|
774 |
+
foreach ( $ips as $key => $ip ) {
|
775 |
+
$html .= '
|
776 |
+
<div class="ip-box">
|
777 |
+
<input type="text" name="post_views_counter_settings_general[exclude_ips][]" value="' . esc_attr( $ip ) . '" /> <a href="#" class="remove-exclude-ip" title="' . esc_attr__( 'Remove', 'post-views-counter' ) . '">' . esc_html__( 'Remove', 'post-views-counter' ) . '</a>
|
778 |
+
</div>';
|
779 |
}
|
780 |
+
} else {
|
781 |
+
$html .= '
|
782 |
+
<div class="ip-box">
|
783 |
+
<input type="text" name="post_views_counter_settings_general[exclude_ips][]" value="" /> <a href="#" class="remove-exclude-ip" title="' . esc_attr__( 'Remove', 'post-views-counter' ) . '">' . esc_html__( 'Remove', 'post-views-counter' ) . '</a>
|
784 |
+
</div>';
|
785 |
+
}
|
786 |
|
787 |
+
$html .= '
|
788 |
+
<p><input type="button" class="button button-secondary add-exclude-ip" value="' . esc_attr__( 'Add new', 'post-views-counter' ) . '" /> <input type="button" class="button button-secondary add-current-ip" value="' . esc_attr__( 'Add my current IP', 'post-views-counter' ) . '" data-rel="' . esc_attr( $_SERVER['REMOTE_ADDR'] ) . '" /></p>
|
789 |
+
<p class="description">' . esc_html__( 'Enter the IP addresses to be excluded from post views count.', 'post-views-counter' ) . '</p>';
|
790 |
|
791 |
+
return $html;
|
792 |
+
}
|
|
|
|
|
793 |
|
794 |
+
/**
|
795 |
+
* Validate exclude IP addresses.
|
796 |
+
*
|
797 |
+
* @param array $input Input POST data
|
798 |
+
* @param array $field Field options
|
799 |
+
* @return array
|
800 |
+
*/
|
801 |
+
public function validate_exclude_ips( $input, $field ) {
|
802 |
+
// get main instance
|
803 |
+
$pvc = Post_Views_Counter();
|
804 |
|
805 |
+
// any ip addresses?
|
806 |
+
if ( isset( $input['exclude_ips'] ) ) {
|
807 |
+
$ips = [];
|
808 |
|
809 |
+
foreach ( $input['exclude_ips'] as $ip ) {
|
810 |
+
if ( strpos( $ip, '*' ) !== false ) {
|
811 |
+
$new_ip = str_replace( '*', '0', $ip );
|
812 |
|
813 |
+
if ( filter_var( $new_ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4 ) )
|
|
|
|
|
814 |
$ips[] = $ip;
|
815 |
+
} elseif ( filter_var( $ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4 ) )
|
816 |
+
$ips[] = $ip;
|
|
|
817 |
}
|
818 |
|
819 |
+
$input['exclude_ips'] = array_unique( $ips );
|
820 |
+
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
821 |
|
822 |
+
return $input;
|
823 |
+
}
|
824 |
|
825 |
+
/**
|
826 |
+
* Setting: tools.
|
827 |
+
*
|
828 |
+
* @return string
|
829 |
+
*/
|
830 |
+
public function setting_wp_postviews() {
|
831 |
+
$html = '
|
832 |
+
<input type="submit" class="button button-secondary" name="post_views_counter_import_wp_postviews" value="' . __( 'Import views', 'post-views-counter' ) . '"/> <label><input id="pvc-wp-postviews" type="checkbox" name="post_views_counter_import_wp_postviews_override" value="1" />' . __( 'Override existing views data.', 'post-views-counter' ) . '</label>
|
833 |
+
<p class="description">' . __( 'Import post views data from WP-PostViews plugin.', 'post-views-counter' ) . '</p>
|
834 |
+
<br /><input type="submit" class="button button-secondary" name="post_views_counter_reset_views" value="' . __( 'Delete views', 'post-views-counter' ) . '"/>
|
835 |
+
<p class="description">' . __( 'Delete all the existing post views data.', 'post-views-counter' ) . '</p>';
|
836 |
+
|
837 |
+
return $html;
|
838 |
+
}
|
839 |
|
840 |
+
/**
|
841 |
+
* Setting: user type.
|
842 |
+
*
|
843 |
+
* @return string
|
844 |
+
*/
|
845 |
+
public function setting_restrict_display() {
|
846 |
+
// get main instance
|
847 |
+
$pvc = Post_Views_Counter();
|
848 |
|
849 |
+
$html = '';
|
|
|
|
|
850 |
|
851 |
+
foreach ( $this->groups as $type => $type_name ) {
|
852 |
+
if ( $type === 'robots' )
|
853 |
+
continue;
|
|
|
854 |
|
855 |
+
$html .= '
|
856 |
+
<label><input id="pvc_restrict_display-' . esc_attr( $type ) . '" type="checkbox" name="post_views_counter_settings_display[restrict_display][groups][' . esc_html( $type ) . ']" value="1" ' . checked( in_array( $type, $pvc->options['display']['restrict_display']['groups'], true ), true, false ) . ' />' . esc_html( $type_name ) . '</label>';
|
857 |
+
}
|
858 |
|
859 |
+
$html .= '
|
860 |
+
<p class="description">' . __( 'Use it to hide the post views counter from selected type of visitors.', 'post-views-counter' ) . '</p>
|
861 |
+
<div class="pvc_user_roles"' . ( in_array( 'roles', $pvc->options['display']['restrict_display']['groups'], true ) ? '' : ' style="display: none;"' ) . '>';
|
862 |
|
863 |
+
foreach ( $this->user_roles as $role => $role_name ) {
|
864 |
+
$html .= '
|
865 |
+
<label><input type="checkbox" name="post_views_counter_settings_display[restrict_display][roles][' . esc_attr( $role ) . ']" value="1" ' . checked( in_array( $role, $pvc->options['display']['restrict_display']['roles'], true ), true, false ) . ' />' . esc_html( $role_name ) . '</label>';
|
866 |
+
}
|
867 |
|
868 |
+
$html .= '
|
869 |
+
<p class="description">' . __( 'Use it to hide the post views counter from selected user roles.', 'post-views-counter' ) . '</p>
|
870 |
+
</div>';
|
871 |
|
872 |
+
return $html;
|
873 |
+
}
|
|
|
874 |
|
875 |
+
/**
|
876 |
+
* Validate user type.
|
877 |
+
*
|
878 |
+
* @param array $input Input POST data
|
879 |
+
* @param array $field Field options
|
880 |
+
* @return array
|
881 |
+
*/
|
882 |
+
public function validate_restrict_display( $input, $field ) {
|
883 |
+
// get main instance
|
884 |
+
$pvc = Post_Views_Counter();
|
885 |
|
886 |
+
// any groups?
|
887 |
+
if ( isset( $input['restrict_display']['groups'] ) ) {
|
888 |
+
$groups = [];
|
889 |
|
890 |
+
foreach ( $input['restrict_display']['groups'] as $group => $set ) {
|
891 |
+
if ( $group === 'robots' )
|
892 |
+
continue;
|
893 |
|
894 |
+
if ( isset( $this->groups[$group] ) )
|
895 |
+
$groups[] = $group;
|
896 |
+
}
|
897 |
|
898 |
+
$input['restrict_display']['groups'] = array_unique( $groups );
|
899 |
+
} else
|
900 |
+
$input['restrict_display']['groups'] = [];
|
|
|
901 |
|
902 |
+
// any roles?
|
903 |
+
if ( in_array( 'roles', $input['restrict_display']['groups'], true ) && isset( $input['restrict_display']['roles'] ) ) {
|
904 |
+
$roles = [];
|
|
|
|
|
|
|
905 |
|
906 |
+
foreach ( $input['restrict_display']['roles'] as $role => $set ) {
|
907 |
+
if ( isset( $this->user_roles[$role] ) )
|
908 |
+
$roles[] = $role;
|
909 |
+
}
|
910 |
|
911 |
+
$input['restrict_display']['roles'] = array_unique( $roles );
|
912 |
+
} else
|
913 |
+
$input['restrict_display']['roles'] = [];
|
914 |
|
915 |
return $input;
|
916 |
}
|
js/admin-dashboard.js
CHANGED
@@ -125,6 +125,11 @@
|
|
125 |
scaleLabel: {
|
126 |
display: false,
|
127 |
labelString: response.text.yAxes
|
|
|
|
|
|
|
|
|
|
|
128 |
}
|
129 |
} ]
|
130 |
},
|
125 |
scaleLabel: {
|
126 |
display: false,
|
127 |
labelString: response.text.yAxes
|
128 |
+
},
|
129 |
+
ticks: {
|
130 |
+
precision: 0,
|
131 |
+
beginAtZero: true,
|
132 |
+
maxTicksLimit: 12
|
133 |
}
|
134 |
} ]
|
135 |
},
|
js/admin-settings.js
CHANGED
@@ -1,66 +1,65 @@
|
|
1 |
-
( function( $ ) {
|
2 |
-
|
3 |
-
// ready event
|
4 |
-
$( function() {
|
5 |
-
var ip_boxes = $( '#
|
6 |
-
|
7 |
-
$( '#
|
8 |
-
|
9 |
-
// ask whether to reset options to defaults
|
10 |
-
$( document ).on( 'click', '.reset_pvc_settings', function() {
|
11 |
-
return confirm( pvcArgsSettings.resetToDefaults );
|
12 |
-
} );
|
13 |
-
|
14 |
-
// ask whether to reset views
|
15 |
-
$( document ).on( 'click', 'input[name="post_views_counter_reset_views"]', function() {
|
16 |
-
return confirm( pvcArgsSettings.resetViews );
|
17 |
-
} );
|
18 |
-
|
19 |
-
// remove ip box
|
20 |
-
$( document ).on( 'click', '.remove-exclude-ip', function( e ) {
|
21 |
-
e.preventDefault();
|
22 |
-
|
23 |
-
ip_boxes--;
|
24 |
-
|
25 |
-
var parent = $( this ).parent();
|
26 |
-
|
27 |
-
// remove ip box
|
28 |
-
parent.slideUp( 'fast', function() {
|
29 |
-
$( this ).remove();
|
30 |
-
} );
|
31 |
-
} );
|
32 |
-
|
33 |
-
// add ip box
|
34 |
-
$( document ).on( 'click', '.add-exclude-ip', function() {
|
35 |
-
ip_boxes++;
|
36 |
-
|
37 |
-
var parent = $( this ).parents( '#
|
38 |
-
new_ip_box = parent.find( '.ip-box:last' ).clone().hide();
|
39 |
-
|
40 |
-
// clear value
|
41 |
-
new_ip_box.find( 'input' ).val( '' );
|
42 |
-
|
43 |
-
if ( ip_boxes > 1 )
|
44 |
-
new_ip_box.find( '.remove-exclude-ip' ).show();
|
45 |
-
|
46 |
-
|
47 |
-
|
48 |
-
|
49 |
-
|
50 |
-
|
51 |
-
|
52 |
-
|
53 |
-
|
54 |
-
|
55 |
-
|
56 |
-
|
57 |
-
|
58 |
-
|
59 |
-
|
60 |
-
|
61 |
-
|
62 |
-
|
63 |
-
|
64 |
-
|
65 |
-
|
66 |
} )( jQuery );
|
1 |
+
( function( $ ) {
|
2 |
+
|
3 |
+
// ready event
|
4 |
+
$( function() {
|
5 |
+
var ip_boxes = $( '#post_views_counter_general_exclude_ips_setting' ).find( '.ip-box' ).length;
|
6 |
+
|
7 |
+
$( '#post_views_counter_general_exclude_ips_setting .ip-box:first' ).find( '.remove-exclude-ip' ).hide();
|
8 |
+
|
9 |
+
// ask whether to reset options to defaults
|
10 |
+
$( document ).on( 'click', '.reset_pvc_settings', function() {
|
11 |
+
return confirm( pvcArgsSettings.resetToDefaults );
|
12 |
+
} );
|
13 |
+
|
14 |
+
// ask whether to reset views
|
15 |
+
$( document ).on( 'click', 'input[name="post_views_counter_reset_views"]', function() {
|
16 |
+
return confirm( pvcArgsSettings.resetViews );
|
17 |
+
} );
|
18 |
+
|
19 |
+
// remove ip box
|
20 |
+
$( document ).on( 'click', '.remove-exclude-ip', function( e ) {
|
21 |
+
e.preventDefault();
|
22 |
+
|
23 |
+
ip_boxes--;
|
24 |
+
|
25 |
+
var parent = $( this ).parent();
|
26 |
+
|
27 |
+
// remove ip box
|
28 |
+
parent.slideUp( 'fast', function() {
|
29 |
+
$( this ).remove();
|
30 |
+
} );
|
31 |
+
} );
|
32 |
+
|
33 |
+
// add ip box
|
34 |
+
$( document ).on( 'click', '.add-exclude-ip', function() {
|
35 |
+
ip_boxes++;
|
36 |
+
|
37 |
+
var parent = $( this ).parents( '#post_views_counter_general_exclude_ips_setting' ),
|
38 |
+
new_ip_box = parent.find( '.ip-box:last' ).clone().hide();
|
39 |
+
|
40 |
+
// clear value
|
41 |
+
new_ip_box.find( 'input' ).val( '' );
|
42 |
+
|
43 |
+
if ( ip_boxes > 1 )
|
44 |
+
new_ip_box.find( '.remove-exclude-ip' ).show();
|
45 |
+
|
46 |
+
// add and display new ip box
|
47 |
+
parent.find( '.ip-box:last' ).after( new_ip_box ).next().slideDown( 'fast' );
|
48 |
+
} );
|
49 |
+
|
50 |
+
// add current ip
|
51 |
+
$( document ).on( 'click', '.add-current-ip', function() {
|
52 |
+
// fill input with user's current ip
|
53 |
+
$( this ).parents( '#post_views_counter_general_exclude_ips_setting' ).find( '.ip-box' ).last().find( 'input' ).val( $( this ).attr( 'data-rel' ) );
|
54 |
+
} );
|
55 |
+
|
56 |
+
// toggle user roles
|
57 |
+
$( '#pvc_exclude-roles, #pvc_restrict_display-roles' ).on( 'change', function() {
|
58 |
+
if ( $( this ).is( ':checked' ) )
|
59 |
+
$( '.pvc_user_roles' ).slideDown( 'fast' );
|
60 |
+
else
|
61 |
+
$( '.pvc_user_roles' ).slideUp( 'fast' );
|
62 |
+
} );
|
63 |
+
} );
|
64 |
+
|
|
|
65 |
} )( jQuery );
|
post-views-counter.php
CHANGED
@@ -2,7 +2,7 @@
|
|
2 |
/*
|
3 |
Plugin Name: Post Views Counter
|
4 |
Description: Post Views Counter allows you to display how many times a post, page or custom post type had been viewed in a simple, fast and reliable way.
|
5 |
-
Version: 1.3.
|
6 |
Author: Digital Factory
|
7 |
Author URI: http://www.dfactory.eu/
|
8 |
Plugin URI: http://www.dfactory.eu/plugins/post-views-counter/
|
@@ -31,77 +31,80 @@ if ( ! class_exists( 'Post_Views_Counter' ) ) :
|
|
31 |
* Post Views Counter final class.
|
32 |
*
|
33 |
* @class Post_Views_Counter
|
34 |
-
* @version 1.3.
|
35 |
*/
|
36 |
final class Post_Views_Counter {
|
37 |
|
38 |
private static $instance;
|
39 |
public $options;
|
40 |
-
public $defaults =
|
41 |
-
'general' =>
|
42 |
-
'post_types_count' =>
|
43 |
'counter_mode' => 'php',
|
44 |
'post_views_column' => true,
|
45 |
-
'time_between_counts' => array(
|
46 |
-
'number' => 24,
|
47 |
-
'type' => 'hours'
|
48 |
-
),
|
49 |
-
'reset_counts' => array(
|
50 |
-
'number' => 30,
|
51 |
-
'type' => 'days'
|
52 |
-
),
|
53 |
-
'flush_interval' => array(
|
54 |
-
'number' => 0,
|
55 |
-
'type' => 'minutes'
|
56 |
-
),
|
57 |
-
'exclude' => array(
|
58 |
-
'groups' => array(),
|
59 |
-
'roles' => array()
|
60 |
-
),
|
61 |
-
'exclude_ips' => array(),
|
62 |
-
'strict_counts' => false,
|
63 |
'restrict_edit_views' => false,
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
64 |
'deactivation_delete' => false,
|
65 |
'cron_run' => true,
|
66 |
'cron_update' => true,
|
67 |
'update_version' => 1,
|
68 |
'update_notice' => true,
|
69 |
'update_delay_date' => 0
|
70 |
-
|
71 |
-
'display' =>
|
72 |
'label' => 'Post Views:',
|
73 |
-
'post_types_display' =>
|
74 |
-
'page_types_display' =>
|
75 |
-
'restrict_display' =>
|
76 |
-
'groups' =>
|
77 |
-
'roles' =>
|
78 |
-
|
79 |
'position' => 'after',
|
80 |
-
'display_style' =>
|
81 |
'icon' => true,
|
82 |
'text' => true
|
83 |
-
|
84 |
-
'link_to_post' => true,
|
85 |
'icon_class' => 'dashicons-chart-bar',
|
86 |
'toolbar_statistics' => true
|
87 |
-
|
88 |
-
'version' => '1.3.
|
89 |
-
|
90 |
|
91 |
/**
|
92 |
* Disable object cloning.
|
|
|
|
|
93 |
*/
|
94 |
public function __clone() {}
|
95 |
|
96 |
/**
|
97 |
* Disable unserializing of the class.
|
|
|
|
|
98 |
*/
|
99 |
public function __wakeup() {}
|
100 |
|
101 |
/**
|
102 |
* Main plugin instance,
|
103 |
* Insures that only one instance of the plugin exists in memory at one time.
|
104 |
-
*
|
105 |
* @return object
|
106 |
*/
|
107 |
public static function instance() {
|
@@ -119,9 +122,22 @@ if ( ! class_exists( 'Post_Views_Counter' ) ) :
|
|
119 |
self::$instance->crawler_detect = new Post_Views_Counter_Crawler_Detect();
|
120 |
// regular setup
|
121 |
} else {
|
122 |
-
add_action( 'plugins_loaded',
|
123 |
|
124 |
self::$instance->includes();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
125 |
self::$instance->update = new Post_Views_Counter_Update();
|
126 |
self::$instance->settings = new Post_Views_Counter_Settings();
|
127 |
self::$instance->query = new Post_Views_Counter_Query();
|
@@ -160,6 +176,7 @@ if ( ! class_exists( 'Post_Views_Counter' ) ) :
|
|
160 |
*/
|
161 |
private function includes() {
|
162 |
include_once( POST_VIEWS_COUNTER_PATH . 'includes/update.php' );
|
|
|
163 |
include_once( POST_VIEWS_COUNTER_PATH . 'includes/settings.php' );
|
164 |
include_once( POST_VIEWS_COUNTER_PATH . 'includes/columns.php' );
|
165 |
include_once( POST_VIEWS_COUNTER_PATH . 'includes/query.php' );
|
@@ -178,30 +195,30 @@ if ( ! class_exists( 'Post_Views_Counter' ) ) :
|
|
178 |
*/
|
179 |
public function __construct() {
|
180 |
if ( defined( 'SHORTINIT' ) && SHORTINIT ) {
|
181 |
-
$this->options =
|
182 |
'general' => array_merge( $this->defaults['general'], get_option( 'post_views_counter_settings_general', $this->defaults['general'] ) ),
|
183 |
'display' => array_merge( $this->defaults['display'], get_option( 'post_views_counter_settings_display', $this->defaults['display'] ) )
|
184 |
-
|
185 |
} else {
|
186 |
-
register_activation_hook( __FILE__,
|
187 |
-
register_deactivation_hook( __FILE__,
|
188 |
|
189 |
// settings
|
190 |
-
$this->options =
|
191 |
'general' => array_merge( $this->defaults['general'], get_option( 'post_views_counter_settings_general', $this->defaults['general'] ) ),
|
192 |
'display' => array_merge( $this->defaults['display'], get_option( 'post_views_counter_settings_display', $this->defaults['display'] ) )
|
193 |
-
|
194 |
|
195 |
// actions
|
196 |
-
add_action( 'admin_enqueue_scripts',
|
197 |
-
add_action( 'wp_loaded',
|
198 |
-
// add_action( 'init',
|
199 |
-
add_action( 'admin_init',
|
200 |
-
add_action( 'wp_ajax_pvc_dismiss_notice',
|
201 |
|
202 |
// filters
|
203 |
-
add_filter( 'plugin_row_meta',
|
204 |
-
add_filter( 'plugin_action_links',
|
205 |
}
|
206 |
}
|
207 |
|
@@ -221,7 +238,13 @@ if ( ! class_exists( 'Post_Views_Counter' ) ) :
|
|
221 |
|
222 |
if ( $this->options['general']['update_version'] < $current_update ) {
|
223 |
// check version, if update version is lower than plugin version, set update notice to true
|
224 |
-
$this->options['general'] = array_merge(
|
|
|
|
|
|
|
|
|
|
|
|
|
225 |
|
226 |
update_option( 'post_views_counter_settings_general', $this->options['general'] );
|
227 |
|
@@ -235,7 +258,7 @@ if ( ! class_exists( 'Post_Views_Counter' ) ) :
|
|
235 |
// display current version notice
|
236 |
if ( $this->options['general']['update_notice'] === true ) {
|
237 |
// include notice js, only if needed
|
238 |
-
add_action( 'admin_print_scripts',
|
239 |
|
240 |
// get activation date
|
241 |
$activation_date = get_option( 'post_views_counter_activation_date' );
|
@@ -260,21 +283,22 @@ if ( ! class_exists( 'Post_Views_Counter' ) ) :
|
|
260 |
* @param string $html
|
261 |
* @param string $status
|
262 |
* @param bool $paragraph
|
|
|
263 |
*/
|
264 |
public function add_notice( $html = '', $status = 'error', $paragraph = true ) {
|
265 |
-
$this->notices[] =
|
266 |
'html' => $html,
|
267 |
'status' => $status,
|
268 |
'paragraph' => $paragraph
|
269 |
-
|
270 |
|
271 |
-
add_action( 'admin_notices',
|
272 |
}
|
273 |
|
274 |
/**
|
275 |
* Print admin notices.
|
276 |
-
*
|
277 |
-
* @return
|
278 |
*/
|
279 |
public function display_notice() {
|
280 |
foreach( $this->notices as $notice ) {
|
@@ -289,8 +313,8 @@ if ( ! class_exists( 'Post_Views_Counter' ) ) :
|
|
289 |
|
290 |
/**
|
291 |
* Print admin scripts.
|
292 |
-
*
|
293 |
-
* @return
|
294 |
*/
|
295 |
public function admin_inline_js() {
|
296 |
if ( ! current_user_can( 'install_plugins' ) )
|
@@ -324,6 +348,8 @@ if ( ! class_exists( 'Post_Views_Counter' ) ) :
|
|
324 |
|
325 |
/**
|
326 |
* Dismiss notice.
|
|
|
|
|
327 |
*/
|
328 |
public function dismiss_notice() {
|
329 |
if ( ! current_user_can( 'install_plugins' ) )
|
@@ -336,14 +362,29 @@ if ( ! class_exists( 'Post_Views_Counter' ) ) :
|
|
336 |
// delay notice
|
337 |
case 'delay':
|
338 |
// set delay period to 1 week from now
|
339 |
-
$this->options['general'] = array_merge(
|
|
|
|
|
|
|
|
|
|
|
340 |
update_option( 'post_views_counter_settings_general', $this->options['general'] );
|
341 |
break;
|
342 |
|
343 |
// hide notice
|
344 |
default:
|
345 |
-
$this->options['general'] = array_merge(
|
346 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
347 |
|
348 |
update_option( 'post_views_counter_settings_general', $this->options['general'] );
|
349 |
}
|
@@ -357,12 +398,13 @@ if ( ! class_exists( 'Post_Views_Counter' ) ) :
|
|
357 |
*
|
358 |
* @global object $wpdb
|
359 |
* @param bool $networkwide
|
|
|
360 |
*/
|
361 |
public function multisite_activation( $networkwide ) {
|
362 |
if ( is_multisite() && $networkwide ) {
|
363 |
global $wpdb;
|
364 |
|
365 |
-
$activated_blogs =
|
366 |
$current_blog_id = $wpdb->blogid;
|
367 |
$blogs_ids = $wpdb->get_col( $wpdb->prepare( 'SELECT blog_id FROM ' . $wpdb->blogs, '' ) );
|
368 |
|
@@ -373,7 +415,7 @@ if ( ! class_exists( 'Post_Views_Counter' ) ) :
|
|
373 |
}
|
374 |
|
375 |
switch_to_blog( $current_blog_id );
|
376 |
-
update_site_option( 'post_views_counter_activated_blogs', $activated_blogs,
|
377 |
} else
|
378 |
$this->activate_single();
|
379 |
}
|
@@ -382,6 +424,7 @@ if ( ! class_exists( 'Post_Views_Counter' ) ) :
|
|
382 |
* Single site activation.
|
383 |
*
|
384 |
* @global array $wp_roles
|
|
|
385 |
*/
|
386 |
public function activate_single() {
|
387 |
global $wpdb, $charset_collate;
|
@@ -416,6 +459,7 @@ if ( ! class_exists( 'Post_Views_Counter' ) ) :
|
|
416 |
*
|
417 |
* @global array $wpdb
|
418 |
* @param bool $networkwide
|
|
|
419 |
*/
|
420 |
public function multisite_deactivation( $networkwide ) {
|
421 |
if ( is_multisite() && $networkwide ) {
|
@@ -425,7 +469,7 @@ if ( ! class_exists( 'Post_Views_Counter' ) ) :
|
|
425 |
$blogs_ids = $wpdb->get_col( $wpdb->prepare( 'SELECT blog_id FROM ' . $wpdb->blogs, '' ) );
|
426 |
|
427 |
if ( ! ( $activated_blogs = get_site_option( 'post_views_counter_activated_blogs', false, false ) ) )
|
428 |
-
$activated_blogs =
|
429 |
|
430 |
foreach ( $blogs_ids as $blog_id ) {
|
431 |
switch_to_blog( $blog_id );
|
@@ -446,6 +490,7 @@ if ( ! class_exists( 'Post_Views_Counter' ) ) :
|
|
446 |
*
|
447 |
* @global array $wp_roles
|
448 |
* @param bool $multi
|
|
|
449 |
*/
|
450 |
public function deactivate_single( $multi = false ) {
|
451 |
if ( $multi ) {
|
@@ -467,7 +512,7 @@ if ( ! class_exists( 'Post_Views_Counter' ) ) :
|
|
467 |
|
468 |
// remove schedule
|
469 |
wp_clear_scheduled_hook( 'pvc_reset_counts' );
|
470 |
-
remove_action( 'pvc_reset_counts',
|
471 |
|
472 |
$this->remove_cache_flush();
|
473 |
}
|
@@ -476,6 +521,7 @@ if ( ! class_exists( 'Post_Views_Counter' ) ) :
|
|
476 |
* Schedule cache flushing if it's not already scheduled.
|
477 |
*
|
478 |
* @param bool $forced
|
|
|
479 |
*/
|
480 |
public function schedule_cache_flush( $forced = true ) {
|
481 |
if ( $forced || ! wp_next_scheduled( 'pvc_flush_cached_counts' ) )
|
@@ -484,57 +530,66 @@ if ( ! class_exists( 'Post_Views_Counter' ) ) :
|
|
484 |
|
485 |
/**
|
486 |
* Remove scheduled cache flush and the corresponding action.
|
|
|
|
|
487 |
*/
|
488 |
public function remove_cache_flush() {
|
489 |
wp_clear_scheduled_hook( 'pvc_flush_cached_counts' );
|
490 |
-
remove_action( 'pvc_flush_cached_counts',
|
491 |
}
|
492 |
|
493 |
/**
|
494 |
-
* Load text domain
|
|
|
|
|
495 |
*/
|
496 |
public function load_textdomain() {
|
497 |
load_plugin_textdomain( 'post-views-counter', false, POST_VIEWS_COUNTER_REL_PATH . 'languages/' );
|
498 |
}
|
499 |
|
500 |
/**
|
501 |
-
* Load pluggable template functions
|
|
|
|
|
502 |
*/
|
503 |
public function load_pluggable_functions() {
|
504 |
include_once( POST_VIEWS_COUNTER_PATH . 'includes/functions.php' );
|
505 |
}
|
506 |
|
507 |
/**
|
508 |
-
* Add Gutenberg blocks
|
|
|
|
|
509 |
*/
|
510 |
public function gutenberg_blocks() {
|
511 |
-
wp_register_script( 'pvc-admin-block-views', POST_VIEWS_COUNTER_URL . '/js/admin-block.js',
|
512 |
|
513 |
-
register_block_type( 'post-views-counter/views',
|
514 |
}
|
515 |
|
516 |
/**
|
517 |
* Enqueue admin scripts and styles.
|
518 |
*
|
519 |
* @global string $post_type
|
520 |
-
* @param string $page
|
|
|
521 |
*/
|
522 |
public function admin_enqueue_scripts( $page ) {
|
523 |
wp_register_style( 'pvc-admin', POST_VIEWS_COUNTER_URL . '/css/admin.css' );
|
524 |
|
525 |
-
wp_register_script( 'pvc-admin-settings', POST_VIEWS_COUNTER_URL . '/js/admin-settings.js',
|
526 |
-
wp_register_script( 'pvc-admin-post', POST_VIEWS_COUNTER_URL . '/js/admin-post.js',
|
527 |
-
wp_register_script( 'pvc-admin-quick-edit', POST_VIEWS_COUNTER_URL . '/js/admin-quick-edit.js',
|
528 |
|
529 |
// load on PVC settings page
|
530 |
if ( $page === 'settings_page_post-views-counter' ) {
|
531 |
wp_enqueue_script( 'pvc-admin-settings' );
|
532 |
|
533 |
wp_localize_script(
|
534 |
-
'pvc-admin-settings', 'pvcArgsSettings',
|
535 |
'resetToDefaults' => __( 'Are you sure you want to reset these settings to defaults?', 'post-views-counter' ),
|
536 |
'resetViews' => __( 'Are you sure you want to delete all existing data?', 'post-views-counter' )
|
537 |
-
|
538 |
);
|
539 |
|
540 |
wp_enqueue_style( 'pvc-admin' );
|
@@ -566,7 +621,7 @@ if ( ! class_exists( 'Post_Views_Counter' ) ) :
|
|
566 |
wp_enqueue_script( 'pvc-admin-quick-edit' );
|
567 |
// widgets
|
568 |
} elseif ( $page === 'widgets.php' )
|
569 |
-
wp_enqueue_script( 'pvc-admin-widgets', POST_VIEWS_COUNTER_URL . '/js/admin-widgets.js',
|
570 |
// media
|
571 |
elseif ( $page === 'upload.php' )
|
572 |
wp_enqueue_style( 'pvc-admin' );
|
@@ -587,7 +642,10 @@ if ( ! class_exists( 'Post_Views_Counter' ) ) :
|
|
587 |
|
588 |
if ( $file == $plugin ) {
|
589 |
return array_merge(
|
590 |
-
$links,
|
|
|
|
|
|
|
591 |
);
|
592 |
}
|
593 |
|
2 |
/*
|
3 |
Plugin Name: Post Views Counter
|
4 |
Description: Post Views Counter allows you to display how many times a post, page or custom post type had been viewed in a simple, fast and reliable way.
|
5 |
+
Version: 1.3.7
|
6 |
Author: Digital Factory
|
7 |
Author URI: http://www.dfactory.eu/
|
8 |
Plugin URI: http://www.dfactory.eu/plugins/post-views-counter/
|
31 |
* Post Views Counter final class.
|
32 |
*
|
33 |
* @class Post_Views_Counter
|
34 |
+
* @version 1.3.7
|
35 |
*/
|
36 |
final class Post_Views_Counter {
|
37 |
|
38 |
private static $instance;
|
39 |
public $options;
|
40 |
+
public $defaults = [
|
41 |
+
'general' => [
|
42 |
+
'post_types_count' => [ 'post' ],
|
43 |
'counter_mode' => 'php',
|
44 |
'post_views_column' => true,
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
45 |
'restrict_edit_views' => false,
|
46 |
+
'time_between_counts' => [
|
47 |
+
'number' => 24,
|
48 |
+
'type' => 'hours'
|
49 |
+
],
|
50 |
+
'reset_counts' => [
|
51 |
+
'number' => 30,
|
52 |
+
'type' => 'days'
|
53 |
+
],
|
54 |
+
'flush_interval' => [
|
55 |
+
'number' => 0,
|
56 |
+
'type' => 'minutes'
|
57 |
+
],
|
58 |
+
'exclude' => [
|
59 |
+
'groups' => [],
|
60 |
+
'roles' => []
|
61 |
+
],
|
62 |
+
'exclude_ips' => [],
|
63 |
+
'strict_counts' => false,
|
64 |
'deactivation_delete' => false,
|
65 |
'cron_run' => true,
|
66 |
'cron_update' => true,
|
67 |
'update_version' => 1,
|
68 |
'update_notice' => true,
|
69 |
'update_delay_date' => 0
|
70 |
+
],
|
71 |
+
'display' => [
|
72 |
'label' => 'Post Views:',
|
73 |
+
'post_types_display' => [ 'post' ],
|
74 |
+
'page_types_display' => [ 'singular' ],
|
75 |
+
'restrict_display' => [
|
76 |
+
'groups' => [],
|
77 |
+
'roles' => []
|
78 |
+
],
|
79 |
'position' => 'after',
|
80 |
+
'display_style' => [
|
81 |
'icon' => true,
|
82 |
'text' => true
|
83 |
+
],
|
|
|
84 |
'icon_class' => 'dashicons-chart-bar',
|
85 |
'toolbar_statistics' => true
|
86 |
+
],
|
87 |
+
'version' => '1.3.7'
|
88 |
+
];
|
89 |
|
90 |
/**
|
91 |
* Disable object cloning.
|
92 |
+
*
|
93 |
+
* @return void
|
94 |
*/
|
95 |
public function __clone() {}
|
96 |
|
97 |
/**
|
98 |
* Disable unserializing of the class.
|
99 |
+
*
|
100 |
+
* @return void
|
101 |
*/
|
102 |
public function __wakeup() {}
|
103 |
|
104 |
/**
|
105 |
* Main plugin instance,
|
106 |
* Insures that only one instance of the plugin exists in memory at one time.
|
107 |
+
*
|
108 |
* @return object
|
109 |
*/
|
110 |
public static function instance() {
|
122 |
self::$instance->crawler_detect = new Post_Views_Counter_Crawler_Detect();
|
123 |
// regular setup
|
124 |
} else {
|
125 |
+
add_action( 'plugins_loaded', [ self::$instance, 'load_textdomain' ] );
|
126 |
|
127 |
self::$instance->includes();
|
128 |
+
|
129 |
+
// create settings API
|
130 |
+
self::$instance->settings_api = new Post_Views_Counter_Settings_API(
|
131 |
+
[
|
132 |
+
'object' => self::$instance,
|
133 |
+
'prefix' => 'post_views_counter',
|
134 |
+
'slug' => 'post-views-counter',
|
135 |
+
'domain' => 'post-views-counter',
|
136 |
+
'plugin' => 'Post Views Counter',
|
137 |
+
'plugin_url' => 'POST_VIEWS_COUNTER_URL'
|
138 |
+
]
|
139 |
+
);
|
140 |
+
|
141 |
self::$instance->update = new Post_Views_Counter_Update();
|
142 |
self::$instance->settings = new Post_Views_Counter_Settings();
|
143 |
self::$instance->query = new Post_Views_Counter_Query();
|
176 |
*/
|
177 |
private function includes() {
|
178 |
include_once( POST_VIEWS_COUNTER_PATH . 'includes/update.php' );
|
179 |
+
include_once( POST_VIEWS_COUNTER_PATH . 'includes/settings-api.php' );
|
180 |
include_once( POST_VIEWS_COUNTER_PATH . 'includes/settings.php' );
|
181 |
include_once( POST_VIEWS_COUNTER_PATH . 'includes/columns.php' );
|
182 |
include_once( POST_VIEWS_COUNTER_PATH . 'includes/query.php' );
|
195 |
*/
|
196 |
public function __construct() {
|
197 |
if ( defined( 'SHORTINIT' ) && SHORTINIT ) {
|
198 |
+
$this->options = [
|
199 |
'general' => array_merge( $this->defaults['general'], get_option( 'post_views_counter_settings_general', $this->defaults['general'] ) ),
|
200 |
'display' => array_merge( $this->defaults['display'], get_option( 'post_views_counter_settings_display', $this->defaults['display'] ) )
|
201 |
+
];
|
202 |
} else {
|
203 |
+
register_activation_hook( __FILE__, [ $this, 'multisite_activation' ] );
|
204 |
+
register_deactivation_hook( __FILE__, [ $this, 'multisite_deactivation' ] );
|
205 |
|
206 |
// settings
|
207 |
+
$this->options = [
|
208 |
'general' => array_merge( $this->defaults['general'], get_option( 'post_views_counter_settings_general', $this->defaults['general'] ) ),
|
209 |
'display' => array_merge( $this->defaults['display'], get_option( 'post_views_counter_settings_display', $this->defaults['display'] ) )
|
210 |
+
];
|
211 |
|
212 |
// actions
|
213 |
+
add_action( 'admin_enqueue_scripts', [ $this, 'admin_enqueue_scripts' ] );
|
214 |
+
add_action( 'wp_loaded', [ $this, 'load_pluggable_functions' ], 10 );
|
215 |
+
// add_action( 'init', [ $this, 'gutenberg_blocks' ] );
|
216 |
+
add_action( 'admin_init', [ $this, 'update_notice' ] );
|
217 |
+
add_action( 'wp_ajax_pvc_dismiss_notice', [ $this, 'dismiss_notice' ] );
|
218 |
|
219 |
// filters
|
220 |
+
add_filter( 'plugin_row_meta', [ $this, 'plugin_row_meta' ], 10, 2 );
|
221 |
+
add_filter( 'plugin_action_links', [ $this, 'plugin_action_links' ], 10, 2 );
|
222 |
}
|
223 |
}
|
224 |
|
238 |
|
239 |
if ( $this->options['general']['update_version'] < $current_update ) {
|
240 |
// check version, if update version is lower than plugin version, set update notice to true
|
241 |
+
$this->options['general'] = array_merge(
|
242 |
+
$this->options['general'],
|
243 |
+
[
|
244 |
+
'update_version' => $current_update,
|
245 |
+
'update_notice' => true
|
246 |
+
]
|
247 |
+
);
|
248 |
|
249 |
update_option( 'post_views_counter_settings_general', $this->options['general'] );
|
250 |
|
258 |
// display current version notice
|
259 |
if ( $this->options['general']['update_notice'] === true ) {
|
260 |
// include notice js, only if needed
|
261 |
+
add_action( 'admin_print_scripts', [ $this, 'admin_inline_js' ], 999 );
|
262 |
|
263 |
// get activation date
|
264 |
$activation_date = get_option( 'post_views_counter_activation_date' );
|
283 |
* @param string $html
|
284 |
* @param string $status
|
285 |
* @param bool $paragraph
|
286 |
+
* @return void
|
287 |
*/
|
288 |
public function add_notice( $html = '', $status = 'error', $paragraph = true ) {
|
289 |
+
$this->notices[] = [
|
290 |
'html' => $html,
|
291 |
'status' => $status,
|
292 |
'paragraph' => $paragraph
|
293 |
+
];
|
294 |
|
295 |
+
add_action( 'admin_notices', [ $this, 'display_notice' ] );
|
296 |
}
|
297 |
|
298 |
/**
|
299 |
* Print admin notices.
|
300 |
+
*
|
301 |
+
* @return void
|
302 |
*/
|
303 |
public function display_notice() {
|
304 |
foreach( $this->notices as $notice ) {
|
313 |
|
314 |
/**
|
315 |
* Print admin scripts.
|
316 |
+
*
|
317 |
+
* @return void
|
318 |
*/
|
319 |
public function admin_inline_js() {
|
320 |
if ( ! current_user_can( 'install_plugins' ) )
|
348 |
|
349 |
/**
|
350 |
* Dismiss notice.
|
351 |
+
*
|
352 |
+
* @return void
|
353 |
*/
|
354 |
public function dismiss_notice() {
|
355 |
if ( ! current_user_can( 'install_plugins' ) )
|
362 |
// delay notice
|
363 |
case 'delay':
|
364 |
// set delay period to 1 week from now
|
365 |
+
$this->options['general'] = array_merge(
|
366 |
+
$this->options['general'],
|
367 |
+
[
|
368 |
+
'update_delay_date' => time() + 1209600
|
369 |
+
]
|
370 |
+
);
|
371 |
update_option( 'post_views_counter_settings_general', $this->options['general'] );
|
372 |
break;
|
373 |
|
374 |
// hide notice
|
375 |
default:
|
376 |
+
$this->options['general'] = array_merge(
|
377 |
+
$this->options['general'],
|
378 |
+
[
|
379 |
+
'update_notice' => false
|
380 |
+
]
|
381 |
+
);
|
382 |
+
$this->options['general'] = array_merge(
|
383 |
+
$this->options['general'],
|
384 |
+
[
|
385 |
+
'update_delay_date' => 0
|
386 |
+
]
|
387 |
+
);
|
388 |
|
389 |
update_option( 'post_views_counter_settings_general', $this->options['general'] );
|
390 |
}
|
398 |
*
|
399 |
* @global object $wpdb
|
400 |
* @param bool $networkwide
|
401 |
+
* @return void
|
402 |
*/
|
403 |
public function multisite_activation( $networkwide ) {
|
404 |
if ( is_multisite() && $networkwide ) {
|
405 |
global $wpdb;
|
406 |
|
407 |
+
$activated_blogs = [];
|
408 |
$current_blog_id = $wpdb->blogid;
|
409 |
$blogs_ids = $wpdb->get_col( $wpdb->prepare( 'SELECT blog_id FROM ' . $wpdb->blogs, '' ) );
|
410 |
|
415 |
}
|
416 |
|
417 |
switch_to_blog( $current_blog_id );
|
418 |
+
update_site_option( 'post_views_counter_activated_blogs', $activated_blogs, [] );
|
419 |
} else
|
420 |
$this->activate_single();
|
421 |
}
|
424 |
* Single site activation.
|
425 |
*
|
426 |
* @global array $wp_roles
|
427 |
+
* @return void
|
428 |
*/
|
429 |
public function activate_single() {
|
430 |
global $wpdb, $charset_collate;
|
459 |
*
|
460 |
* @global array $wpdb
|
461 |
* @param bool $networkwide
|
462 |
+
* @return void
|
463 |
*/
|
464 |
public function multisite_deactivation( $networkwide ) {
|
465 |
if ( is_multisite() && $networkwide ) {
|
469 |
$blogs_ids = $wpdb->get_col( $wpdb->prepare( 'SELECT blog_id FROM ' . $wpdb->blogs, '' ) );
|
470 |
|
471 |
if ( ! ( $activated_blogs = get_site_option( 'post_views_counter_activated_blogs', false, false ) ) )
|
472 |
+
$activated_blogs = [];
|
473 |
|
474 |
foreach ( $blogs_ids as $blog_id ) {
|
475 |
switch_to_blog( $blog_id );
|
490 |
*
|
491 |
* @global array $wp_roles
|
492 |
* @param bool $multi
|
493 |
+
* @return void
|
494 |
*/
|
495 |
public function deactivate_single( $multi = false ) {
|
496 |
if ( $multi ) {
|
512 |
|
513 |
// remove schedule
|
514 |
wp_clear_scheduled_hook( 'pvc_reset_counts' );
|
515 |
+
remove_action( 'pvc_reset_counts', [ Post_Views_Counter()->cron, 'reset_counts' ] );
|
516 |
|
517 |
$this->remove_cache_flush();
|
518 |
}
|
521 |
* Schedule cache flushing if it's not already scheduled.
|
522 |
*
|
523 |
* @param bool $forced
|
524 |
+
* @return void
|
525 |
*/
|
526 |
public function schedule_cache_flush( $forced = true ) {
|
527 |
if ( $forced || ! wp_next_scheduled( 'pvc_flush_cached_counts' ) )
|
530 |
|
531 |
/**
|
532 |
* Remove scheduled cache flush and the corresponding action.
|
533 |
+
*
|
534 |
+
* @return void
|
535 |
*/
|
536 |
public function remove_cache_flush() {
|
537 |
wp_clear_scheduled_hook( 'pvc_flush_cached_counts' );
|
538 |
+
remove_action( 'pvc_flush_cached_counts', [ Post_Views_Counter()->cron, 'flush_cached_counts' ] );
|
539 |
}
|
540 |
|
541 |
/**
|
542 |
+
* Load text domain..
|
543 |
+
*
|
544 |
+
* @return void
|
545 |
*/
|
546 |
public function load_textdomain() {
|
547 |
load_plugin_textdomain( 'post-views-counter', false, POST_VIEWS_COUNTER_REL_PATH . 'languages/' );
|
548 |
}
|
549 |
|
550 |
/**
|
551 |
+
* Load pluggable template functions..
|
552 |
+
*
|
553 |
+
* @return void
|
554 |
*/
|
555 |
public function load_pluggable_functions() {
|
556 |
include_once( POST_VIEWS_COUNTER_PATH . 'includes/functions.php' );
|
557 |
}
|
558 |
|
559 |
/**
|
560 |
+
* Add Gutenberg blocks..
|
561 |
+
*
|
562 |
+
* @return void
|
563 |
*/
|
564 |
public function gutenberg_blocks() {
|
565 |
+
wp_register_script( 'pvc-admin-block-views', POST_VIEWS_COUNTER_URL . '/js/admin-block.js', [ 'wp-blocks', 'wp-element', 'wp-i18n' ] );
|
566 |
|
567 |
+
register_block_type( 'post-views-counter/views', [ 'editor_script' => 'pvc-admin-block-views' ] );
|
568 |
}
|
569 |
|
570 |
/**
|
571 |
* Enqueue admin scripts and styles.
|
572 |
*
|
573 |
* @global string $post_type
|
574 |
+
* @param string $page.
|
575 |
+
* @return void
|
576 |
*/
|
577 |
public function admin_enqueue_scripts( $page ) {
|
578 |
wp_register_style( 'pvc-admin', POST_VIEWS_COUNTER_URL . '/css/admin.css' );
|
579 |
|
580 |
+
wp_register_script( 'pvc-admin-settings', POST_VIEWS_COUNTER_URL . '/js/admin-settings.js', [ 'jquery' ], $this->defaults['version'] );
|
581 |
+
wp_register_script( 'pvc-admin-post', POST_VIEWS_COUNTER_URL . '/js/admin-post.js', [ 'jquery' ], $this->defaults['version'] );
|
582 |
+
wp_register_script( 'pvc-admin-quick-edit', POST_VIEWS_COUNTER_URL . '/js/admin-quick-edit.js', [ 'jquery', 'inline-edit-post' ], $this->defaults['version'] );
|
583 |
|
584 |
// load on PVC settings page
|
585 |
if ( $page === 'settings_page_post-views-counter' ) {
|
586 |
wp_enqueue_script( 'pvc-admin-settings' );
|
587 |
|
588 |
wp_localize_script(
|
589 |
+
'pvc-admin-settings', 'pvcArgsSettings', [
|
590 |
'resetToDefaults' => __( 'Are you sure you want to reset these settings to defaults?', 'post-views-counter' ),
|
591 |
'resetViews' => __( 'Are you sure you want to delete all existing data?', 'post-views-counter' )
|
592 |
+
]
|
593 |
);
|
594 |
|
595 |
wp_enqueue_style( 'pvc-admin' );
|
621 |
wp_enqueue_script( 'pvc-admin-quick-edit' );
|
622 |
// widgets
|
623 |
} elseif ( $page === 'widgets.php' )
|
624 |
+
wp_enqueue_script( 'pvc-admin-widgets', POST_VIEWS_COUNTER_URL . '/js/admin-widgets.js', [ 'jquery' ], $this->defaults['version'] );
|
625 |
// media
|
626 |
elseif ( $page === 'upload.php' )
|
627 |
wp_enqueue_style( 'pvc-admin' );
|
642 |
|
643 |
if ( $file == $plugin ) {
|
644 |
return array_merge(
|
645 |
+
$links,
|
646 |
+
[
|
647 |
+
sprintf( '<a href="http://www.dfactory.eu/support/forum/post-views-counter/" target="_blank">%s</a>', __( 'Support', 'post-views-counter' ) )
|
648 |
+
]
|
649 |
);
|
650 |
}
|
651 |
|
readme.txt
CHANGED
@@ -5,7 +5,7 @@ Tags: counter, hits, posts, postviews, post views, views, count, statistics, sta
|
|
5 |
Requires at least: 5.0
|
6 |
Requires PHP: 5.2.4
|
7 |
Tested up to: 5.8.1
|
8 |
-
Stable tag: 1.3.
|
9 |
License: MIT License
|
10 |
License URI: http://opensource.org/licenses/MIT
|
11 |
|
@@ -62,6 +62,9 @@ No questions yet.
|
|
62 |
|
63 |
== Changelog ==
|
64 |
|
|
|
|
|
|
|
65 |
= 1.3.6 =
|
66 |
* Fix: Option to hide admin bar chart
|
67 |
|
@@ -219,5 +222,5 @@ Initial release
|
|
219 |
|
220 |
== Upgrade Notice ==
|
221 |
|
222 |
-
= 1.3.
|
223 |
-
*
|
5 |
Requires at least: 5.0
|
6 |
Requires PHP: 5.2.4
|
7 |
Tested up to: 5.8.1
|
8 |
+
Stable tag: 1.3.7
|
9 |
License: MIT License
|
10 |
License URI: http://opensource.org/licenses/MIT
|
11 |
|
62 |
|
63 |
== Changelog ==
|
64 |
|
65 |
+
= 1.3.7 =
|
66 |
+
* Tweak: Implemented internal settings API
|
67 |
+
|
68 |
= 1.3.6 =
|
69 |
* Fix: Option to hide admin bar chart
|
70 |
|
222 |
|
223 |
== Upgrade Notice ==
|
224 |
|
225 |
+
= 1.3.7 =
|
226 |
+
* Tweak: Implemented internal settings API
|