Post Views Counter - Version 1.3.4

Version Description

  • New: Post Views stats preview in the admin bar
  • New: Top Posts data available in the dashboard widget
  • Tweak: Improved privacy using IP encrypting
  • Tweak: PHP 8.x compatibility
Download this release

Release Info

Developer dfactory
Plugin Icon 128x128 Post Views Counter
Version 1.3.4
Comparing to
See all releases

Code changes from version 1.3.3 to 1.3.4

assets/microtip/microtip.css ADDED
@@ -0,0 +1,266 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* -------------------------------------------------------------------
2
+ Microtip
3
+
4
+ Modern, lightweight css-only tooltips
5
+ Just 1kb minified and gzipped
6
+
7
+ @author Ghosh
8
+ @package Microtip
9
+
10
+ ----------------------------------------------------------------------
11
+ 1. Base Styles
12
+ 2. Direction Modifiers
13
+ 3. Position Modifiers
14
+ --------------------------------------------------------------------*/
15
+
16
+
17
+ /* ------------------------------------------------
18
+ [1] Base Styles
19
+ -------------------------------------------------*/
20
+
21
+ [aria-label][role~="tooltip"] {
22
+ position: relative;
23
+ }
24
+
25
+ [aria-label][role~="tooltip"]::before,
26
+ [aria-label][role~="tooltip"]::after {
27
+ transform: translate3d(0, 0, 0);
28
+ -webkit-backface-visibility: hidden;
29
+ backface-visibility: hidden;
30
+ will-change: transform;
31
+ opacity: 0;
32
+ pointer-events: none;
33
+ transition: all var(--microtip-transition-duration, .18s) var(--microtip-transition-easing, ease-in-out) var(--microtip-transition-delay, 0s);
34
+ position: absolute;
35
+ box-sizing: border-box;
36
+ z-index: 10;
37
+ transform-origin: top;
38
+ }
39
+
40
+ [aria-label][role~="tooltip"]::before {
41
+ background-size: 100% auto !important;
42
+ content: "";
43
+ }
44
+
45
+ [aria-label][role~="tooltip"]::after {
46
+ background: rgba(17, 17, 17, .9);
47
+ border-radius: 4px;
48
+ color: #ffffff;
49
+ content: attr(aria-label);
50
+ font-size: var(--microtip-font-size, 13px);
51
+ font-weight: var(--microtip-font-weight, normal);
52
+ text-transform: var(--microtip-text-transform, none);
53
+ padding: .5em 1em;
54
+ white-space: nowrap;
55
+ box-sizing: content-box;
56
+ }
57
+
58
+ [aria-label][role~="tooltip"]:hover::before,
59
+ [aria-label][role~="tooltip"]:hover::after,
60
+ [aria-label][role~="tooltip"]:focus::before,
61
+ [aria-label][role~="tooltip"]:focus::after {
62
+ opacity: 1;
63
+ pointer-events: auto;
64
+ }
65
+
66
+
67
+
68
+ /* ------------------------------------------------
69
+ [2] Position Modifiers
70
+ -------------------------------------------------*/
71
+
72
+ [role~="tooltip"][data-microtip-position|="top"]::before {
73
+ background: url("data:image/svg+xml;charset=utf-8,%3Csvg%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%20width%3D%2236px%22%20height%3D%2212px%22%3E%3Cpath%20fill%3D%22rgba%2817,%2017,%2017,%200.9%29%22%20transform%3D%22rotate%280%29%22%20d%3D%22M2.658,0.000%20C-13.615,0.000%2050.938,0.000%2034.662,0.000%20C28.662,0.000%2023.035,12.002%2018.660,12.002%20C14.285,12.002%208.594,0.000%202.658,0.000%20Z%22/%3E%3C/svg%3E") no-repeat;
74
+ height: 6px;
75
+ width: 18px;
76
+ margin-bottom: 5px;
77
+ }
78
+
79
+ [role~="tooltip"][data-microtip-position|="top"]::after {
80
+ margin-bottom: 11px;
81
+ }
82
+
83
+ [role~="tooltip"][data-microtip-position|="top"]::before {
84
+ transform: translate3d(-50%, 0, 0);
85
+ bottom: 100%;
86
+ left: 50%;
87
+ }
88
+
89
+ [role~="tooltip"][data-microtip-position|="top"]:hover::before {
90
+ transform: translate3d(-50%, -5px, 0);
91
+ }
92
+
93
+ [role~="tooltip"][data-microtip-position|="top"]::after {
94
+ transform: translate3d(-50%, 0, 0);
95
+ bottom: 100%;
96
+ left: 50%;
97
+ }
98
+
99
+ [role~="tooltip"][data-microtip-position="top"]:hover::after {
100
+ transform: translate3d(-50%, -5px, 0);
101
+ }
102
+
103
+ /* ------------------------------------------------
104
+ [2.1] Top Left
105
+ -------------------------------------------------*/
106
+ [role~="tooltip"][data-microtip-position="top-left"]::after {
107
+ transform: translate3d(calc(-100% + 16px), 0, 0);
108
+ bottom: 100%;
109
+ }
110
+
111
+ [role~="tooltip"][data-microtip-position="top-left"]:hover::after {
112
+ transform: translate3d(calc(-100% + 16px), -5px, 0);
113
+ }
114
+
115
+
116
+ /* ------------------------------------------------
117
+ [2.2] Top Right
118
+ -------------------------------------------------*/
119
+ [role~="tooltip"][data-microtip-position="top-right"]::after {
120
+ transform: translate3d(calc(0% + -16px), 0, 0);
121
+ bottom: 100%;
122
+ }
123
+
124
+ [role~="tooltip"][data-microtip-position="top-right"]:hover::after {
125
+ transform: translate3d(calc(0% + -16px), -5px, 0);
126
+ }
127
+
128
+
129
+ /* ------------------------------------------------
130
+ [2.3] Bottom
131
+ -------------------------------------------------*/
132
+ [role~="tooltip"][data-microtip-position|="bottom"]::before {
133
+ background: url("data:image/svg+xml;charset=utf-8,%3Csvg%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%20width%3D%2236px%22%20height%3D%2212px%22%3E%3Cpath%20fill%3D%22rgba%2817,%2017,%2017,%200.9%29%22%20transform%3D%22rotate%28180%2018%206%29%22%20d%3D%22M2.658,0.000%20C-13.615,0.000%2050.938,0.000%2034.662,0.000%20C28.662,0.000%2023.035,12.002%2018.660,12.002%20C14.285,12.002%208.594,0.000%202.658,0.000%20Z%22/%3E%3C/svg%3E") no-repeat;
134
+ height: 6px;
135
+ width: 18px;
136
+ margin-top: 5px;
137
+ margin-bottom: 0;
138
+ }
139
+
140
+ [role~="tooltip"][data-microtip-position|="bottom"]::after {
141
+ margin-top: 11px;
142
+ }
143
+
144
+ [role~="tooltip"][data-microtip-position|="bottom"]::before {
145
+ transform: translate3d(-50%, -10px, 0);
146
+ bottom: auto;
147
+ left: 50%;
148
+ top: 100%;
149
+ }
150
+
151
+ [role~="tooltip"][data-microtip-position|="bottom"]:hover::before {
152
+ transform: translate3d(-50%, 0, 0);
153
+ }
154
+
155
+ [role~="tooltip"][data-microtip-position|="bottom"]::after {
156
+ transform: translate3d(-50%, -10px, 0);
157
+ top: 100%;
158
+ left: 50%;
159
+ }
160
+
161
+ [role~="tooltip"][data-microtip-position="bottom"]:hover::after {
162
+ transform: translate3d(-50%, 0, 0);
163
+ }
164
+
165
+
166
+ /* ------------------------------------------------
167
+ [2.4] Bottom Left
168
+ -------------------------------------------------*/
169
+ [role~="tooltip"][data-microtip-position="bottom-left"]::after {
170
+ transform: translate3d(calc(-100% + 16px), -10px, 0);
171
+ top: 100%;
172
+ }
173
+
174
+ [role~="tooltip"][data-microtip-position="bottom-left"]:hover::after {
175
+ transform: translate3d(calc(-100% + 16px), 0, 0);
176
+ }
177
+
178
+
179
+ /* ------------------------------------------------
180
+ [2.5] Bottom Right
181
+ -------------------------------------------------*/
182
+ [role~="tooltip"][data-microtip-position="bottom-right"]::after {
183
+ transform: translate3d(calc(0% + -16px), -10px, 0);
184
+ top: 100%;
185
+ }
186
+
187
+ [role~="tooltip"][data-microtip-position="bottom-right"]:hover::after {
188
+ transform: translate3d(calc(0% + -16px), 0, 0);
189
+ }
190
+
191
+
192
+ /* ------------------------------------------------
193
+ [2.6] Left
194
+ -------------------------------------------------*/
195
+ [role~="tooltip"][data-microtip-position="left"]::before,
196
+ [role~="tooltip"][data-microtip-position="left"]::after {
197
+ bottom: auto;
198
+ left: auto;
199
+ right: 100%;
200
+ top: 50%;
201
+ transform: translate3d(10px, -50%, 0);
202
+ }
203
+
204
+ [role~="tooltip"][data-microtip-position="left"]::before {
205
+ background: url("data:image/svg+xml;charset=utf-8,%3Csvg%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%20width%3D%2212px%22%20height%3D%2236px%22%3E%3Cpath%20fill%3D%22rgba%2817,%2017,%2017,%200.9%29%22%20transform%3D%22rotate%28-90%2018%2018%29%22%20d%3D%22M2.658,0.000%20C-13.615,0.000%2050.938,0.000%2034.662,0.000%20C28.662,0.000%2023.035,12.002%2018.660,12.002%20C14.285,12.002%208.594,0.000%202.658,0.000%20Z%22/%3E%3C/svg%3E") no-repeat;
206
+ height: 18px;
207
+ width: 6px;
208
+ margin-right: 5px;
209
+ margin-bottom: 0;
210
+ }
211
+
212
+ [role~="tooltip"][data-microtip-position="left"]::after {
213
+ margin-right: 11px;
214
+ }
215
+
216
+ [role~="tooltip"][data-microtip-position="left"]:hover::before,
217
+ [role~="tooltip"][data-microtip-position="left"]:hover::after {
218
+ transform: translate3d(0, -50%, 0);
219
+ }
220
+
221
+
222
+ /* ------------------------------------------------
223
+ [2.7] Right
224
+ -------------------------------------------------*/
225
+ [role~="tooltip"][data-microtip-position="right"]::before,
226
+ [role~="tooltip"][data-microtip-position="right"]::after {
227
+ bottom: auto;
228
+ left: 100%;
229
+ top: 50%;
230
+ transform: translate3d(-10px, -50%, 0);
231
+ }
232
+
233
+ [role~="tooltip"][data-microtip-position="right"]::before {
234
+ background: url("data:image/svg+xml;charset=utf-8,%3Csvg%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%20width%3D%2212px%22%20height%3D%2236px%22%3E%3Cpath%20fill%3D%22rgba%2817,%2017,%2017,%200.9%29%22%20transform%3D%22rotate%2890%206%206%29%22%20d%3D%22M2.658,0.000%20C-13.615,0.000%2050.938,0.000%2034.662,0.000%20C28.662,0.000%2023.035,12.002%2018.660,12.002%20C14.285,12.002%208.594,0.000%202.658,0.000%20Z%22/%3E%3C/svg%3E") no-repeat;
235
+ height: 18px;
236
+ width: 6px;
237
+ margin-bottom: 0;
238
+ margin-left: 5px;
239
+ }
240
+
241
+ [role~="tooltip"][data-microtip-position="right"]::after {
242
+ margin-left: 11px;
243
+ }
244
+
245
+ [role~="tooltip"][data-microtip-position="right"]:hover::before,
246
+ [role~="tooltip"][data-microtip-position="right"]:hover::after {
247
+ transform: translate3d(0, -50%, 0);
248
+ }
249
+
250
+ /* ------------------------------------------------
251
+ [3] Size
252
+ -------------------------------------------------*/
253
+ [role~="tooltip"][data-microtip-size="small"]::after {
254
+ white-space: initial;
255
+ width: 80px;
256
+ }
257
+
258
+ [role~="tooltip"][data-microtip-size="medium"]::after {
259
+ white-space: initial;
260
+ width: 150px;
261
+ }
262
+
263
+ [role~="tooltip"][data-microtip-size="large"]::after {
264
+ white-space: initial;
265
+ width: 260px;
266
+ }
assets/microtip/microtip.min.css ADDED
@@ -0,0 +1,15 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* -------------------------------------------------------------------
2
+ Microtip
3
+
4
+ Modern, lightweight css-only tooltips
5
+ Just 1kb minified and gzipped
6
+
7
+ @author Ghosh
8
+ @package Microtip
9
+
10
+ ----------------------------------------------------------------------
11
+ 1. Base Styles
12
+ 2. Direction Modifiers
13
+ 3. Position Modifiers
14
+ --------------------------------------------------------------------*/
15
+ [aria-label][role~="tooltip"]{position:relative}[aria-label][role~="tooltip"]::before,[aria-label][role~="tooltip"]::after{transform:translate3d(0,0,0);-webkit-backface-visibility:hidden;backface-visibility:hidden;will-change:transform;opacity:0;pointer-events:none;transition:all var(--microtip-transition-duration,.18s) var(--microtip-transition-easing,ease-in-out) var(--microtip-transition-delay,0s);position:absolute;box-sizing:border-box;z-index:10;transform-origin:top}[aria-label][role~="tooltip"]::before{background-size:100% auto!important;content:""}[aria-label][role~="tooltip"]::after{background:rgba(17,17,17,.9);border-radius:4px;color:#fff;content:attr(aria-label);font-size:var(--microtip-font-size,13px);font-weight:var(--microtip-font-weight,normal);text-transform:var(--microtip-text-transform,none);padding:.5em 1em;white-space:nowrap;box-sizing:content-box}[aria-label][role~="tooltip"]:hover::before,[aria-label][role~="tooltip"]:hover::after,[aria-label][role~="tooltip"]:focus::before,[aria-label][role~="tooltip"]:focus::after{opacity:1;pointer-events:auto}[role~="tooltip"][data-microtip-position|="top"]::before{background:url(data:image/svg+xml;charset=utf-8,%3Csvg%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%20width%3D%2236px%22%20height%3D%2212px%22%3E%3Cpath%20fill%3D%22rgba%2817,%2017,%2017,%200.9%29%22%20transform%3D%22rotate%280%29%22%20d%3D%22M2.658,0.000%20C-13.615,0.000%2050.938,0.000%2034.662,0.000%20C28.662,0.000%2023.035,12.002%2018.660,12.002%20C14.285,12.002%208.594,0.000%202.658,0.000%20Z%22/%3E%3C/svg%3E) no-repeat;height:6px;width:18px;margin-bottom:5px}[role~="tooltip"][data-microtip-position|="top"]::after{margin-bottom:11px}[role~="tooltip"][data-microtip-position|="top"]::before{transform:translate3d(-50%,0,0);bottom:100%;left:50%}[role~="tooltip"][data-microtip-position|="top"]:hover::before{transform:translate3d(-50%,-5px,0)}[role~="tooltip"][data-microtip-position|="top"]::after{transform:translate3d(-50%,0,0);bottom:100%;left:50%}[role~="tooltip"][data-microtip-position="top"]:hover::after{transform:translate3d(-50%,-5px,0)}[role~="tooltip"][data-microtip-position="top-left"]::after{transform:translate3d(calc(-100% + 16px),0,0);bottom:100%}[role~="tooltip"][data-microtip-position="top-left"]:hover::after{transform:translate3d(calc(-100% + 16px),-5px,0)}[role~="tooltip"][data-microtip-position="top-right"]::after{transform:translate3d(calc(0% + -16px),0,0);bottom:100%}[role~="tooltip"][data-microtip-position="top-right"]:hover::after{transform:translate3d(calc(0% + -16px),-5px,0)}[role~="tooltip"][data-microtip-position|="bottom"]::before{background:url(data:image/svg+xml;charset=utf-8,%3Csvg%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%20width%3D%2236px%22%20height%3D%2212px%22%3E%3Cpath%20fill%3D%22rgba%2817,%2017,%2017,%200.9%29%22%20transform%3D%22rotate%28180%2018%206%29%22%20d%3D%22M2.658,0.000%20C-13.615,0.000%2050.938,0.000%2034.662,0.000%20C28.662,0.000%2023.035,12.002%2018.660,12.002%20C14.285,12.002%208.594,0.000%202.658,0.000%20Z%22/%3E%3C/svg%3E) no-repeat;height:6px;width:18px;margin-top:5px;margin-bottom:0}[role~="tooltip"][data-microtip-position|="bottom"]::after{margin-top:11px}[role~="tooltip"][data-microtip-position|="bottom"]::before{transform:translate3d(-50%,-10px,0);bottom:auto;left:50%;top:100%}[role~="tooltip"][data-microtip-position|="bottom"]:hover::before{transform:translate3d(-50%,0,0)}[role~="tooltip"][data-microtip-position|="bottom"]::after{transform:translate3d(-50%,-10px,0);top:100%;left:50%}[role~="tooltip"][data-microtip-position="bottom"]:hover::after{transform:translate3d(-50%,0,0)}[role~="tooltip"][data-microtip-position="bottom-left"]::after{transform:translate3d(calc(-100% + 16px),-10px,0);top:100%}[role~="tooltip"][data-microtip-position="bottom-left"]:hover::after{transform:translate3d(calc(-100% + 16px),0,0)}[role~="tooltip"][data-microtip-position="bottom-right"]::after{transform:translate3d(calc(0% + -16px),-10px,0);top:100%}[role~="tooltip"][data-microtip-position="bottom-right"]:hover::after{transform:translate3d(calc(0% + -16px),0,0)}[role~="tooltip"][data-microtip-position="left"]::before,[role~="tooltip"][data-microtip-position="left"]::after{bottom:auto;left:auto;right:100%;top:50%;transform:translate3d(10px,-50%,0)}[role~="tooltip"][data-microtip-position="left"]::before{background:url(data:image/svg+xml;charset=utf-8,%3Csvg%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%20width%3D%2212px%22%20height%3D%2236px%22%3E%3Cpath%20fill%3D%22rgba%2817,%2017,%2017,%200.9%29%22%20transform%3D%22rotate%28-90%2018%2018%29%22%20d%3D%22M2.658,0.000%20C-13.615,0.000%2050.938,0.000%2034.662,0.000%20C28.662,0.000%2023.035,12.002%2018.660,12.002%20C14.285,12.002%208.594,0.000%202.658,0.000%20Z%22/%3E%3C/svg%3E) no-repeat;height:18px;width:6px;margin-right:5px;margin-bottom:0}[role~="tooltip"][data-microtip-position="left"]::after{margin-right:11px}[role~="tooltip"][data-microtip-position="left"]:hover::before,[role~="tooltip"][data-microtip-position="left"]:hover::after{transform:translate3d(0,-50%,0)}[role~="tooltip"][data-microtip-position="right"]::before,[role~="tooltip"][data-microtip-position="right"]::after{bottom:auto;left:100%;top:50%;transform:translate3d(-10px,-50%,0)}[role~="tooltip"][data-microtip-position="right"]::before{background:url(data:image/svg+xml;charset=utf-8,%3Csvg%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%20width%3D%2212px%22%20height%3D%2236px%22%3E%3Cpath%20fill%3D%22rgba%2817,%2017,%2017,%200.9%29%22%20transform%3D%22rotate%2890%206%206%29%22%20d%3D%22M2.658,0.000%20C-13.615,0.000%2050.938,0.000%2034.662,0.000%20C28.662,0.000%2023.035,12.002%2018.660,12.002%20C14.285,12.002%208.594,0.000%202.658,0.000%20Z%22/%3E%3C/svg%3E) no-repeat;height:18px;width:6px;margin-bottom:0;margin-left:5px}[role~="tooltip"][data-microtip-position="right"]::after{margin-left:11px}[role~="tooltip"][data-microtip-position="right"]:hover::before,[role~="tooltip"][data-microtip-position="right"]:hover::after{transform:translate3d(0,-50%,0)}[role~="tooltip"][data-microtip-size="small"]::after{white-space:initial;width:80px}[role~="tooltip"][data-microtip-size="medium"]::after{white-space:initial;width:150px}[role~="tooltip"][data-microtip-size="large"]::after{white-space:initial;width:260px}
css/admin-dashboard.css CHANGED
@@ -1,29 +1,206 @@
1
- #pvc_dashboard_container {
2
- color: #aaa;
3
- min-height: 240px;
4
  margin: 0 -4px;
5
  text-align: center;
6
  position: relative;
 
 
7
  }
8
- #pvc_dashboard_container .spinner {
9
  position: absolute;
10
  left: 50%;
11
  top: 40%;
12
  margin-left: -10px;
 
13
  }
14
- #pvc_dashboard p.sub {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
15
  color: #8f8f8f;
16
  font-size: 14px;
17
  text-align: left;
18
  padding-bottom: 3px;
19
  border-bottom: 1px solid #ececec;
20
  }
21
- #pvc_dashboard_container .pvc_months {
 
 
22
  margin: 6px 10px 0 10px;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
23
  }
24
- #pvc_dashboard_container .pvc_months a.prev {
25
- float: left;
26
  }
27
- #pvc_dashboard_container .pvc_months a.next, #pvc_dashboard_container .pvc_months span.next {
28
- float: right;
29
  }
1
+ .pvc-dashboard-container {
2
+ min-height: 260px;
 
3
  margin: 0 -4px;
4
  text-align: center;
5
  position: relative;
6
+ display: flex;
7
+ flex-direction: column;
8
  }
9
+ .pvc-dashboard-container .spinner {
10
  position: absolute;
11
  left: 50%;
12
  top: 40%;
13
  margin-left: -10px;
14
+ z-index: 10;
15
  }
16
+ .pvc-dashboard-container.loading {
17
+ pointer-events: none;
18
+ }
19
+ .pvc-dashboard-container.loading:after {
20
+ position: absolute;
21
+ content: '';
22
+ display: block;
23
+ height: 100%;
24
+ width: 100%;
25
+ top: 0;
26
+ left: 0;
27
+ background-color: rgba(255,255,255,0.8);
28
+ z-index: 1;
29
+ transition: all 0.2s;
30
+ }
31
+ .pvc-dashboard p.sub {
32
  color: #8f8f8f;
33
  font-size: 14px;
34
  text-align: left;
35
  padding-bottom: 3px;
36
  border-bottom: 1px solid #ececec;
37
  }
38
+ .pvc-dashboard-container .pvc-months {
39
+ display: flex;
40
+ justify-content: space-between;
41
  margin: 6px 10px 0 10px;
42
+ color: #aaa;
43
+ }
44
+ .pvc-dashboard-container .pvc-months .current {
45
+ color: #212529;
46
+ }
47
+ #pvc-chart-container {
48
+ min-height: 230px;
49
+ }
50
+
51
+ .pvc-data-container {
52
+ min-height: 230px;
53
+ }
54
+
55
+ .pvc-table-responsive {
56
+ overflow-x: auto;
57
+ -webkit-overflow-scrolling: touch;
58
+ }
59
+ .pvc-table {
60
+ caption-side: bottom;
61
+ border-collapse: collapse;
62
+ width: 100%;
63
+ margin-bottom: 1rem;
64
+ color: inherit;
65
+ vertical-align: top;
66
+ border-color: #dee2e6;
67
+ text-align: left;
68
+ }
69
+
70
+ .pvc-table > thead {
71
+ vertical-align: bottom;
72
+ color: #212529;
73
+ }
74
+
75
+ .pvc-table > tbody {
76
+ vertical-align: inherit;
77
+ }
78
+
79
+ .pvc-table tbody,
80
+ .pvc-table td,
81
+ .pvc-table tfoot,
82
+ .pvc-table th,
83
+ .pvc-table thead,
84
+ .pvc-table tr {
85
+ border-color: inherit;
86
+ border-style: solid;
87
+ border-width: 0;
88
+ }
89
+
90
+ .pvc-table th,
91
+ .pvc-table td {
92
+ text-align: inherit;
93
+ text-align: -webkit-match-parent;
94
+ }
95
+
96
+ .pvc-table th:first-child,
97
+ .pvc-table td:first-child {
98
+ width: 1px;
99
+ white-space: nowrap;
100
+ }
101
+
102
+ .pvc-table th:last-child,
103
+ .pvc-table td:last-child {
104
+ text-align: right;
105
+ }
106
+
107
+ .pvc-table .no-posts :last-child {
108
+ text-align: left;
109
+ }
110
+
111
+ .pvc-table > :not(caption) > * > * {
112
+ padding: .5rem .5rem;
113
+ background-color: transparent;
114
+ border-bottom-width: 1px;
115
+ box-shadow: inset 0 0 0 9999px transparent;
116
+ }
117
+
118
+ #pvc_dashboard .inside {
119
+ margin: 0;
120
+ padding: 0;
121
+ }
122
+ .pvc-accordion-toggle {
123
+ background-color: #fafafa;
124
+ border-bottom: 1px solid #eee;
125
+ cursor: pointer;
126
+ line-height: 1;
127
+ position: relative;
128
+ font-size: 14px;
129
+ font-weight: 400;
130
+ line-height: 1;
131
+ margin: 0;
132
+ padding: 11px 12px;
133
+ color: #23282c;
134
+ }
135
+ .pvc-accordion-toggle::before {
136
+ color: #72777c;
137
+ content: "\f142";
138
+ display: inline-block;
139
+ font: normal 20px/1 dashicons;
140
+ position: absolute;
141
+ right: 8px;
142
+ text-decoration: none !important;
143
+ text-indent: -1px;
144
+ transform: rotate(0deg);
145
+ speak: none;
146
+ -webkit-font-smoothing: antialiased;
147
+ -moz-osx-font-smoothing: grayscale;
148
+ top: 8px;
149
+ }
150
+ .pvc-accordion-title {
151
+ display: inline-block;
152
+ padding-right: 10px;
153
+ }
154
+ .pvc-accordion-actions {
155
+ position: absolute;
156
+ top: 0;
157
+ right: 0;
158
+ z-index: 1;
159
+ padding: 11px 30px 11px 0;
160
+ height: 14px;
161
+ line-height: 1;
162
+ }
163
+ .pvc-accordion-actions .pvc-accordion-action,
164
+ .pvc-accordion-actions .pvc-accordion-action::before {
165
+ font-size: 14px;
166
+ height: 14px;
167
+ width: 14px;
168
+ color: #72777c;
169
+ }
170
+ .pvc-tooltip {
171
+ position: relative;
172
+ }
173
+ .pvc-tooltip-icon {
174
+ display: inline-block;
175
+ width: 16px;
176
+ cursor: help;
177
+ }
178
+ .pvc-tooltip-icon::before {
179
+ color: #b4b9be;
180
+ content: "\f14c";
181
+ display: inline-block;
182
+ font: normal 16px/1 dashicons;
183
+ position: absolute;
184
+ text-decoration: none !important;
185
+ speak: none;
186
+ -webkit-font-smoothing: antialiased;
187
+ -moz-osx-font-smoothing: grayscale;
188
+ left: 0;
189
+ top: 2px;
190
+ }
191
+ .pvc-according-header {
192
+ display: flex;
193
+ align-items: center;
194
+ justify-content: space-between;
195
+ }
196
+ .pvc-accordion-content {
197
+ padding: 11px 12px;
198
+ border-bottom: 1px solid #eee;
199
+ height: 100%;
200
  }
201
+ .pvc-collapsed .pvc-accordion-toggle::before {
202
+ transform: rotate(180deg);
203
  }
204
+ .pvc-collapsed .pvc-accordion-content {
205
+ display: none;
206
  }
includes/columns.php CHANGED
@@ -20,15 +20,18 @@ class Post_Views_Counter_Columns {
20
  add_action( 'bulk_edit_custom_box', array( $this, 'quick_edit_custom_box' ), 10, 2 );
21
  add_action( 'quick_edit_custom_box', array( $this, 'quick_edit_custom_box' ), 10, 2 );
22
  add_action( 'wp_ajax_save_bulk_post_views', array( $this, 'save_bulk_post_views' ) );
 
 
 
23
 
24
  // gutenberg
25
- add_action( 'plugins_loaded', array( $this, 'init_gutemberg' ) );
26
  }
27
-
28
  /**
29
  * Init Gutenberg
30
  */
31
- public function init_gutemberg() {
32
  $block_editor = has_action( 'enqueue_block_assets' );
33
  $gutenberg = function_exists( 'gutenberg_can_edit_post_type' );
34
 
@@ -462,4 +465,141 @@ class Post_Views_Counter_Columns {
462
 
463
  exit;
464
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
465
  }
20
  add_action( 'bulk_edit_custom_box', array( $this, 'quick_edit_custom_box' ), 10, 2 );
21
  add_action( 'quick_edit_custom_box', array( $this, 'quick_edit_custom_box' ), 10, 2 );
22
  add_action( 'wp_ajax_save_bulk_post_views', array( $this, 'save_bulk_post_views' ) );
23
+ add_action( 'admin_bar_menu', array( $this, 'admin_bar_menu' ), 100 );
24
+ add_action( 'wp', array( $this, 'admin_bar_maybe_add_style' ) );
25
+ add_action( 'admin_init', array( $this, 'admin_bar_maybe_add_style' ) );
26
 
27
  // gutenberg
28
+ add_action( 'plugins_loaded', array( $this, 'init_gutenberg' ) );
29
  }
30
+
31
  /**
32
  * Init Gutenberg
33
  */
34
+ public function init_gutenberg() {
35
  $block_editor = has_action( 'enqueue_block_assets' );
36
  $gutenberg = function_exists( 'gutenberg_can_edit_post_type' );
37
 
465
 
466
  exit;
467
  }
468
+
469
+ /**
470
+ * Add admin bar stats to a post.
471
+ */
472
+ public function admin_bar_menu( $admin_bar ) {
473
+ $post = null;
474
+
475
+ if ( is_admin() && ! wp_doing_ajax() ) {
476
+ global $pagenow;
477
+
478
+ $post = $pagenow == 'post.php' && ! empty( $_GET['post'] ) ? get_post( (int) $_GET['post'] ) : $post;
479
+ } elseif ( is_singular() ) {
480
+ global $post;
481
+ }
482
+
483
+ // get countable post types
484
+ $post_types = Post_Views_Counter()->options['general']['post_types_count'];
485
+
486
+ // whether to count this post type or not
487
+ if ( empty( $post_types ) || empty( $post ) || ! in_array( $post->post_type, $post_types, true ) )
488
+ return;
489
+
490
+ $dt = new DateTime();
491
+ $date = $dt->format( 'Y-m-d\TH:i:s.v' );
492
+ $year = date_i18n( 'Y', $date );
493
+ $month = date_i18n( 'm', $date );
494
+ $week = date_i18n( 'W', $date );
495
+ $day = date_i18n( 'd', $date );
496
+
497
+ $views = pvc_get_views( array(
498
+ 'post_id' => $post->ID,
499
+ 'post_type' => $post->post_type,
500
+ 'fields' => 'date=>views',
501
+ 'views_query' => array(
502
+ 'year' => $year,
503
+ // 'week' => $week,
504
+ 'month' => $month,
505
+ // 'day' => $day
506
+ )
507
+ ) );
508
+
509
+ $graph = '';
510
+
511
+ // get highest value
512
+ $views_copy = $views;
513
+ arsort( $views_copy, SORT_NUMERIC );
514
+ $highest = reset( $views_copy );
515
+ // find the multiplier
516
+ $multiplier = $highest * 0.05;
517
+
518
+ // generate ranges
519
+ $ranges = array();
520
+
521
+ for ( $i = 1; $i <= 20; $i ++ ) {
522
+ $ranges[$i] = round( $multiplier * $i );
523
+ }
524
+
525
+ // create graph
526
+ foreach ( $views as $date => $count ) {
527
+ $count_class = 0;
528
+
529
+ if ( $count > 0 ) {
530
+ foreach ( $ranges as $index => $range ) {
531
+ if ( $count <= $range ) {
532
+ $count_class = $index;
533
+ break;
534
+ }
535
+ }
536
+ }
537
+
538
+ $graph .= '<span class="pvc-line-graph pvc-line-graph-' . $count_class . '" title="' . sprintf( _n( '%s post view', '%s post views', $count, 'post-views-counter' ), number_format_i18n( $count ) ) . '"></span>';
539
+ }
540
+
541
+ $admin_bar->add_menu( array(
542
+ 'id' => 'pvc-post-views',
543
+ 'title' => '<span class="pvc-graph-container">' . $graph . '</span>',
544
+ 'href' => false,
545
+ 'meta' => array(
546
+ 'title' => false
547
+ ),
548
+ ) );
549
+ }
550
+
551
+ /**
552
+ * Maybe add admin CSS.
553
+ */
554
+ public function admin_bar_maybe_add_style() {
555
+ $post = null;
556
+
557
+ if ( is_admin() && ! wp_doing_ajax() ) {
558
+ global $pagenow;
559
+
560
+ $post = $pagenow == 'post.php' && ! empty( $_GET['post'] ) ? get_post( (int) $_GET['post'] ) : $post;
561
+ } elseif ( is_singular() ) {
562
+ global $post;
563
+ }
564
+
565
+ // get countable post types
566
+ $post_types = Post_Views_Counter()->options['general']['post_types_count'];
567
+
568
+ // whether to count this post type or not
569
+ if ( empty( $post_types ) || empty( $post ) || ! in_array( $post->post_type, $post_types, true ) )
570
+ return;
571
+
572
+ // on backend area
573
+ add_action( 'admin_head', array( $this, 'admin_bar_css' ) );
574
+ // on frontend area
575
+ add_action( 'wp_head', array( $this, 'admin_bar_css' ) );
576
+ }
577
+
578
+ /**
579
+ * Add admin CSS.
580
+ */
581
+ public function admin_bar_css() {
582
+ $html = '
583
+ <style type="text/css">
584
+ #wp-admin-bar-pvc-post-views .pvc-graph-container { padding-top: 6px; padding-bottom: 6px; position: relative; display: block; height: 100%; box-sizing: border-box; }
585
+ #wp-admin-bar-pvc-post-views .pvc-line-graph {
586
+ display: inline-block;
587
+ width: 1px;
588
+ margin-right: 1px;
589
+ background-color: #ccc;
590
+ vertical-align: baseline;
591
+ }
592
+ #wp-admin-bar-pvc-post-views .pvc-line-graph:hover { background-color: #eee; }
593
+ #wp-admin-bar-pvc-post-views .pvc-line-graph-0 { height: 1% }';
594
+
595
+ for ( $i = 1; $i <= 20; $i ++ ) {
596
+ $html .= '
597
+ #wp-admin-bar-pvc-post-views .pvc-line-graph-' . $i . ' { height: ' . $i * 5 . '% }';
598
+ }
599
+
600
+ $html .= '
601
+ </style>';
602
+
603
+ echo $html;
604
+ }
605
  }
includes/counter.php CHANGED
@@ -74,6 +74,27 @@ class Post_Views_Counter_Counter {
74
  }
75
  }
76
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
77
 
78
  // get groups to check them faster
79
  $groups = Post_Views_Counter()->options['general']['exclude']['groups'];
@@ -365,7 +386,7 @@ class Post_Views_Counter_Counter {
365
  */
366
  private function save_ip( $id ) {
367
  $set_cookie = apply_filters( 'pvc_maybe_set_cookie', true );
368
-
369
  // Cookie Notice compatibility
370
  if ( function_exists( 'cn_cookies_accepted' ) && ! cn_cookies_accepted() )
371
  $set_cookie = false;
@@ -380,7 +401,7 @@ class Post_Views_Counter_Counter {
380
  $ip_cache = array();
381
 
382
  // get user IP address
383
- $user_ip = (string) $this->get_user_ip();
384
 
385
  // get current time
386
  $current_time = current_time( 'timestamp', true );
@@ -709,6 +730,8 @@ class Post_Views_Counter_Counter {
709
  * @return string
710
  */
711
  public function get_user_ip() {
 
 
712
  foreach ( array( 'HTTP_CLIENT_IP', 'HTTP_X_FORWARDED_FOR', 'HTTP_X_FORWARDED', 'HTTP_X_CLUSTER_CLIENT_IP', 'HTTP_FORWARDED_FOR', 'HTTP_FORWARDED', 'REMOTE_ADDR' ) as $key ) {
713
  if ( array_key_exists( $key, $_SERVER ) === true ) {
714
  foreach ( explode( ',', $_SERVER[$key] ) as $ip ) {
@@ -717,12 +740,12 @@ class Post_Views_Counter_Counter {
717
 
718
  // attempt to validate IP
719
  if ( $this->validate_user_ip( $ip ) )
720
- return $ip;
721
  }
722
  }
723
  }
724
 
725
- return isset( $_SERVER['REMOTE_ADDR'] ) ? $_SERVER['REMOTE_ADDR'] : '';
726
  }
727
 
728
  /**
@@ -737,6 +760,67 @@ class Post_Views_Counter_Counter {
737
 
738
  return true;
739
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
740
 
741
  /**
742
  * Register REST API endpoints.
74
  }
75
  }
76
  }
77
+
78
+ // strict counts?
79
+ if ( Post_Views_Counter()->options['general']['strict_counts'] ) {
80
+ // get IP cached visits
81
+ $ip_cache = get_transient( 'post_views_counter_ip_cache' );
82
+
83
+ if ( ! $ip_cache )
84
+ $ip_cache = array();
85
+
86
+ // get user IP address
87
+ $user_ip = $this->encrypt_ip( $this->get_user_ip() );
88
+
89
+ // get current time
90
+ $current_time = current_time( 'timestamp', true );
91
+
92
+ // visit exists in transient?
93
+ if ( isset( $ip_cache[$id][$user_ip] ) ) {
94
+ if ( $current_time < $ip_cache[$id][$user_ip] + $this->get_timestamp( Post_Views_Counter()->options['general']['time_between_counts']['type'], Post_Views_Counter()->options['general']['time_between_counts']['number'], false ) )
95
+ return;
96
+ }
97
+ }
98
 
99
  // get groups to check them faster
100
  $groups = Post_Views_Counter()->options['general']['exclude']['groups'];
386
  */
387
  private function save_ip( $id ) {
388
  $set_cookie = apply_filters( 'pvc_maybe_set_cookie', true );
389
+
390
  // Cookie Notice compatibility
391
  if ( function_exists( 'cn_cookies_accepted' ) && ! cn_cookies_accepted() )
392
  $set_cookie = false;
401
  $ip_cache = array();
402
 
403
  // get user IP address
404
+ $user_ip = $this->encrypt_ip( $this->get_user_ip() );
405
 
406
  // get current time
407
  $current_time = current_time( 'timestamp', true );
730
  * @return string
731
  */
732
  public function get_user_ip() {
733
+ $ip = isset( $_SERVER['REMOTE_ADDR'] ) ? $_SERVER['REMOTE_ADDR'] : '';
734
+
735
  foreach ( array( 'HTTP_CLIENT_IP', 'HTTP_X_FORWARDED_FOR', 'HTTP_X_FORWARDED', 'HTTP_X_CLUSTER_CLIENT_IP', 'HTTP_FORWARDED_FOR', 'HTTP_FORWARDED', 'REMOTE_ADDR' ) as $key ) {
736
  if ( array_key_exists( $key, $_SERVER ) === true ) {
737
  foreach ( explode( ',', $_SERVER[$key] ) as $ip ) {
740
 
741
  // attempt to validate IP
742
  if ( $this->validate_user_ip( $ip ) )
743
+ continue;
744
  }
745
  }
746
  }
747
 
748
+ return $ip;
749
  }
750
 
751
  /**
760
 
761
  return true;
762
  }
763
+
764
+ /**
765
+ * Encrypt user IP
766
+ *
767
+ * @param int $ip
768
+ * @return string $encrypted_ip
769
+ */
770
+ public function encrypt_ip( $ip ) {
771
+ $auth_key = defined( 'AUTH_KEY' ) ? AUTH_KEY : '';
772
+ $auth_iv = defined( 'NONCE_KEY' ) ? NONCE_KEY : '';
773
+
774
+ // mcrypt strong encryption
775
+ if ( function_exists( 'mcrypt_encrypt' ) && defined( 'MCRYPT_BLOWFISH' ) ) {
776
+ // get max key size of the mcrypt mode
777
+ $max_key_size = mcrypt_get_key_size( MCRYPT_BLOWFISH, MCRYPT_MODE_CBC );
778
+ $max_iv_size = mcrypt_get_iv_size( MCRYPT_BLOWFISH, MCRYPT_MODE_CBC );
779
+
780
+ $encrypt_key = mb_strimwidth( $auth_key, 0, $max_key_size );
781
+ $encrypt_iv = mb_strimwidth( $auth_iv, 0, $max_iv_size );
782
+
783
+ $encrypted_ip = strtr( base64_encode( mcrypt_encrypt( MCRYPT_BLOWFISH, $encrypt_key, $ip, MCRYPT_MODE_CBC, $encrypt_iv ) ), '+/=', '-_,' );
784
+ // simple encryption
785
+ } elseif ( function_exists( 'gzdeflate' ) )
786
+ $encrypted_ip = base64_encode( convert_uuencode( gzdeflate( $ip ) ) );
787
+ // no encryption
788
+ else
789
+ $encrypted_ip = strtr( base64_encode( convert_uuencode( $ip ) ), '+/=', '-_,' );
790
+
791
+ return $encrypted_ip;
792
+ }
793
+
794
+ /**
795
+ * Decrypt user IP
796
+ *
797
+ * @param int $encrypted_ip
798
+ * @return string $ip
799
+ */
800
+ public function decrypt_ip( $encrypted_ip ) {
801
+ $auth_key = defined( 'AUTH_KEY' ) ? AUTH_KEY : '';
802
+ $auth_iv = defined( 'NONCE_KEY' ) ? NONCE_KEY : '';
803
+
804
+ // mcrypt strong encryption
805
+ if ( function_exists( 'mcrypt_decrypt' ) && defined( 'MCRYPT_BLOWFISH' ) ) {
806
+ // get max key size of the mcrypt mode
807
+ $max_key_size = mcrypt_get_key_size( MCRYPT_BLOWFISH, MCRYPT_MODE_CBC );
808
+ $max_iv_size = mcrypt_get_iv_size( MCRYPT_BLOWFISH, MCRYPT_MODE_CBC );
809
+
810
+ $encrypt_key = mb_strimwidth( $auth_key, 0, $max_key_size );
811
+ $encrypt_iv = mb_strimwidth( $auth_iv, 0, $max_iv_size );
812
+
813
+ $ip = mcrypt_decrypt( MCRYPT_BLOWFISH, $encrypt_key, base64_decode( strtr( $encrypted_ip, '-_,', '+/=' ) ), MCRYPT_MODE_CBC, $encrypt_iv );
814
+ // simple encryption
815
+ } elseif ( function_exists( 'gzinflate' ) ) {
816
+ $ip = gzinflate( convert_uudecode( base64_decode( $encrypted_ip ) ) );
817
+ // no encryption
818
+ } else {
819
+ $ip = convert_uudecode( base64_decode( strtr( $encrypted_ip, '-_,', '+/=' ) ) );
820
+ }
821
+
822
+ return $ip;
823
+ }
824
 
825
  /**
826
  * Register REST API endpoints.
includes/dashboard.php CHANGED
@@ -12,10 +12,11 @@ class Post_Views_Counter_Dashboard {
12
 
13
  public function __construct() {
14
  // actions
15
- add_action( 'wp_dashboard_setup', array( $this, 'wp_dashboard_setup' ) );
16
  add_action( 'admin_enqueue_scripts', array( $this, 'admin_scripts_styles' ) );
17
- add_action( 'wp_ajax_pvc_dashboard_chart', array( $this, 'dashboard_widget_chart' ) );
18
- add_action( 'wp_ajax_pvc_dashboard_chart_user_post_types', array( $this, 'dashboard_widget_chart_user_post_types' ) );
 
19
  }
20
 
21
  /**
@@ -27,102 +28,112 @@ class Post_Views_Counter_Dashboard {
27
  return;
28
  }
29
 
30
- // add dashboard widget
31
- wp_add_dashboard_widget( 'pvc_dashboard', __( 'Post Views', 'post-views-counter' ), array( $this, 'dashboard_widget' ) );
32
  }
33
-
34
  /**
35
- * Render dashboard widget.
36
- *
37
- * @return mixed
38
  */
39
- public function dashboard_widget() {
40
- ?>
41
- <div id="pvc_dashboard_container">
42
- <canvas id="pvc_chart" height="175"></canvas>
43
- <div class="pvc_months">
44
-
45
- <?php echo $this->generate_months( current_time( 'timestamp', false ) ); ?>
46
 
47
- </div>
48
- </div>
49
- <?php
50
- }
51
 
52
- /**
53
- * Generate months.
54
- *
55
- * @param string $timestamp
56
- * @return string
57
- */
58
- public function generate_months( $timestamp ) {
59
- $dates = array(
60
- explode( ' ', date( "m F Y", strtotime( "-1 months", $timestamp ) ) ),
61
- explode( ' ', date( "m F Y", $timestamp ) ),
62
- explode( ' ', date( "m F Y", strtotime( "+1 months", $timestamp ) ) )
63
- );
64
 
65
- $current = date( "Ym", current_time( 'timestamp', false ) );
 
66
 
67
- if ( (int) $current <= (int) ( $dates[1][2] . $dates[1][0] ) )
68
- $next = '<span class="next">' . $dates[2][1] . ' ' . $dates[2][2] . ' ›</span>';
69
- else
70
- $next = '<a class="next" href="#" data-date="' . ( $dates[2][0] . '|' . $dates[2][2] ) . '">' . $dates[2][1] . ' ' . $dates[2][2] . ' ›</a>';
71
 
72
- $dates = array(
73
- 'prev' => '<a class="prev" href="#" data-date="' . ( $dates[0][0] . '|' . $dates[0][2] ) . '">‹ ' . $dates[0][1] . ' ' . $dates[0][2] . '</a>',
74
- 'current' => '<span class="current">' . $dates[1][1] . ' ' . $dates[1][2] . '</span>',
75
- 'next' => $next
 
 
 
 
76
  );
77
-
78
- return $dates['prev'] . $dates['current'] . $dates['next'];
79
  }
80
 
81
  /**
82
- * Dashboard widget chart user post types.
83
- *
84
- * @return void
85
  */
86
- public function dashboard_widget_chart_user_post_types() {
87
- if ( ! check_ajax_referer( 'dashboard-chart-user-post-types', 'nonce' ) )
88
- wp_die( __( 'You do not have permission to access this page.', 'post-views-counter' ) );
89
-
90
- // get post types
91
- $post_types = Post_Views_Counter()->options['general']['post_types_count'];
92
-
93
- // simulate total views as post type
94
- $post_types[] = '_pvc_total_views';
95
-
96
- // valid data?
97
- if ( isset( $_POST['nonce'], $_POST['hidden'], $_POST['post_type'] ) && ( in_array( $_POST['post_type'], $post_types, true ) ) ) {
98
- // get user ID
99
- $user_id = get_current_user_id();
100
-
101
- // get user dashboard data
102
- $userdata = get_user_meta( $user_id, 'pvc_dashboard', true );
103
-
104
- // empty userdata?
105
- if ( ! is_array( $userdata ) || empty( $userdata ) )
106
- $userdata = array();
107
-
108
- // empty post types?
109
- if ( ! array_key_exists( 'post_types', $userdata ) || ! is_array( $userdata['post_types'] ) )
110
- $userdata['post_types'] = array();
111
-
112
- // hide post type?
113
- if ( $_POST['hidden'] === 'true' ) {
114
- if ( ! in_array( $_POST['post_type'], $userdata['post_types'], true ) )
115
- $userdata['post_types'][] = $_POST['post_type'];
116
- } else {
117
- if ( ( $key = array_search( $_POST['post_type'], $userdata['post_types'] ) ) !== false )
118
- unset( $userdata['post_types'][$key] );
119
- }
120
-
121
- // update userdata
122
- update_user_meta( $user_id, 'pvc_dashboard', $userdata );
123
- }
124
-
125
- exit;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
126
  }
127
 
128
  /**
@@ -131,11 +142,11 @@ class Post_Views_Counter_Dashboard {
131
  * @global $_wp_admin_css_colors
132
  * @return void
133
  */
134
- public function dashboard_widget_chart() {
135
  if ( ! apply_filters( 'pvc_user_can_see_stats', current_user_can( 'publish_posts' ) ) )
136
  wp_die( _( 'You do not have permission to access this page.', 'post-views-counter' ) );
137
 
138
- if ( ! check_ajax_referer( 'dashboard-chart', 'nonce' ) )
139
  wp_die( __( 'You do not have permission to access this page.', 'post-views-counter' ) );
140
 
141
  // get period
@@ -273,7 +284,7 @@ class Post_Views_Counter_Dashboard {
273
 
274
  case 'this_month':
275
  default:
276
- $userdata = $this->get_dashboard_user_data( get_current_user_id(), 'post_types' );
277
 
278
  if ( $period !== 'this_month' ) {
279
  $date = explode( '|', $period, 2 );
@@ -304,7 +315,7 @@ class Post_Views_Counter_Dashboard {
304
 
305
  $data['data']['datasets'][0]['label'] = __( 'Total Views', 'post-views-counter' );
306
  $data['data']['datasets'][0]['post_type'] = '_pvc_total_views';
307
- $data['data']['datasets'][0]['hidden'] = in_array( '_pvc_total_views', $userdata, true );
308
 
309
  // reindex post types
310
  $post_types = array_combine( range( 1, count( $post_types ) ), array_values( $post_types ) );
@@ -316,7 +327,7 @@ class Post_Views_Counter_Dashboard {
316
 
317
  $data['data']['datasets'][$id]['label'] = $post_type_obj->labels->name;
318
  $data['data']['datasets'][$id]['post_type'] = $post_type_obj->name;
319
- $data['data']['datasets'][$id]['hidden'] = in_array( $post_type_obj->name, $userdata, true );
320
  $data['data']['datasets'][$id]['data'] = array();
321
 
322
  // get month views
@@ -364,56 +375,208 @@ class Post_Views_Counter_Dashboard {
364
 
365
  exit;
366
  }
 
 
 
 
 
 
 
 
 
 
367
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
368
  /**
369
- * Get user dashboard data.
370
  *
371
- * @param string $data_type
372
- * @return array
373
  */
374
- public function get_dashboard_user_data( $user_id, $data_type ) {
375
- $userdata = get_user_meta( $user_id, 'pvc_dashboard', true );
 
 
 
 
 
 
376
 
377
- if ( ! is_array( $userdata ) || empty( $userdata ) )
378
- $userdata = array();
 
 
379
 
380
- if ( ! array_key_exists( $data_type, $userdata ) || ! is_array( $userdata[$data_type] ) )
381
- $userdata[$data_type] = array();
 
 
 
382
 
383
- return $userdata[$data_type];
384
  }
385
 
386
  /**
387
- * Enqueue admin scripts and styles.
388
  *
389
- * @param string $pagenow
390
  */
391
- public function admin_scripts_styles( $pagenow ) {
392
- if ( $pagenow != 'index.php' )
393
- return;
394
 
395
- // filter user_can_see_stats
396
- if ( ! apply_filters( 'pvc_user_can_see_stats', current_user_can( 'publish_posts' ) ) )
397
- return;
398
 
399
- wp_register_style( 'pvc-admin-dashboard', POST_VIEWS_COUNTER_URL . '/css/admin-dashboard.css' );
400
- wp_enqueue_style( 'pvc-admin-dashboard' );
401
- wp_enqueue_style( 'pvc-chart-css', POST_VIEWS_COUNTER_URL . '/assets/chartjs/chart.min.css' );
 
 
402
 
403
- wp_register_script( 'pvc-chart', POST_VIEWS_COUNTER_URL . '/assets/chartjs/chart.min.js', array( 'jquery' ), Post_Views_Counter()->defaults['version'], true );
404
- wp_register_script( 'pvc-admin-dashboard', POST_VIEWS_COUNTER_URL . '/js/admin-dashboard.js', array( 'jquery', 'pvc-chart' ), Post_Views_Counter()->defaults['version'], true );
 
 
405
 
406
- wp_enqueue_script( 'pvc-admin-dashboard' );
 
407
 
408
- wp_localize_script(
409
- 'pvc-admin-dashboard',
410
- 'pvcArgs',
411
- array(
412
- 'ajaxURL' => admin_url( 'admin-ajax.php' ),
413
- 'nonce' => wp_create_nonce( 'dashboard-chart' ),
414
- 'nonceUser' => wp_create_nonce( 'dashboard-chart-user-post-types' )
415
- )
416
- );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
417
  }
418
 
419
  /**
12
 
13
  public function __construct() {
14
  // actions
15
+ add_action( 'wp_dashboard_setup', array( $this, 'wp_dashboard_setup' ), 1 );
16
  add_action( 'admin_enqueue_scripts', array( $this, 'admin_scripts_styles' ) );
17
+ add_action( 'wp_ajax_pvc_dashboard_most_viewed', array( $this, 'dashboard_get_most_viewed' ) );
18
+ add_action( 'wp_ajax_pvc_dashboard_chart', array( $this, 'dashboard_get_chart' ) );
19
+ add_action( 'wp_ajax_pvc_dashboard_user_options', array( $this, 'update_dashboard_user_options' ) );
20
  }
21
 
22
  /**
28
  return;
29
  }
30
 
31
+ // add dashboard post views chart widget
32
+ wp_add_dashboard_widget( 'pvc_dashboard', __( 'Post Views Counter', 'post-views-counter' ), array( $this, 'dashboard_widget' ) );
33
  }
34
+
35
  /**
36
+ * Enqueue admin scripts and styles.
37
+ *
38
+ * @param string $pagenow
39
  */
40
+ public function admin_scripts_styles( $pagenow ) {
41
+ if ( $pagenow != 'index.php' )
42
+ return;
 
 
 
 
43
 
44
+ // filter user_can_see_stats
45
+ if ( ! apply_filters( 'pvc_user_can_see_stats', current_user_can( 'publish_posts' ) ) )
46
+ return;
 
47
 
48
+ wp_register_style( 'pvc-admin-dashboard', POST_VIEWS_COUNTER_URL . '/css/admin-dashboard.css', array(), Post_Views_Counter()->defaults['version'] );
49
+ wp_enqueue_style( 'pvc-admin-dashboard' );
50
+ wp_enqueue_style( 'pvc-chartjs', POST_VIEWS_COUNTER_URL . '/assets/chartjs/chart.min.css', array(), Post_Views_Counter()->defaults['version'] );
51
+ wp_enqueue_style( 'pvc-microtip', POST_VIEWS_COUNTER_URL . '/assets/microtip/microtip.min.css', array(), Post_Views_Counter()->defaults['version'] );
 
 
 
 
 
 
 
 
52
 
53
+ wp_register_script( 'pvc-chartjs', POST_VIEWS_COUNTER_URL . '/assets/chartjs/chart.min.js', array( 'jquery' ), Post_Views_Counter()->defaults['version'], true );
54
+ wp_register_script( 'pvc-admin-dashboard', POST_VIEWS_COUNTER_URL . '/js/admin-dashboard.js', array( 'jquery', 'pvc-chartjs' ), Post_Views_Counter()->defaults['version'], true );
55
 
56
+ wp_enqueue_script( 'pvc-admin-dashboard' );
 
 
 
57
 
58
+ wp_localize_script(
59
+ 'pvc-admin-dashboard',
60
+ 'pvcArgs',
61
+ array(
62
+ 'ajaxURL' => admin_url( 'admin-ajax.php' ),
63
+ 'nonce' => wp_create_nonce( 'pvc-dashboard-chart' ),
64
+ 'nonceUser' => wp_create_nonce( 'pvc-dashboard-user-options' )
65
+ )
66
  );
 
 
67
  }
68
 
69
  /**
70
+ * Render dashboard widget.
71
+ *
72
+ * @return mixed
73
  */
74
+ public function dashboard_widget() {
75
+ // get user ID
76
+ $user_id = get_current_user_id();
77
+
78
+ // get user options
79
+ $user_options = get_user_meta( $user_id, 'pvc_dashboard', true );
80
+
81
+ // empty options?
82
+ if ( ! is_array( $user_options ) || empty( $user_options ) )
83
+ $user_options = array();
84
+
85
+ // sanitize options
86
+ $user_options = map_deep( $user_options, 'sanitize_text_field' );
87
+ $menu_items = ! empty( $user_options['menu_items'] ) ? $user_options['menu_items'] : array();
88
+
89
+ $months_html = $this->generate_months( current_time( 'timestamp', false ) );
90
+ ?>
91
+ <div id="pvc-dashboard-accordion" class="pvc-accordion">
92
+ <div id="pvc-post-views" class="pvc-accordion-item<?php echo in_array( 'post-views', $menu_items ) ? ' pvc-collapsed' : ''; ?>">
93
+ <div class="pvc-accordion-header">
94
+ <div class="pvc-accordion-toggle"><span class="pvc-accordion-title"><?php _e( 'Post Views', 'post-views-counter' ); ?></span><span class="pvc-tooltip" aria-label="<?php _e( 'Displays the chart of most viewed post types for a selected time period.', 'post-views-counter' ); ?>" data-microtip-position="top" data-microtip-size="large" role="tooltip"><span class="pvc-tooltip-icon"></span></span></div>
95
+ <?php /*
96
+ <div class="pvc-accordion-actions">
97
+ <a href="javascript:void(0);" class="pvc-accordion-action dashicons dashicons-admin-generic"></a>
98
+ </div>
99
+ */ ?>
100
+ </div>
101
+ <div class="pvc-accordion-content">
102
+ <div class="pvc-dashboard-container loading">
103
+
104
+ <div id="pvc-chart-container" class="pvc-data-container">
105
+ <canvas id="pvc-chart" height="175"></canvas>
106
+ <span class="spinner"></span>
107
+ </div>
108
+
109
+ <div class="pvc-months">
110
+ <?php echo $months_html; ?>
111
+ </div>
112
+
113
+ </div>
114
+ </div>
115
+ </div>
116
+ <div id="pvc-most-viewed" class="pvc-accordion-item<?php echo in_array( 'most-viewed', $menu_items ) ? ' pvc-collapsed' : ''; ?>">
117
+ <div class="pvc-accordion-header">
118
+ <div class="pvc-accordion-toggle"><span class="pvc-accordion-title"><?php _e( 'Top Posts', 'post-views-counter' ); ?></span><span class="pvc-tooltip" aria-label="<?php _e( 'Displays the list of most viewed posts and pages on your website.', 'post-views-counter' ); ?>" data-microtip-position="top" data-microtip-size="large" role="tooltip"><span class="pvc-tooltip-icon"></span></span></div>
119
+ </div>
120
+ <div class="pvc-accordion-content">
121
+ <div class="pvc-dashboard-container loading">
122
+
123
+ <div class="pvc-data-container">
124
+ <div id="pvc-viewed" class="pvc-table-responsive"></div>
125
+ <span class="spinner"></span>
126
+ </div>
127
+
128
+ <div class="pvc-months">
129
+ <?php echo $months_html; ?>
130
+ </div>
131
+
132
+ </div>
133
+ </div>
134
+ </div>
135
+ </div>
136
+ <?php
137
  }
138
 
139
  /**
142
  * @global $_wp_admin_css_colors
143
  * @return void
144
  */
145
+ public function dashboard_get_chart() {
146
  if ( ! apply_filters( 'pvc_user_can_see_stats', current_user_can( 'publish_posts' ) ) )
147
  wp_die( _( 'You do not have permission to access this page.', 'post-views-counter' ) );
148
 
149
+ if ( ! check_ajax_referer( 'pvc-dashboard-chart', 'nonce' ) )
150
  wp_die( __( 'You do not have permission to access this page.', 'post-views-counter' ) );
151
 
152
  // get period
284
 
285
  case 'this_month':
286
  default:
287
+ $user_options = $this->get_dashboard_user_options( get_current_user_id(), 'post_types' );
288
 
289
  if ( $period !== 'this_month' ) {
290
  $date = explode( '|', $period, 2 );
315
 
316
  $data['data']['datasets'][0]['label'] = __( 'Total Views', 'post-views-counter' );
317
  $data['data']['datasets'][0]['post_type'] = '_pvc_total_views';
318
+ $data['data']['datasets'][0]['hidden'] = in_array( '_pvc_total_views', $user_options, true );
319
 
320
  // reindex post types
321
  $post_types = array_combine( range( 1, count( $post_types ) ), array_values( $post_types ) );
327
 
328
  $data['data']['datasets'][$id]['label'] = $post_type_obj->labels->name;
329
  $data['data']['datasets'][$id]['post_type'] = $post_type_obj->name;
330
+ $data['data']['datasets'][$id]['hidden'] = in_array( $post_type_obj->name, $user_options, true );
331
  $data['data']['datasets'][$id]['data'] = array();
332
 
333
  // get month views
375
 
376
  exit;
377
  }
378
+
379
+ /**
380
+ * Dashboard widget chart data function.
381
+ *
382
+ * @global $_wp_admin_css_colors
383
+ * @return void
384
+ */
385
+ public function dashboard_get_most_viewed() {
386
+ if ( ! apply_filters( 'pvc_user_can_see_stats', current_user_can( 'publish_posts' ) ) )
387
+ wp_die( _( 'You do not have permission to access this page.', 'post-views-counter' ) );
388
 
389
+ if ( ! check_ajax_referer( 'pvc-dashboard-chart', 'nonce' ) )
390
+ wp_die( __( 'You do not have permission to access this page.', 'post-views-counter' ) );
391
+
392
+ // get period
393
+ $period = isset( $_POST['period'] ) ? esc_attr( $_POST['period'] ) : 'this_month';
394
+
395
+ // get post types
396
+ $post_types = Post_Views_Counter()->options['general']['post_types_count'];
397
+
398
+ if ( $period !== 'this_month' ) {
399
+ $date = explode( '|', $period, 2 );
400
+ $months = strtotime( (string) $date[1] . '-' . (string) $date[0] . '-13' );
401
+ } else
402
+ $months = current_time( 'timestamp', false );
403
+
404
+ // get date chunks
405
+ $date = explode( ' ', date( "m Y t F", $months ) );
406
+
407
+ // get stats
408
+ $query_args = array(
409
+ 'post_type' => $post_types,
410
+ 'posts_per_page' => 10,
411
+ 'paged' => false,
412
+ 'suppress_filters' => false,
413
+ 'no_found_rows' => true,
414
+ 'views_query' => array(
415
+ 'year' => $date[1],
416
+ 'month' => $date[0],
417
+ )
418
+ );
419
+
420
+ $posts = pvc_get_most_viewed_posts( $query_args );
421
+
422
+ $data = array(
423
+ 'months' => $this->generate_months( $months ),
424
+ 'html' => '',
425
+ );
426
+
427
+ $html = '<table id="pvc-most-viewed-table" class="pvc-table pvc-table-hover">';
428
+ $html .= '<thead>';
429
+ $html .= '<tr>';
430
+ $html .= '<th scope="col">#</th>';
431
+ $html .= '<th scope="col">' . __( 'Post', 'post-views-counter' ) . '</th>';
432
+ $html .= '<th scope="col">' . __( 'Post Views', 'post-views-counter' ) . '</th>';
433
+ $html .= '</tr>';
434
+ $html .= '</thead>';
435
+ $html .= '<tbody>';
436
+
437
+ if ( $posts ) {
438
+ foreach ( $posts as $index => $post ) {
439
+ setup_postdata( $post );
440
+
441
+ $html .= '<tr>';
442
+ $html .= '<th scope="col">' . ( $index + 1 ) . '</th>';
443
+
444
+ if ( current_user_can( 'edit_post', $post->ID ) ) {
445
+ $html .= '<td><a href="' . get_edit_post_link( $post->ID ) . '">' . get_the_title( $post ) . '</a></td>';
446
+ } else {
447
+ $html .= '<td>' . get_the_title( $post ). '</td>';
448
+ }
449
+
450
+ $html .= '<td>' . number_format_i18n( $post->post_views ) . '</td>';
451
+ $html .= '</tr>';
452
+ }
453
+ } else {
454
+ $html .= '<tr class="no-posts">';
455
+ $html .= '<td colspan="3">' . __( 'No most viewed posts found', 'post-views-counter' ) . '</td>';
456
+ $html .= '</tr>';
457
+ }
458
+
459
+ $html .= '</tbody>';
460
+ $html .='</table>';
461
+
462
+ $data['html'] = $html;
463
+
464
+ echo json_encode( $data );
465
+ exit;
466
+ }
467
+
468
  /**
469
+ * Generate months.
470
  *
471
+ * @param string $timestamp
472
+ * @return string
473
  */
474
+ public function generate_months( $timestamp ) {
475
+ $dates = array(
476
+ explode( ' ', date( "m F Y", strtotime( "-1 months", $timestamp ) ) ),
477
+ explode( ' ', date( "m F Y", $timestamp ) ),
478
+ explode( ' ', date( "m F Y", strtotime( "+1 months", $timestamp ) ) )
479
+ );
480
+
481
+ $current = date( "Ym", current_time( 'timestamp', false ) );
482
 
483
+ if ( (int) $current <= (int) ( $dates[1][2] . $dates[1][0] ) )
484
+ $next = '<span class="next">' . $dates[2][1] . ' ' . $dates[2][2] . ' ›</span>';
485
+ else
486
+ $next = '<a class="next" href="#" data-date="' . ( $dates[2][0] . '|' . $dates[2][2] ) . '">' . $dates[2][1] . ' ' . $dates[2][2] . ' ›</a>';
487
 
488
+ $dates = array(
489
+ 'prev' => '<a class="prev" href="#" data-date="' . ( $dates[0][0] . '|' . $dates[0][2] ) . '">‹ ' . $dates[0][1] . ' ' . $dates[0][2] . '</a>',
490
+ 'current' => '<span class="current">' . $dates[1][1] . ' ' . $dates[1][2] . '</span>',
491
+ 'next' => $next
492
+ );
493
 
494
+ return $dates['prev'] . $dates['current'] . $dates['next'];
495
  }
496
 
497
  /**
498
+ * Dashboard widget chart user post types.
499
  *
500
+ * @return void
501
  */
502
+ public function update_dashboard_user_options() {
503
+ if ( ! check_ajax_referer( 'pvc-dashboard-user-options', 'nonce' ) )
504
+ wp_die( __( 'You do not have permission to access this page.', 'post-views-counter' ) );
505
 
506
+ // get allowed post types
507
+ $allowed_post_types = Post_Views_Counter()->options['general']['post_types_count'];
 
508
 
509
+ // simulate total views as post type
510
+ $allowed_post_types[] = '_pvc_total_views';
511
+
512
+ // get allowed menu items
513
+ $allowed_menu_items = array( 'post-views', 'most-viewed' );
514
 
515
+ // valid data?
516
+ if ( isset( $_POST['nonce'], $_POST['options'] ) && ! empty( $_POST['options'] ) ) {
517
+ // get options
518
+ $update = map_deep( $_POST['options'], 'sanitize_text_field' );
519
 
520
+ // get user ID
521
+ $user_id = get_current_user_id();
522
 
523
+ // get user dashboard data
524
+ $user_options = get_user_meta( $user_id, 'pvc_dashboard', true );
525
+
526
+ // empty userdata?
527
+ if ( ! is_array( $user_options ) || empty( $user_options ) )
528
+ $user_options = array();
529
+
530
+ // empty post types?
531
+ if ( ! array_key_exists( 'post_types', $user_options ) || ! is_array( $user_options['post_types'] ) )
532
+ $user_options['post_types'] = array();
533
+
534
+ // hide post type?
535
+ if ( ! empty( $update['post_type'] ) && in_array( $update['post_type'], $allowed_post_types, true ) ) {
536
+ if ( isset( $update['hidden'] ) && $update['hidden'] === 'true' ) {
537
+ if ( ! in_array( $update['post_type'], $user_options['post_types'], true ) )
538
+ $user_options['post_types'][] = $update['post_type'];
539
+ } else {
540
+ if ( ( $key = array_search( $update['post_type'], $user_options['post_types'] ) ) !== false )
541
+ unset( $user_options['post_types'][$key] );
542
+ }
543
+ }
544
+
545
+ // hide menu item?
546
+ $user_options['menu_items'] = array();
547
+
548
+ if ( ! empty( $update['menu_items'] ) && is_array( $update['menu_items'] ) ) {
549
+ $update['menu_items'] = map_deep( $update['menu_items'], 'sanitize_text_field' );
550
+
551
+ foreach ( $update['menu_items'] as $menu_item => $hidden ) {
552
+ if ( in_array( $menu_item, $allowed_menu_items ) && $hidden === 'true' )
553
+ $user_options['menu_items'][] = $menu_item;
554
+ }
555
+ }
556
+
557
+ // update userdata
558
+ update_user_meta( $user_id, 'pvc_dashboard', $user_options );
559
+ }
560
+
561
+ exit;
562
+ }
563
+
564
+ /**
565
+ * Get user dashboard data.
566
+ *
567
+ * @param string $data_type
568
+ * @return array
569
+ */
570
+ public function get_dashboard_user_options( $user_id, $data_type ) {
571
+ $user_options = get_user_meta( $user_id, 'pvc_dashboard', true );
572
+
573
+ if ( ! is_array( $user_options ) || empty( $user_options ) )
574
+ $user_options = array();
575
+
576
+ if ( ! array_key_exists( $data_type, $user_options ) || ! is_array( $user_options[$data_type] ) )
577
+ $user_options[$data_type] = array();
578
+
579
+ return $user_options[$data_type];
580
  }
581
 
582
  /**
includes/settings.php CHANGED
@@ -1,816 +1,816 @@
1
- <?php
2
- // exit if accessed directly
3
- if ( ! defined( 'ABSPATH' ) )
4
- exit;
5
-
6
- /**
7
- * Post_Views_Counter_Settings class.
8
- *
9
- * @class Post_Views_Counter_Settings
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( 'admin_init', array( $this, 'register_settings' ) );
27
- add_action( 'admin_menu', array( $this, 'admin_menu_options' ) );
28
- add_action( 'after_setup_theme', array( $this, 'load_defaults' ) );
29
- add_action( 'wp_loaded', array( $this, 'load_post_types' ) );
30
- }
31
-
32
- /**
33
- * Load default settings.
34
- */
35
- public function load_defaults() {
36
- if ( ! is_admin() )
37
- return;
38
-
39
- $this->modes = array(
40
- 'php' => __( 'PHP', 'post-views-counter' ),
41
- 'js' => __( 'JavaScript', 'post-views-counter' ),
42
- 'ajax' => __( 'Fast AJAX', 'post-views-counter' )
43
- );
44
-
45
- if ( function_exists( 'register_rest_route' ) )
46
- $this->modes['rest_api'] = __( 'REST API', 'post-views-counter' );
47
-
48
- $this->time_types = array(
49
- 'minutes' => __( 'minutes', 'post-views-counter' ),
50
- 'hours' => __( 'hours', 'post-views-counter' ),
51
- 'days' => __( 'days', 'post-views-counter' ),
52
- 'weeks' => __( 'weeks', 'post-views-counter' ),
53
- 'months' => __( 'months', 'post-views-counter' ),
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
- array(
95
- 'home' => __( 'Home', 'post-views-counter' ),
96
- 'archive' => __( 'Archives', 'post-views-counter' ),
97
- 'singular' => __( 'Single pages', 'post-views-counter' ),
98
- 'search' => __( 'Search results', 'post-views-counter' ),
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 = array();
111
-
112
- // built in public post types
113
- foreach ( get_post_types( array( '_builtin' => true, 'public' => true ), 'objects', 'and' ) as $key => $post_type ) {
114
- $post_types[$key] = $post_type->labels->name;
115
- }
116
-
117
- // public custom post types
118
- foreach ( get_post_types( array( '_builtin' => false, 'public' => true ), 'objects', 'and' ) as $key => $post_type ) {
119
- $post_types[$key] = $post_type->labels->name;
120
- }
121
-
122
- // remove bbPress replies
123
- if ( class_exists( 'bbPress' ) && isset( $post_types['reply'] ) )
124
- unset( $post_types['reply'] );
125
-
126
- $post_types = apply_filters( 'pvc_available_post_types', $post_types );
127
-
128
- // sort post types alphabetically with their keys
129
- asort( $post_types, SORT_STRING );
130
-
131
- $this->post_types = $post_types;
132
- }
133
-
134
- /**
135
- * Get all user roles.
136
- *
137
- * @global object $wp_roles
138
- * @return array
139
- */
140
- public function get_user_roles() {
141
- global $wp_roles;
142
-
143
- $roles = array();
144
-
145
- foreach ( apply_filters( 'editable_roles', $wp_roles->roles ) as $role => $details ) {
146
- $roles[$role] = translate_user_role( $details['name'] );
147
- }
148
-
149
- asort( $roles, SORT_STRING );
150
-
151
- return $roles;
152
- }
153
-
154
- /**
155
- * Add options page.
156
- *
157
- * @return void
158
- */
159
- public function admin_menu_options() {
160
- add_options_page( __( 'Post Views Counter', 'post-views-counter' ), __( 'Post Views Counter', 'post-views-counter' ), 'manage_options', 'post-views-counter', array( $this, 'options_page' ) );
161
- }
162
-
163
- /**
164
- * Options page callback.
165
- *
166
- * @return void
167
- */
168
- public function options_page() {
169
- $tab_key = (isset( $_GET['tab'] ) ? esc_attr( $_GET['tab'] ) : 'general');
170
-
171
- echo '
172
- <div class="wrap">
173
- <h2>' . __( 'Post Views Counter', 'post-views-counter' ) . '</h2>
174
- <h2 class="nav-tab-wrapper">';
175
-
176
- foreach ( $this->tabs as $key => $name ) {
177
- echo '
178
- <a class="nav-tab ' . ($tab_key == $key ? 'nav-tab-active' : '') . '" href="' . esc_url( admin_url( 'options-general.php?page=post-views-counter&tab=' . $key ) ) . '">' . $name['name'] . '</a>';
179
- }
180
-
181
- echo '
182
- </h2>
183
- <div class="post-views-counter-settings">
184
- <div class="df-credits">
185
- <h3 class="hndle">' . __( 'Post Views Counter', 'post-views-counter' ) . ' ' . Post_Views_Counter()->defaults['version'] . '</h3>
186
- <div class="inside">
187
- <h4 class="inner">' . __( 'Need support?', 'post-views-counter' ) . '</h4>
188
- <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>', 'post-views-counter' ), 'https://www.dfactory.eu/docs/post-views-counter/?utm_source=post-views-counter-settings&utm_medium=link&utm_campaign=docs', 'https://www.dfactory.eu/support/?utm_source=post-views-counter-settings&utm_medium=link&utm_campaign=support' ) . '</p>
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
- * Register settings callback.
224
- */
225
- public function register_settings() {
226
- // general options
227
- register_setting( 'post_views_counter_settings_general', 'post_views_counter_settings_general', array( $this, 'validate_settings' ) );
228
- add_settings_section( 'post_views_counter_settings_general', __( 'General settings', 'post-views-counter' ), '', 'post_views_counter_settings_general' );
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
- }
253
-
254
- /**
255
- * Post views label option.
256
- */
257
- public function post_views_label() {
258
- echo '
259
- <div id="pvc_post_views_label">
260
- <fieldset>
261
- <input type="text" class="large-text" name="post_views_counter_settings_display[label]" value="' . esc_attr( Post_Views_Counter()->options['display']['label'] ) . '" />
262
- <p class="description">' . __( 'Enter the label for the post views counter field.', 'post-views-counter' ) . '</p>
263
- </fieldset>
264
- </div>';
265
- }
266
-
267
- /**
268
- * Post types to count option.
269
- */
270
- public function post_types_count() {
271
- echo '
272
- <div id="pvc_post_types_count">';
273
-
274
- foreach ( $this->post_types as $post_type => $post_type_name ) {
275
- echo '
276
- <label class="cb-checkbox"><input id="pvc_post_types_count-' . esc_attr( $post_type ) . '" type="checkbox" name="post_views_counter_settings_general[post_types_count][' . esc_attr( $post_type ) . ']" value="1" ' . checked( in_array( $post_type, Post_Views_Counter()->options['general']['post_types_count'], true ), true, false ) . ' />' . esc_html( $post_type_name ) . ' </label>';
277
- }
278
-
279
- echo '
280
- <p class="description">' . __( 'Select post types for which post views will be counted.', 'post-views-counter' ) . '</p>
281
- </div>';
282
- }
283
-
284
- /**
285
- * Post types to display option.
286
- */
287
- public function post_types_display() {
288
- echo '
289
- <div id="pvc_post_types_display">';
290
-
291
- foreach ( $this->post_types as $post_type => $post_type_name ) {
292
- echo '
293
- <label class="cb-checkbox"><input id="pvc_post_types_display-' . esc_attr( $post_type ) . '" type="checkbox" name="post_views_counter_settings_display[post_types_display][' . esc_attr( $post_type ) . ']" value="1" ' . checked( in_array( $post_type, Post_Views_Counter()->options['display']['post_types_display'], true ), true, false ) . ' />' . esc_html( $post_type_name ) . '</label>';
294
- }
295
-
296
- echo '
297
- <p class="description">' . __( 'Select post types for which the views count will be displayed.', 'post-views-counter' ) . '</p>
298
- </div>';
299
- }
300
-
301
- /**
302
- * Counter mode option.
303
- */
304
- public function counter_mode() {
305
- echo '
306
- <div id="pvc_counter_mode">';
307
-
308
- foreach ( $this->modes as $key => $value ) {
309
- $key = esc_attr( $key );
310
-
311
- echo '
312
- <label class="cb-radio"><input type="radio" name="post_views_counter_settings_general[counter_mode]" value="' . $key . '" ' . checked( $key, Post_Views_Counter()->options['general']['counter_mode'], false ) . ' />' . esc_html( $value ) . '</label>';
313
- }
314
-
315
- echo '
316
- <p class="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' ) . '</p>
317
- </div>';
318
- }
319
-
320
- /**
321
- * Post views column option.
322
- */
323
- public function post_views_column() {
324
- echo '
325
- <div id="pvc_post_views_column">
326
- <label class="cb-checkbox"><input id="pvc-post-views-column-enable" type="checkbox" name="post_views_counter_settings_general[post_views_column]" value="1" ' . checked( true, Post_Views_Counter()->options['general']['post_views_column'], false ) . ' />' . __( 'Enable to display post views count column for each of the selected post types.', 'post-views-counter' ) . '</label>
327
- </div>';
328
- }
329
-
330
- /**
331
- * Time between counts option.
332
- */
333
- public function time_between_counts() {
334
- echo '
335
- <div id="pvc_time_between_counts">
336
- <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'] ) . '" />
337
- <select class="pvc-chosen-short" name="post_views_counter_settings_general[time_between_counts][type]">';
338
-
339
- foreach ( $this->time_types as $type => $type_name ) {
340
- echo '
341
- <option value="' . esc_attr( $type ) . '" ' . selected( $type, Post_Views_Counter()->options['general']['time_between_counts']['type'], false ) . '>' . esc_html( $type_name ) . '</option>';
342
- }
343
-
344
- echo '
345
- </select>
346
- <p class="description">' . __( 'Enter the time between single user visit count.', 'post-views-counter' ) . '</p>
347
- </div>';
348
- }
349
-
350
- /**
351
- * Reset counts option.
352
- */
353
- public function reset_counts() {
354
- echo '
355
- <div id="pvc_reset_counts">
356
- <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'] ) . '" />
357
- <select class="pvc-chosen-short" name="post_views_counter_settings_general[reset_counts][type]">';
358
-
359
- foreach ( array_slice( $this->time_types, 2, null, true ) as $type => $type_name ) {
360
- echo '
361
- <option value="' . esc_attr( $type ) . '" ' . selected( $type, Post_Views_Counter()->options['general']['reset_counts']['type'], false ) . '>' . esc_html( $type_name ) . '</option>';
362
- }
363
-
364
- echo '
365
- </select>
366
- <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>
367
- </div>';
368
- }
369
-
370
- /**
371
- * Flush interval option.
372
- */
373
- public function flush_interval() {
374
- echo '
375
- <div id="pvc_flush_interval">
376
- <input size="4" type="text" name="post_views_counter_settings_general[flush_interval][number]" value="' . esc_attr( Post_Views_Counter()->options['general']['flush_interval']['number'] ) . '" />
377
- <select class="pvc-chosen-short" name="post_views_counter_settings_general[flush_interval][type]">';
378
-
379
- foreach ( $this->time_types as $type => $type_name ) {
380
- echo '
381
- <option value="' . esc_attr( $type ) . '" ' . selected( $type, Post_Views_Counter()->options['general']['flush_interval']['type'], false ) . '>' . esc_html( $type_name ) . '</option>';
382
- }
383
-
384
- echo '
385
- </select>
386
- <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>
387
- </div>';
388
- }
389
-
390
- /**
391
- * Exlude user groups option.
392
- */
393
- public function exclude() {
394
- echo '
395
- <div id="pvc_exclude">
396
- <fieldset>';
397
-
398
- foreach ( $this->groups as $type => $type_name ) {
399
- echo '
400
- <label class="cb-checkbox"><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>';
401
- }
402
-
403
- echo '
404
- <p class="description">' . __( 'Use it to hide the post views counter from selected type of visitors.', 'post-views-counter' ) . '</p>
405
- <div class="pvc_user_roles"' . (in_array( 'roles', Post_Views_Counter()->options['general']['exclude']['groups'], true ) ? '' : ' style="display: none;"') . '>';
406
-
407
- foreach ( $this->user_roles as $role => $role_name ) {
408
- echo '
409
- <label class="cb-checkbox"><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>';
410
- }
411
-
412
- echo ' <p class="description">' . __( 'Use it to hide the post views counter from selected user roles.', 'post-views-counter' ) . '</p>
413
- </div>
414
- </fieldset>
415
- </div>';
416
- }
417
-
418
- /**
419
- * Exclude IPs option.
420
- */
421
- public function exclude_ips() {
422
- // lovely php 5.2 limitations
423
- $ips = Post_Views_Counter()->options['general']['exclude_ips'];
424
-
425
- echo '
426
- <div id="pvc_exclude_ips">';
427
-
428
- if ( ! empty( $ips ) ) {
429
- foreach ( $ips as $key => $ip ) {
430
- echo '
431
- <div class="ip-box">
432
- <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>
433
- </div>';
434
- }
435
- } else {
436
- echo '
437
- <div class="ip-box">
438
- <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>
439
- </div>';
440
- }
441
-
442
- echo '
443
- <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>
444
- <p class="description">' . __( 'Enter the IP addresses to be excluded from post views count.', 'post-views-counter' ) . '</p>
445
- </div>';
446
- }
447
-
448
- /**
449
- * Strict counts option.
450
- */
451
- public function strict_counts() {
452
- echo '
453
- <div id="pvc_strict_counts">
454
- <label class="cb-checkbox"><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>
455
- </div>';
456
- }
457
-
458
- /**
459
- * WP-PostViews import option.
460
- */
461
- public function wp_postviews() {
462
- echo '
463
- <div id="pvc_wp_postviews">
464
- <fieldset>
465
- <input type="submit" class="button button-secondary" name="post_views_counter_import_wp_postviews" value="' . __( 'Import views', 'post-views-counter' ) . '"/> <label class="cb-checkbox"><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>
466
- <p class="description">' . __( 'Import post views data from WP-PostViews plugin.', 'post-views-counter' ) . '</p>
467
- <input type="submit" class="button button-secondary" name="post_views_counter_reset_views" value="' . __( 'Delete views', 'post-views-counter' ) . '"/>
468
- <p class="description">' . __( 'Delete ALL the existing post views data.', 'post-views-counter' ) . '</p>
469
- </fieldset>
470
- </div>';
471
- }
472
-
473
- /**
474
- * Limit views edit to admins.
475
- */
476
- public function restrict_edit_views() {
477
- echo '
478
- <div id="pvc_restrict_edit_views">
479
- <label class="cb-checkbox"><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>
480
- </div>';
481
- }
482
-
483
- /**
484
- * Plugin deactivation option.
485
- */
486
- public function deactivation_delete() {
487
- echo '
488
- <div id="pvc_deactivation_delete">
489
- <label class="cb-checkbox"><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>
490
- </div>';
491
- }
492
-
493
- /**
494
- * Visibility option.
495
- */
496
- public function page_types_display() {
497
- echo '
498
- <div id="pvc_post_types_display">';
499
-
500
- foreach ( $this->page_types as $key => $label ) {
501
- echo '
502
- <label class="cb-checkbox"><input id="pvc_page_types_display-' . esc_attr( $key ) . '" type="checkbox" name="post_views_counter_settings_display[page_types_display][' . esc_attr( $key ) . ']" value="1" ' . checked( in_array( $key, Post_Views_Counter()->options['display']['page_types_display'], true ), true, false ) . ' />' . esc_html( $label ) . '</label>';
503
- }
504
-
505
- echo '
506
- <p class="description">' . __( 'Select page types where the views count will be displayed.', 'post-views-counter' ) . '</p>
507
- </div>';
508
- }
509
-
510
- /**
511
- * Counter position option.
512
- */
513
- public function position() {
514
- echo '
515
- <div id="pvc_position">
516
- <select class="pvc-chosen-short" name="post_views_counter_settings_display[position]">';
517
-
518
- foreach ( $this->positions as $position => $position_name ) {
519
- echo '
520
- <option value="' . esc_attr( $position ) . '" ' . selected( $position, Post_Views_Counter()->options['display']['position'], false ) . '>' . esc_html( $position_name ) . '</option>';
521
- }
522
-
523
- echo '
524
- </select>
525
- <p class="description">' . __( 'Select where would you like to display the post views counter. Use [post-views] shortcode for manual display.', 'post-views-counter' ) . '</p>
526
- </div>';
527
- }
528
-
529
- /**
530
- * Counter style option.
531
- */
532
- public function display_style() {
533
- echo '
534
- <div id="pvc_display_style">';
535
-
536
- foreach ( $this->display_styles as $display => $style ) {
537
- $display = esc_attr( $display );
538
-
539
- echo '
540
- <label class="cb-checkbox"><input type="checkbox" name="post_views_counter_settings_display[display_style][' . $display . ']" value="1" ' . checked( true, Post_Views_Counter()->options['display']['display_style'][$display], false ) . ' />' . esc_html( $style ) . '</label>';
541
- }
542
-
543
- echo '
544
- <p class="description">' . __( 'Choose how to display the post views counter.', 'post-views-counter' ) . '</p>
545
- </div>';
546
- }
547
-
548
- /**
549
- * Counter icon class option.
550
- */
551
- public function icon_class() {
552
- echo '
553
- <div id="pvc_icon_class">
554
- <input type="text" name="post_views_counter_settings_display[icon_class]" class="large-text" value="' . esc_attr( Post_Views_Counter()->options['display']['icon_class'] ) . '" />
555
- <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>
556
- </div>';
557
- }
558
-
559
- /**
560
- * Restrict display option.
561
- */
562
- public function restrict_display() {
563
- echo '
564
- <div id="pvc_restrict_display">
565
- <fieldset>';
566
-
567
- foreach ( $this->groups as $type => $type_name ) {
568
-
569
- if ( $type === 'robots' )
570
- continue;
571
-
572
- echo '
573
- <label class="cb-checkbox"><input id="pvc_restrict_display-' . $type . '" type="checkbox" name="post_views_counter_settings_display[restrict_display][groups][' . esc_html( $type ) . ']" value="1" ' . checked( in_array( $type, Post_Views_Counter()->options['display']['restrict_display']['groups'], true ), true, false ) . ' />' . esc_html( $type_name ) . '</label>';
574
- }
575
-
576
- echo '
577
- <p class="description">' . __( 'Use it to hide the post views counter from selected type of visitors.', 'post-views-counter' ) . '</p>
578
- <div class="pvc_user_roles"' . (in_array( 'roles', Post_Views_Counter()->options['display']['restrict_display']['groups'], true ) ? '' : ' style="display: none;"') . '>';
579
-
580
- foreach ( $this->user_roles as $role => $role_name ) {
581
- echo '
582
- <label class="cb-checkbox"><input type="checkbox" name="post_views_counter_settings_display[restrict_display][roles][' . $role . ']" value="1" ' . checked( in_array( $role, Post_Views_Counter()->options['display']['restrict_display']['roles'], true ), true, false ) . ' />' . esc_html( $role_name ) . '</label>';
583
- }
584
-
585
- echo '
586
- <p class="description">' . __( 'Use it to hide the post views counter from selected user roles.', 'post-views-counter' ) . '</p>
587
- </div>
588
- </fieldset>
589
- </div>';
590
- }
591
-
592
- /**
593
- * Validate general settings.
594
- */
595
- public function validate_settings( $input ) {
596
- // get main instance
597
- $pvc = Post_Views_Counter();
598
-
599
- if ( isset( $_POST['post_views_counter_import_wp_postviews'] ) ) {
600
- global $wpdb;
601
-
602
- $meta_key = esc_attr( apply_filters( 'pvc_import_meta_key', 'views' ) );
603
-
604
- $views = $wpdb->get_results( "SELECT post_id, meta_value FROM " . $wpdb->postmeta . " WHERE meta_key = '" . $meta_key . "'", ARRAY_A, 0 );
605
-
606
- if ( ! empty( $views ) ) {
607
- $input = $pvc->defaults['general'];
608
- $input['wp_postviews_import'] = true;
609
-
610
- $sql = array();
611
-
612
- foreach ( $views as $view ) {
613
- $sql[] = "(" . $view['post_id'] . ", 4, 'total', " . $view['meta_value'] . ")";
614
- }
615
-
616
- $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)" );
617
-
618
- add_settings_error( 'wp_postviews_import', 'wp_postviews_import', __( 'Post views data imported succesfully.', 'post-views-counter' ), 'updated' );
619
- } else {
620
- add_settings_error( 'wp_postviews_import', 'wp_postviews_import', __( 'There was no post views data to import.', 'post-views-counter' ), 'updated' );
621
- }
622
- } elseif ( isset( $_POST['post_views_counter_reset_views'] ) ) {
623
- global $wpdb;
624
-
625
- if ( $wpdb->query( 'TRUNCATE TABLE ' . $wpdb->prefix . 'post_views' ) )
626
- add_settings_error( 'reset_post_views', 'reset_post_views', __( 'All existing data deleted succesfully.', 'post-views-counter' ), 'updated' );
627
- else
628
- add_settings_error( 'reset_post_views', 'reset_post_views', __( 'Error occurred. All existing data were not deleted.', 'post-views-counter' ), 'error' );
629
- } elseif ( isset( $_POST['save_pvc_general'] ) ) {
630
- // post types count
631
- if ( isset( $input['post_types_count'] ) ) {
632
- $post_types = array();
633
-
634
- foreach ( $input['post_types_count'] as $post_type => $set ) {
635
- if ( isset( $this->post_types[$post_type] ) )
636
- $post_types[] = $post_type;
637
- }
638
-
639
- $input['post_types_count'] = array_unique( $post_types );
640
- } else
641
- $input['post_types_count'] = array();
642
-
643
- // counter mode
644
- $input['counter_mode'] = isset( $input['counter_mode'], $this->modes[$input['counter_mode']] ) ? $input['counter_mode'] : $pvc->defaults['general']['counter_mode'];
645
-
646
- // post views column
647
- $input['post_views_column'] = isset( $input['post_views_column'] );
648
-
649
- // time between counts
650
- $input['time_between_counts']['number'] = (int) ( isset( $input['time_between_counts']['number'] ) ? $input['time_between_counts']['number'] : $pvc->defaults['general']['time_between_counts']['number'] );
651
- $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'];
652
-
653
- // flush interval
654
- $input['flush_interval']['number'] = (int) ( isset( $input['flush_interval']['number'] ) ? $input['flush_interval']['number'] : $pvc->defaults['general']['flush_interval']['number'] );
655
- $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'];
656
-
657
- // Since the settings are about to be saved and cache flush interval could've changed,
658
- // we want to make sure that any changes done on the settings page are in effect immediately
659
- // (instead of having to wait for the previous schedule to occur).
660
- // We achieve that by making sure to clear any previous cache flush schedules and
661
- // schedule the new one if the specified interval is > 0
662
- $pvc->remove_cache_flush();
663
-
664
- if ( $input['flush_interval']['number'] > 0 ) {
665
- $pvc->schedule_cache_flush();
666
- }
667
-
668
- // reset counts
669
- $input['reset_counts']['number'] = (int) ( isset( $input['reset_counts']['number'] ) ? $input['reset_counts']['number'] : $pvc->defaults['general']['reset_counts']['number'] );
670
- $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'];
671
-
672
- // run cron on next visit?
673
- $input['cron_run'] = ($input['reset_counts']['number'] > 0 ? true : false);
674
- $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'] ) ? true : false);
675
-
676
- // exclude
677
- if ( isset( $input['exclude']['groups'] ) ) {
678
- $groups = array();
679
-
680
- foreach ( $input['exclude']['groups'] as $group => $set ) {
681
- if ( isset( $this->groups[$group] ) )
682
- $groups[] = $group;
683
- }
684
-
685
- $input['exclude']['groups'] = array_unique( $groups );
686
- } else {
687
- $input['exclude']['groups'] = array();
688
- }
689
-
690
- if ( in_array( 'roles', $input['exclude']['groups'], true ) && isset( $input['exclude']['roles'] ) ) {
691
- $roles = array();
692
-
693
- foreach ( $input['exclude']['roles'] as $role => $set ) {
694
- if ( isset( $this->user_roles[$role] ) )
695
- $roles[] = $role;
696
- }
697
-
698
- $input['exclude']['roles'] = array_unique( $roles );
699
- } else
700
- $input['exclude']['roles'] = array();
701
-
702
- // exclude ips
703
- if ( isset( $input['exclude_ips'] ) ) {
704
- $ips = array();
705
-
706
- foreach ( $input['exclude_ips'] as $ip ) {
707
- if ( strpos( $ip, '*' ) !== false ) {
708
- $new_ip = str_replace( '*', '0', $ip );
709
-
710
- if ( filter_var( $new_ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4 ) )
711
- $ips[] = $ip;
712
- } elseif ( filter_var( $ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4 ) )
713
- $ips[] = $ip;
714
- }
715
-
716
- $input['exclude_ips'] = array_unique( $ips );
717
- }
718
-
719
- // restrict edit views
720
- $input['restrict_edit_views'] = isset( $input['restrict_edit_views'] );
721
-
722
- // strict counts
723
- $input['strict_counts'] = isset( $input['strict_counts'] );
724
-
725
- // deactivation delete
726
- $input['deactivation_delete'] = isset( $input['deactivation_delete'] );
727
-
728
- $input['update_version'] = $pvc->options['general']['update_version'];
729
- $input['update_notice'] = $pvc->options['general']['update_notice'];
730
- } elseif ( isset( $_POST['save_pvc_display'] ) ) {
731
-
732
- // post views label
733
- $input['label'] = isset( $input['label'] ) ? $input['label'] : $pvc->defaults['general']['label'];
734
-
735
- if ( function_exists( 'icl_register_string' ) )
736
- icl_register_string( 'Post Views Counter', 'Post Views Label', $input['label'] );
737
-
738
- // position
739
- $input['position'] = isset( $input['position'], $this->positions[$input['position']] ) ? $input['position'] : $pvc->defaults['general']['position'];
740
-
741
- // display style
742
- $input['display_style']['icon'] = isset( $input['display_style']['icon'] );
743
- $input['display_style']['text'] = isset( $input['display_style']['text'] );
744
-
745
- // link to post
746
- $input['link_to_post'] = isset( $input['link_to_post'] ) ? $input['link_to_post'] : $pvc->defaults['display']['link_to_post'];
747
-
748
- // icon class
749
- $input['icon_class'] = isset( $input['icon_class'] ) ? trim( $input['icon_class'] ) : $pvc->defaults['general']['icon_class'];
750
-
751
- // post types display
752
- if ( isset( $input['post_types_display'] ) ) {
753
- $post_types = array();
754
-
755
- foreach ( $input['post_types_display'] as $post_type => $set ) {
756
- if ( isset( $this->post_types[$post_type] ) )
757
- $post_types[] = $post_type;
758
- }
759
-
760
- $input['post_types_display'] = array_unique( $post_types );
761
- } else
762
- $input['post_types_display'] = array();
763
-
764
- // page types display
765
- if ( isset( $input['page_types_display'] ) ) {
766
- $page_types = array();
767
-
768
- foreach ( $input['page_types_display'] as $page_type => $set ) {
769
- if ( isset( $this->page_types[$page_type] ) )
770
- $page_types[] = $page_type;
771
- }
772
-
773
- $input['page_types_display'] = array_unique( $page_types );
774
- } else
775
- $input['page_types_display'] = array();
776
-
777
- // restrict display
778
- if ( isset( $input['restrict_display']['groups'] ) ) {
779
- $groups = array();
780
-
781
- foreach ( $input['restrict_display']['groups'] as $group => $set ) {
782
- if ( $group === 'robots' )
783
- continue;
784
-
785
- if ( isset( $this->groups[$group] ) )
786
- $groups[] = $group;
787
- }
788
-
789
- $input['restrict_display']['groups'] = array_unique( $groups );
790
- } else
791
- $input['restrict_display']['groups'] = array();
792
-
793
- if ( in_array( 'roles', $input['restrict_display']['groups'], true ) && isset( $input['restrict_display']['roles'] ) ) {
794
- $roles = array();
795
-
796
- foreach ( $input['restrict_display']['roles'] as $role => $set ) {
797
- if ( isset( $this->user_roles[$role] ) )
798
- $roles[] = $role;
799
- }
800
-
801
- $input['restrict_display']['roles'] = array_unique( $roles );
802
- } else
803
- $input['restrict_display']['roles'] = array();
804
- } elseif ( isset( $_POST['reset_pvc_general'] ) ) {
805
- $input = $pvc->defaults['general'];
806
-
807
- add_settings_error( 'reset_general_settings', 'settings_reset', __( 'General settings restored to defaults.', 'post-views-counter' ), 'updated' );
808
- } elseif ( isset( $_POST['reset_pvc_display'] ) ) {
809
- $input = $pvc->defaults['display'];
810
-
811
- add_settings_error( 'reset_general_settings', 'settings_reset', __( 'Display settings restored to defaults.', 'post-views-counter' ), 'updated' );
812
- }
813
-
814
- return $input;
815
- }
816
  }
1
+ <?php
2
+ // exit if accessed directly
3
+ if ( ! defined( 'ABSPATH' ) )
4
+ exit;
5
+
6
+ /**
7
+ * Post_Views_Counter_Settings class.
8
+ *
9
+ * @class Post_Views_Counter_Settings
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( 'admin_init', array( $this, 'register_settings' ) );
27
+ add_action( 'admin_menu', array( $this, 'admin_menu_options' ) );
28
+ add_action( 'after_setup_theme', array( $this, 'load_defaults' ) );
29
+ add_action( 'wp_loaded', array( $this, 'load_post_types' ) );
30
+ }
31
+
32
+ /**
33
+ * Load default settings.
34
+ */
35
+ public function load_defaults() {
36
+ if ( ! is_admin() )
37
+ return;
38
+
39
+ $this->modes = array(
40
+ 'php' => __( 'PHP', 'post-views-counter' ),
41
+ 'js' => __( 'JavaScript', 'post-views-counter' ),
42
+ 'ajax' => __( 'Fast AJAX', 'post-views-counter' )
43
+ );
44
+
45
+ if ( function_exists( 'register_rest_route' ) )
46
+ $this->modes['rest_api'] = __( 'REST API', 'post-views-counter' );
47
+
48
+ $this->time_types = array(
49
+ 'minutes' => __( 'minutes', 'post-views-counter' ),
50
+ 'hours' => __( 'hours', 'post-views-counter' ),
51
+ 'days' => __( 'days', 'post-views-counter' ),
52
+ 'weeks' => __( 'weeks', 'post-views-counter' ),
53
+ 'months' => __( 'months', 'post-views-counter' ),
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
+ array(
95
+ 'home' => __( 'Home', 'post-views-counter' ),
96
+ 'archive' => __( 'Archives', 'post-views-counter' ),
97
+ 'singular' => __( 'Single pages', 'post-views-counter' ),
98
+ 'search' => __( 'Search results', 'post-views-counter' ),
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 = array();
111
+
112
+ // built in public post types
113
+ foreach ( get_post_types( array( '_builtin' => true, 'public' => true ), 'objects', 'and' ) as $key => $post_type ) {
114
+ $post_types[$key] = $post_type->labels->name;
115
+ }
116
+
117
+ // public custom post types
118
+ foreach ( get_post_types( array( '_builtin' => false, 'public' => true ), 'objects', 'and' ) as $key => $post_type ) {
119
+ $post_types[$key] = $post_type->labels->name;
120
+ }
121
+
122
+ // remove bbPress replies
123
+ if ( class_exists( 'bbPress' ) && isset( $post_types['reply'] ) )
124
+ unset( $post_types['reply'] );
125
+
126
+ $post_types = apply_filters( 'pvc_available_post_types', $post_types );
127
+
128
+ // sort post types alphabetically with their keys
129
+ asort( $post_types, SORT_STRING );
130
+
131
+ $this->post_types = $post_types;
132
+ }
133
+
134
+ /**
135
+ * Get all user roles.
136
+ *
137
+ * @global object $wp_roles
138
+ * @return array
139
+ */
140
+ public function get_user_roles() {
141
+ global $wp_roles;
142
+
143
+ $roles = array();
144
+
145
+ foreach ( apply_filters( 'editable_roles', $wp_roles->roles ) as $role => $details ) {
146
+ $roles[$role] = translate_user_role( $details['name'] );
147
+ }
148
+
149
+ asort( $roles, SORT_STRING );
150
+
151
+ return $roles;
152
+ }
153
+
154
+ /**
155
+ * Add options page.
156
+ *
157
+ * @return void
158
+ */
159
+ public function admin_menu_options() {
160
+ add_options_page( __( 'Post Views Counter', 'post-views-counter' ), __( 'Post Views Counter', 'post-views-counter' ), 'manage_options', 'post-views-counter', array( $this, 'options_page' ) );
161
+ }
162
+
163
+ /**
164
+ * Options page callback.
165
+ *
166
+ * @return void
167
+ */
168
+ public function options_page() {
169
+ $tab_key = (isset( $_GET['tab'] ) ? esc_attr( $_GET['tab'] ) : 'general');
170
+
171
+ echo '
172
+ <div class="wrap">
173
+ <h2>' . __( 'Post Views Counter', 'post-views-counter' ) . '</h2>
174
+ <h2 class="nav-tab-wrapper">';
175
+
176
+ foreach ( $this->tabs as $key => $name ) {
177
+ echo '
178
+ <a class="nav-tab ' . ($tab_key == $key ? 'nav-tab-active' : '') . '" href="' . esc_url( admin_url( 'options-general.php?page=post-views-counter&tab=' . $key ) ) . '">' . $name['name'] . '</a>';
179
+ }
180
+
181
+ echo '
182
+ </h2>
183
+ <div class="post-views-counter-settings">
184
+ <div class="df-credits">
185
+ <h3 class="hndle">' . __( 'Post Views Counter', 'post-views-counter' ) . ' ' . Post_Views_Counter()->defaults['version'] . '</h3>
186
+ <div class="inside">
187
+ <h4 class="inner">' . __( 'Need support?', 'post-views-counter' ) . '</h4>
188
+ <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>', 'post-views-counter' ), 'https://www.dfactory.eu/docs/post-views-counter/?utm_source=post-views-counter-settings&utm_medium=link&utm_campaign=docs', 'https://www.dfactory.eu/support/?utm_source=post-views-counter-settings&utm_medium=link&utm_campaign=support' ) . '</p>
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
+ * Register settings callback.
224
+ */
225
+ public function register_settings() {
226
+ // general options
227
+ register_setting( 'post_views_counter_settings_general', 'post_views_counter_settings_general', array( $this, 'validate_settings' ) );
228
+ add_settings_section( 'post_views_counter_settings_general', __( 'General settings', 'post-views-counter' ), '', 'post_views_counter_settings_general' );
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
+ }
253
+
254
+ /**
255
+ * Post views label option.
256
+ */
257
+ public function post_views_label() {
258
+ echo '
259
+ <div id="pvc_post_views_label">
260
+ <fieldset>
261
+ <input type="text" class="large-text" name="post_views_counter_settings_display[label]" value="' . esc_attr( Post_Views_Counter()->options['display']['label'] ) . '" />
262
+ <p class="description">' . __( 'Enter the label for the post views counter field.', 'post-views-counter' ) . '</p>
263
+ </fieldset>
264
+ </div>';
265
+ }
266
+
267
+ /**
268
+ * Post types to count option.
269
+ */
270
+ public function post_types_count() {
271
+ echo '
272
+ <div id="pvc_post_types_count">';
273
+
274
+ foreach ( $this->post_types as $post_type => $post_type_name ) {
275
+ echo '
276
+ <label><input id="pvc_post_types_count-' . esc_attr( $post_type ) . '" type="checkbox" name="post_views_counter_settings_general[post_types_count][' . esc_attr( $post_type ) . ']" value="1" ' . checked( in_array( $post_type, Post_Views_Counter()->options['general']['post_types_count'], true ), true, false ) . ' />' . esc_html( $post_type_name ) . ' </label>';
277
+ }
278
+
279
+ echo '
280
+ <p class="description">' . __( 'Select post types for which post views will be counted.', 'post-views-counter' ) . '</p>
281
+ </div>';
282
+ }
283
+
284
+ /**
285
+ * Post types to display option.
286
+ */
287
+ public function post_types_display() {
288
+ echo '
289
+ <div id="pvc_post_types_display">';
290
+
291
+ foreach ( $this->post_types as $post_type => $post_type_name ) {
292
+ echo '
293
+ <label><input id="pvc_post_types_display-' . esc_attr( $post_type ) . '" type="checkbox" name="post_views_counter_settings_display[post_types_display][' . esc_attr( $post_type ) . ']" value="1" ' . checked( in_array( $post_type, Post_Views_Counter()->options['display']['post_types_display'], true ), true, false ) . ' />' . esc_html( $post_type_name ) . '</label>';
294
+ }
295
+
296
+ echo '
297
+ <p class="description">' . __( 'Select post types for which the views count will be displayed.', 'post-views-counter' ) . '</p>
298
+ </div>';
299
+ }
300
+
301
+ /**
302
+ * Counter mode option.
303
+ */
304
+ public function counter_mode() {
305
+ echo '
306
+ <div id="pvc_counter_mode">';
307
+
308
+ foreach ( $this->modes as $key => $value ) {
309
+ $key = esc_attr( $key );
310
+
311
+ echo '
312
+ <label><input type="radio" name="post_views_counter_settings_general[counter_mode]" value="' . $key . '" ' . checked( $key, Post_Views_Counter()->options['general']['counter_mode'], false ) . ' />' . esc_html( $value ) . '</label>';
313
+ }
314
+
315
+ echo '
316
+ <p class="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' ) . '</p>
317
+ </div>';
318
+ }
319
+
320
+ /**
321
+ * Post views column option.
322
+ */
323
+ public function post_views_column() {
324
+ echo '
325
+ <div id="pvc_post_views_column">
326
+ <label><input id="pvc-post-views-column-enable" type="checkbox" name="post_views_counter_settings_general[post_views_column]" value="1" ' . checked( true, Post_Views_Counter()->options['general']['post_views_column'], false ) . ' />' . __( 'Enable to display post views count column for each of the selected post types.', 'post-views-counter' ) . '</label>
327
+ </div>';
328
+ }
329
+
330
+ /**
331
+ * Time between counts option.
332
+ */
333
+ public function time_between_counts() {
334
+ echo '
335
+ <div id="pvc_time_between_counts">
336
+ <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'] ) . '" />
337
+ <select class="pvc-chosen-short" name="post_views_counter_settings_general[time_between_counts][type]">';
338
+
339
+ foreach ( $this->time_types as $type => $type_name ) {
340
+ echo '
341
+ <option value="' . esc_attr( $type ) . '" ' . selected( $type, Post_Views_Counter()->options['general']['time_between_counts']['type'], false ) . '>' . esc_html( $type_name ) . '</option>';
342
+ }
343
+
344
+ echo '
345
+ </select>
346
+ <p class="description">' . __( 'Enter the time between single user visit count.', 'post-views-counter' ) . '</p>
347
+ </div>';
348
+ }
349
+
350
+ /**
351
+ * Reset counts option.
352
+ */
353
+ public function reset_counts() {
354
+ echo '
355
+ <div id="pvc_reset_counts">
356
+ <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'] ) . '" />
357
+ <select class="pvc-chosen-short" name="post_views_counter_settings_general[reset_counts][type]">';
358
+
359
+ foreach ( array_slice( $this->time_types, 2, null, true ) as $type => $type_name ) {
360
+ echo '
361
+ <option value="' . esc_attr( $type ) . '" ' . selected( $type, Post_Views_Counter()->options['general']['reset_counts']['type'], false ) . '>' . esc_html( $type_name ) . '</option>';
362
+ }
363
+
364
+ echo '
365
+ </select>
366
+ <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>
367
+ </div>';
368
+ }
369
+
370
+ /**
371
+ * Flush interval option.
372
+ */
373
+ public function flush_interval() {
374
+ echo '
375
+ <div id="pvc_flush_interval">
376
+ <input size="4" type="text" name="post_views_counter_settings_general[flush_interval][number]" value="' . esc_attr( Post_Views_Counter()->options['general']['flush_interval']['number'] ) . '" />
377
+ <select class="pvc-chosen-short" name="post_views_counter_settings_general[flush_interval][type]">';
378
+
379
+ foreach ( $this->time_types as $type => $type_name ) {
380
+ echo '
381
+ <option value="' . esc_attr( $type ) . '" ' . selected( $type, Post_Views_Counter()->options['general']['flush_interval']['type'], false ) . '>' . esc_html( $type_name ) . '</option>';
382
+ }
383
+
384
+ echo '
385
+ </select>
386
+ <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>
387
+ </div>';
388
+ }
389
+
390
+ /**
391
+ * Exlude user groups option.
392
+ */
393
+ public function exclude() {
394
+ echo '
395
+ <div id="pvc_exclude">
396
+ <fieldset>';
397
+
398
+ foreach ( $this->groups as $type => $type_name ) {
399
+ echo '
400
+ <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>';
401
+ }
402
+
403
+ echo '
404
+ <p class="description">' . __( 'Use it to hide the post views counter from selected type of visitors.', 'post-views-counter' ) . '</p>
405
+ <div class="pvc_user_roles"' . (in_array( 'roles', Post_Views_Counter()->options['general']['exclude']['groups'], true ) ? '' : ' style="display: none;"') . '>';
406
+
407
+ foreach ( $this->user_roles as $role => $role_name ) {
408
+ echo '
409
+ <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>';
410
+ }
411
+
412
+ echo ' <p class="description">' . __( 'Use it to hide the post views counter from selected user roles.', 'post-views-counter' ) . '</p>
413
+ </div>
414
+ </fieldset>
415
+ </div>';
416
+ }
417
+
418
+ /**
419
+ * Exclude IPs option.
420
+ */
421
+ public function exclude_ips() {
422
+ // lovely php 5.2 limitations
423
+ $ips = Post_Views_Counter()->options['general']['exclude_ips'];
424
+
425
+ echo '
426
+ <div id="pvc_exclude_ips">';
427
+
428
+ if ( ! empty( $ips ) ) {
429
+ foreach ( $ips as $key => $ip ) {
430
+ echo '
431
+ <div class="ip-box">
432
+ <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>
433
+ </div>';
434
+ }
435
+ } else {
436
+ echo '
437
+ <div class="ip-box">
438
+ <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>
439
+ </div>';
440
+ }
441
+
442
+ echo '
443
+ <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>
444
+ <p class="description">' . __( 'Enter the IP addresses to be excluded from post views count.', 'post-views-counter' ) . '</p>
445
+ </div>';
446
+ }
447
+
448
+ /**
449
+ * Strict counts option.
450
+ */
451
+ public function strict_counts() {
452
+ echo '
453
+ <div id="pvc_strict_counts">
454
+ <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>
455
+ </div>';
456
+ }
457
+
458
+ /**
459
+ * WP-PostViews import option.
460
+ */
461
+ public function wp_postviews() {
462
+ echo '
463
+ <div id="pvc_wp_postviews">
464
+ <fieldset>
465
+ <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>
466
+ <p class="description">' . __( 'Import post views data from WP-PostViews plugin.', 'post-views-counter' ) . '</p>
467
+ <input type="submit" class="button button-secondary" name="post_views_counter_reset_views" value="' . __( 'Delete views', 'post-views-counter' ) . '"/>
468
+ <p class="description">' . __( 'Delete ALL the existing post views data.', 'post-views-counter' ) . '</p>
469
+ </fieldset>
470
+ </div>';
471
+ }
472
+
473
+ /**
474
+ * Limit views edit to admins.
475
+ */
476
+ public function restrict_edit_views() {
477
+ echo '
478
+ <div id="pvc_restrict_edit_views">
479
+ <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>
480
+ </div>';
481
+ }
482
+
483
+ /**
484
+ * Plugin deactivation option.
485
+ */
486
+ public function deactivation_delete() {
487
+ echo '
488
+ <div id="pvc_deactivation_delete">
489
+ <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>
490
+ </div>';
491
+ }
492
+
493
+ /**
494
+ * Visibility option.
495
+ */
496
+ public function page_types_display() {
497
+ echo '
498
+ <div id="pvc_post_types_display">';
499
+
500
+ foreach ( $this->page_types as $key => $label ) {
501
+ echo '
502
+ <label><input id="pvc_page_types_display-' . esc_attr( $key ) . '" type="checkbox" name="post_views_counter_settings_display[page_types_display][' . esc_attr( $key ) . ']" value="1" ' . checked( in_array( $key, Post_Views_Counter()->options['display']['page_types_display'], true ), true, false ) . ' />' . esc_html( $label ) . '</label>';
503
+ }
504
+
505
+ echo '
506
+ <p class="description">' . __( 'Select page types where the views count will be displayed.', 'post-views-counter' ) . '</p>
507
+ </div>';
508
+ }
509
+
510
+ /**
511
+ * Counter position option.
512
+ */
513
+ public function position() {
514
+ echo '
515
+ <div id="pvc_position">
516
+ <select class="pvc-chosen-short" name="post_views_counter_settings_display[position]">';
517
+
518
+ foreach ( $this->positions as $position => $position_name ) {
519
+ echo '
520
+ <option value="' . esc_attr( $position ) . '" ' . selected( $position, Post_Views_Counter()->options['display']['position'], false ) . '>' . esc_html( $position_name ) . '</option>';
521
+ }
522
+
523
+ echo '
524
+ </select>
525
+ <p class="description">' . __( 'Select where would you like to display the post views counter. Use [post-views] shortcode for manual display.', 'post-views-counter' ) . '</p>
526
+ </div>';
527
+ }
528
+
529
+ /**
530
+ * Counter style option.
531
+ */
532
+ public function display_style() {
533
+ echo '
534
+ <div id="pvc_display_style">';
535
+
536
+ foreach ( $this->display_styles as $display => $style ) {
537
+ $display = esc_attr( $display );
538
+
539
+ echo '
540
+ <label><input type="checkbox" name="post_views_counter_settings_display[display_style][' . $display . ']" value="1" ' . checked( true, Post_Views_Counter()->options['display']['display_style'][$display], false ) . ' />' . esc_html( $style ) . '</label>';
541
+ }
542
+
543
+ echo '
544
+ <p class="description">' . __( 'Choose how to display the post views counter.', 'post-views-counter' ) . '</p>
545
+ </div>';
546
+ }
547
+
548
+ /**
549
+ * Counter icon class option.
550
+ */
551
+ public function icon_class() {
552
+ echo '
553
+ <div id="pvc_icon_class">
554
+ <input type="text" name="post_views_counter_settings_display[icon_class]" class="large-text" value="' . esc_attr( Post_Views_Counter()->options['display']['icon_class'] ) . '" />
555
+ <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>
556
+ </div>';
557
+ }
558
+
559
+ /**
560
+ * Restrict display option.
561
+ */
562
+ public function restrict_display() {
563
+ echo '
564
+ <div id="pvc_restrict_display">
565
+ <fieldset>';
566
+
567
+ foreach ( $this->groups as $type => $type_name ) {
568
+
569
+ if ( $type === 'robots' )
570
+ continue;
571
+
572
+ echo '
573
+ <label><input id="pvc_restrict_display-' . $type . '" type="checkbox" name="post_views_counter_settings_display[restrict_display][groups][' . esc_html( $type ) . ']" value="1" ' . checked( in_array( $type, Post_Views_Counter()->options['display']['restrict_display']['groups'], true ), true, false ) . ' />' . esc_html( $type_name ) . '</label>';
574
+ }
575
+
576
+ echo '
577
+ <p class="description">' . __( 'Use it to hide the post views counter from selected type of visitors.', 'post-views-counter' ) . '</p>
578
+ <div class="pvc_user_roles"' . (in_array( 'roles', Post_Views_Counter()->options['display']['restrict_display']['groups'], true ) ? '' : ' style="display: none;"') . '>';
579
+
580
+ foreach ( $this->user_roles as $role => $role_name ) {
581
+ echo '
582
+ <label><input type="checkbox" name="post_views_counter_settings_display[restrict_display][roles][' . $role . ']" value="1" ' . checked( in_array( $role, Post_Views_Counter()->options['display']['restrict_display']['roles'], true ), true, false ) . ' />' . esc_html( $role_name ) . '</label>';
583
+ }
584
+
585
+ echo '
586
+ <p class="description">' . __( 'Use it to hide the post views counter from selected user roles.', 'post-views-counter' ) . '</p>
587
+ </div>
588
+ </fieldset>
589
+ </div>';
590
+ }
591
+
592
+ /**
593
+ * Validate general settings.
594
+ */
595
+ public function validate_settings( $input ) {
596
+ // get main instance
597
+ $pvc = Post_Views_Counter();
598
+
599
+ if ( isset( $_POST['post_views_counter_import_wp_postviews'] ) ) {
600
+ global $wpdb;
601
+
602
+ $meta_key = esc_attr( apply_filters( 'pvc_import_meta_key', 'views' ) );
603
+
604
+ $views = $wpdb->get_results( "SELECT post_id, meta_value FROM " . $wpdb->postmeta . " WHERE meta_key = '" . $meta_key . "'", ARRAY_A, 0 );
605
+
606
+ if ( ! empty( $views ) ) {
607
+ $input = $pvc->defaults['general'];
608
+ $input['wp_postviews_import'] = true;
609
+
610
+ $sql = array();
611
+
612
+ foreach ( $views as $view ) {
613
+ $sql[] = "(" . $view['post_id'] . ", 4, 'total', " . $view['meta_value'] . ")";
614
+ }
615
+
616
+ $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)" );
617
+
618
+ add_settings_error( 'wp_postviews_import', 'wp_postviews_import', __( 'Post views data imported succesfully.', 'post-views-counter' ), 'updated' );
619
+ } else {
620
+ add_settings_error( 'wp_postviews_import', 'wp_postviews_import', __( 'There was no post views data to import.', 'post-views-counter' ), 'updated' );
621
+ }
622
+ } elseif ( isset( $_POST['post_views_counter_reset_views'] ) ) {
623
+ global $wpdb;
624
+
625
+ if ( $wpdb->query( 'TRUNCATE TABLE ' . $wpdb->prefix . 'post_views' ) )
626
+ add_settings_error( 'reset_post_views', 'reset_post_views', __( 'All existing data deleted succesfully.', 'post-views-counter' ), 'updated' );
627
+ else
628
+ add_settings_error( 'reset_post_views', 'reset_post_views', __( 'Error occurred. All existing data were not deleted.', 'post-views-counter' ), 'error' );
629
+ } elseif ( isset( $_POST['save_pvc_general'] ) ) {
630
+ // post types count
631
+ if ( isset( $input['post_types_count'] ) ) {
632
+ $post_types = array();
633
+
634
+ foreach ( $input['post_types_count'] as $post_type => $set ) {
635
+ if ( isset( $this->post_types[$post_type] ) )
636
+ $post_types[] = $post_type;
637
+ }
638
+
639
+ $input['post_types_count'] = array_unique( $post_types );
640
+ } else
641
+ $input['post_types_count'] = array();
642
+
643
+ // counter mode
644
+ $input['counter_mode'] = isset( $input['counter_mode'], $this->modes[$input['counter_mode']] ) ? $input['counter_mode'] : $pvc->defaults['general']['counter_mode'];
645
+
646
+ // post views column
647
+ $input['post_views_column'] = isset( $input['post_views_column'] );
648
+
649
+ // time between counts
650
+ $input['time_between_counts']['number'] = (int) ( isset( $input['time_between_counts']['number'] ) ? $input['time_between_counts']['number'] : $pvc->defaults['general']['time_between_counts']['number'] );
651
+ $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'];
652
+
653
+ // flush interval
654
+ $input['flush_interval']['number'] = (int) ( isset( $input['flush_interval']['number'] ) ? $input['flush_interval']['number'] : $pvc->defaults['general']['flush_interval']['number'] );
655
+ $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'];
656
+
657
+ // Since the settings are about to be saved and cache flush interval could've changed,
658
+ // we want to make sure that any changes done on the settings page are in effect immediately
659
+ // (instead of having to wait for the previous schedule to occur).
660
+ // We achieve that by making sure to clear any previous cache flush schedules and
661
+ // schedule the new one if the specified interval is > 0
662
+ $pvc->remove_cache_flush();
663
+
664
+ if ( $input['flush_interval']['number'] > 0 ) {
665
+ $pvc->schedule_cache_flush();
666
+ }
667
+
668
+ // reset counts
669
+ $input['reset_counts']['number'] = (int) ( isset( $input['reset_counts']['number'] ) ? $input['reset_counts']['number'] : $pvc->defaults['general']['reset_counts']['number'] );
670
+ $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'];
671
+
672
+ // run cron on next visit?
673
+ $input['cron_run'] = ($input['reset_counts']['number'] > 0 ? true : false);
674
+ $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'] ) ? true : false);
675
+
676
+ // exclude
677
+ if ( isset( $input['exclude']['groups'] ) ) {
678
+ $groups = array();
679
+
680
+ foreach ( $input['exclude']['groups'] as $group => $set ) {
681
+ if ( isset( $this->groups[$group] ) )
682
+ $groups[] = $group;
683
+ }
684
+
685
+ $input['exclude']['groups'] = array_unique( $groups );
686
+ } else {
687
+ $input['exclude']['groups'] = array();
688
+ }
689
+
690
+ if ( in_array( 'roles', $input['exclude']['groups'], true ) && isset( $input['exclude']['roles'] ) ) {
691
+ $roles = array();
692
+
693
+ foreach ( $input['exclude']['roles'] as $role => $set ) {
694
+ if ( isset( $this->user_roles[$role] ) )
695
+ $roles[] = $role;
696
+ }
697
+
698
+ $input['exclude']['roles'] = array_unique( $roles );
699
+ } else
700
+ $input['exclude']['roles'] = array();
701
+
702
+ // exclude ips
703
+ if ( isset( $input['exclude_ips'] ) ) {
704
+ $ips = array();
705
+
706
+ foreach ( $input['exclude_ips'] as $ip ) {
707
+ if ( strpos( $ip, '*' ) !== false ) {
708
+ $new_ip = str_replace( '*', '0', $ip );
709
+
710
+ if ( filter_var( $new_ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4 ) )
711
+ $ips[] = $ip;
712
+ } elseif ( filter_var( $ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4 ) )
713
+ $ips[] = $ip;
714
+ }
715
+
716
+ $input['exclude_ips'] = array_unique( $ips );
717
+ }
718
+
719
+ // restrict edit views
720
+ $input['restrict_edit_views'] = isset( $input['restrict_edit_views'] );
721
+
722
+ // strict counts
723
+ $input['strict_counts'] = isset( $input['strict_counts'] );
724
+
725
+ // deactivation delete
726
+ $input['deactivation_delete'] = isset( $input['deactivation_delete'] );
727
+
728
+ $input['update_version'] = $pvc->options['general']['update_version'];
729
+ $input['update_notice'] = $pvc->options['general']['update_notice'];
730
+ } elseif ( isset( $_POST['save_pvc_display'] ) ) {
731
+
732
+ // post views label
733
+ $input['label'] = isset( $input['label'] ) ? $input['label'] : $pvc->defaults['general']['label'];
734
+
735
+ if ( function_exists( 'icl_register_string' ) )
736
+ icl_register_string( 'Post Views Counter', 'Post Views Label', $input['label'] );
737
+
738
+ // position
739
+ $input['position'] = isset( $input['position'], $this->positions[$input['position']] ) ? $input['position'] : $pvc->defaults['general']['position'];
740
+
741
+ // display style
742
+ $input['display_style']['icon'] = isset( $input['display_style']['icon'] );
743
+ $input['display_style']['text'] = isset( $input['display_style']['text'] );
744
+
745
+ // link to post
746
+ $input['link_to_post'] = isset( $input['link_to_post'] ) ? $input['link_to_post'] : $pvc->defaults['display']['link_to_post'];
747
+
748
+ // icon class
749
+ $input['icon_class'] = isset( $input['icon_class'] ) ? trim( $input['icon_class'] ) : $pvc->defaults['general']['icon_class'];
750
+
751
+ // post types display
752
+ if ( isset( $input['post_types_display'] ) ) {
753
+ $post_types = array();
754
+
755
+ foreach ( $input['post_types_display'] as $post_type => $set ) {
756
+ if ( isset( $this->post_types[$post_type] ) )
757
+ $post_types[] = $post_type;
758
+ }
759
+
760
+ $input['post_types_display'] = array_unique( $post_types );
761
+ } else
762
+ $input['post_types_display'] = array();
763
+
764
+ // page types display
765
+ if ( isset( $input['page_types_display'] ) ) {
766
+ $page_types = array();
767
+
768
+ foreach ( $input['page_types_display'] as $page_type => $set ) {
769
+ if ( isset( $this->page_types[$page_type] ) )
770
+ $page_types[] = $page_type;
771
+ }
772
+
773
+ $input['page_types_display'] = array_unique( $page_types );
774
+ } else
775
+ $input['page_types_display'] = array();
776
+
777
+ // restrict display
778
+ if ( isset( $input['restrict_display']['groups'] ) ) {
779
+ $groups = array();
780
+
781
+ foreach ( $input['restrict_display']['groups'] as $group => $set ) {
782
+ if ( $group === 'robots' )
783
+ continue;
784
+
785
+ if ( isset( $this->groups[$group] ) )
786
+ $groups[] = $group;
787
+ }
788
+
789
+ $input['restrict_display']['groups'] = array_unique( $groups );
790
+ } else
791
+ $input['restrict_display']['groups'] = array();
792
+
793
+ if ( in_array( 'roles', $input['restrict_display']['groups'], true ) && isset( $input['restrict_display']['roles'] ) ) {
794
+ $roles = array();
795
+
796
+ foreach ( $input['restrict_display']['roles'] as $role => $set ) {
797
+ if ( isset( $this->user_roles[$role] ) )
798
+ $roles[] = $role;
799
+ }
800
+
801
+ $input['restrict_display']['roles'] = array_unique( $roles );
802
+ } else
803
+ $input['restrict_display']['roles'] = array();
804
+ } elseif ( isset( $_POST['reset_pvc_general'] ) ) {
805
+ $input = $pvc->defaults['general'];
806
+
807
+ add_settings_error( 'reset_general_settings', 'settings_reset', __( 'General settings restored to defaults.', 'post-views-counter' ), 'updated' );
808
+ } elseif ( isset( $_POST['reset_pvc_display'] ) ) {
809
+ $input = $pvc->defaults['display'];
810
+
811
+ add_settings_error( 'reset_general_settings', 'settings_reset', __( 'Display settings restored to defaults.', 'post-views-counter' ), 'updated' );
812
+ }
813
+
814
+ return $input;
815
+ }
816
  }
includes/widgets.php CHANGED
@@ -55,7 +55,7 @@ class Post_Views_Counter_List_Widget extends WP_Widget {
55
  'show_post_thumbnail' => false,
56
  'show_post_excerpt' => false,
57
  'show_post_author' => false,
58
- 'no_posts_message' => __( 'No Posts found', 'post-views-counter' )
59
  );
60
 
61
  $this->pvc_order_types = array(
55
  'show_post_thumbnail' => false,
56
  'show_post_excerpt' => false,
57
  'show_post_author' => false,
58
+ 'no_posts_message' => __( 'No most viewed posts found', 'post-views-counter' )
59
  );
60
 
61
  $this->pvc_order_types = array(
js/admin-dashboard.js CHANGED
@@ -1,25 +1,84 @@
1
  ( function ( $ ) {
2
 
3
  window.onload = function () {
4
- updateChart( 'this_month' );
 
5
  };
 
 
 
 
 
 
 
 
6
 
7
- function ajaxGetChartData( init, period, container ) {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
8
  $.ajax( {
9
  url: pvcArgs.ajaxURL,
10
  type: 'POST',
11
  dataType: 'json',
12
  data: {
13
- action: 'pvc_dashboard_chart',
14
  nonce: pvcArgs.nonce,
15
  period: period
16
  },
17
- success: function ( args ) {
 
 
 
 
18
  // first call?
19
  if ( init ) {
20
- container.removeClass( 'loading' );
21
- container.find( '.spinner' ).removeClass( 'is-active' );
 
 
 
 
 
 
 
22
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
23
  var config = {
24
  type: 'line',
25
  options: {
@@ -37,8 +96,14 @@
37
 
38
  // rerender the chart
39
  ci.update();
40
-
41
- ajaxUpdateChartPostTypes( ci.data.datasets[index].post_type, meta.hidden === null ? false : meta.hidden );
 
 
 
 
 
 
42
  },
43
  labels: {
44
  boxWidth: 0,
@@ -52,14 +117,14 @@
52
  display: true,
53
  scaleLabel: {
54
  display: false,
55
- labelString: args.text.xAxes
56
  }
57
  } ],
58
  yAxes: [ {
59
  display: true,
60
  scaleLabel: {
61
  display: false,
62
- labelString: args.text.yAxes
63
  }
64
  } ]
65
  },
@@ -69,35 +134,34 @@
69
  }
70
  };
71
 
72
- config = updateConfig( config, args );
73
 
74
- window.chartPVC = new Chart( document.getElementById( 'pvc_chart' ).getContext( '2d' ), config );
75
  } else {
76
- bindMonthEvents( args.months );
77
 
78
- window.chartPVC.config = updateConfig( window.chartPVC.config, args );
79
  window.chartPVC.update();
80
  }
81
  }
82
  } );
83
  }
84
 
85
- function ajaxUpdateChartPostTypes( post_type, hidden ) {
86
  $.ajax( {
87
  url: pvcArgs.ajaxURL,
88
  type: 'POST',
89
  dataType: 'json',
90
  data: {
91
- action: 'pvc_dashboard_chart_user_post_types',
92
  nonce: pvcArgs.nonceUser,
93
- post_type: post_type,
94
- hidden: hidden
95
  },
96
  success: function ( ) {}
97
  } );
98
  }
99
 
100
- function updateConfig( config, args ) {
101
  // update datasets
102
  config.data = args.data;
103
 
@@ -129,20 +193,28 @@
129
  return config;
130
  }
131
 
132
- function updateChart( period ) {
133
- var container = document.getElementById( 'pvc_dashboard_container' );
134
 
135
  if ( $( container ).length > 0 ) {
136
- bindMonthEvents( false );
 
 
 
 
 
 
 
137
 
138
- $( container ).addClass( 'loading' ).append( '<span class="spinner is-active"></span>' );
 
139
 
140
- ajaxGetChartData( true, period, $( container ) );
141
  }
142
  }
143
 
144
- function bindMonthEvents( newMonths ) {
145
- var months = document.getElementsByClassName( 'pvc_months' );
146
 
147
  // replace months?
148
  if ( newMonths !== false )
@@ -151,17 +223,36 @@
151
  var prev = months[0].getElementsByClassName( 'prev' );
152
  var next = months[0].getElementsByClassName( 'next' );
153
 
154
- prev[0].addEventListener( 'click', loadChartData );
 
 
 
 
155
 
156
  // skip span
157
- if ( next[0].tagName === 'A' )
158
- next[0].addEventListener( 'click', loadChartData );
 
 
 
 
 
159
  }
160
 
161
- function loadChartData( e ) {
 
 
 
 
 
 
 
 
162
  e.preventDefault();
 
 
163
 
164
- ajaxGetChartData( false, e.target.dataset.date );
165
  }
166
 
167
  } )( jQuery );
1
  ( function ( $ ) {
2
 
3
  window.onload = function () {
4
+ pvcUpdateChart( 'this_month' );
5
+ pvcUpdateMostViewed( 'this_month' );
6
  };
7
+
8
+ // ready event
9
+ $( function() {
10
+ $( '.pvc-accordion-header' ).on( 'click', function( e ) {
11
+ $( this ).closest( '.pvc-accordion-item' ).toggleClass( 'pvc-collapsed' );
12
+
13
+ var items = $( '#pvc-dashboard-accordion' ).find( '.pvc-accordion-item' ),
14
+ menuItems = {};
15
 
16
+ if ( items.length > 0 ) {
17
+ $( items ).each( function( index, item ) {
18
+ var itemName = $( item ).prop( 'id' );
19
+ itemName = itemName.replace( 'pvc-', '' );
20
+
21
+ menuItems[itemName] = $( item ).hasClass( 'pvc-collapsed' );
22
+ } );
23
+ }
24
+
25
+ // update user options
26
+ var userOptions = {
27
+ menu_items: menuItems
28
+ };
29
+
30
+ pvcUpdateUserOptions( userOptions );
31
+ } );
32
+ } );
33
+
34
+ function pvcGetViewedData( init, period, container ) {
35
+ $( container ).addClass( 'loading' ).find( '.spinner' ).addClass( 'is-active' );
36
+
37
  $.ajax( {
38
  url: pvcArgs.ajaxURL,
39
  type: 'POST',
40
  dataType: 'json',
41
  data: {
42
+ action: 'pvc_dashboard_most_viewed',
43
  nonce: pvcArgs.nonce,
44
  period: period
45
  },
46
+ success: function ( response ) {
47
+ // remove loader
48
+ $( container ).removeClass( 'loading' );
49
+ $( container ).find( '.spinner' ).removeClass( 'is-active' );
50
+
51
  // first call?
52
  if ( init ) {
53
+ $( container ).find( '#pvc-viewed' ).html( response.html );
54
+ } else {
55
+ pvcBindMonthEvents( response.months, container );
56
+
57
+ $( container ).find( '#pvc-viewed' ).html( response.html );
58
+ }
59
+ }
60
+ } );
61
+ }
62
 
63
+ function pvcGetChartData( init, period, container ) {
64
+ $( container ).addClass( 'loading' ).find( '.spinner' ).addClass( 'is-active' );
65
+
66
+ $.ajax( {
67
+ url: pvcArgs.ajaxURL,
68
+ type: 'POST',
69
+ dataType: 'json',
70
+ data: {
71
+ action: 'pvc_dashboard_chart',
72
+ nonce: pvcArgs.nonce,
73
+ period: period
74
+ },
75
+ success: function ( response ) {
76
+ // remove loader
77
+ $( container ).removeClass( 'loading' );
78
+ $( container ).find( '.spinner' ).removeClass( 'is-active' );
79
+
80
+ // first call?
81
+ if ( init ) {
82
  var config = {
83
  type: 'line',
84
  options: {
96
 
97
  // rerender the chart
98
  ci.update();
99
+
100
+ // update user options
101
+ var userOptions = {
102
+ post_type: ci.data.datasets[index].post_type,
103
+ hidden: meta.hidden === null ? false : meta.hidden
104
+ }
105
+
106
+ pvcUpdateUserOptions( userOptions );
107
  },
108
  labels: {
109
  boxWidth: 0,
117
  display: true,
118
  scaleLabel: {
119
  display: false,
120
+ labelString: response.text.xAxes
121
  }
122
  } ],
123
  yAxes: [ {
124
  display: true,
125
  scaleLabel: {
126
  display: false,
127
+ labelString: response.text.yAxes
128
  }
129
  } ]
130
  },
134
  }
135
  };
136
 
137
+ config = pvcUpdateConfig( config, response );
138
 
139
+ window.chartPVC = new Chart( document.getElementById( 'pvc-chart' ).getContext( '2d' ), config );
140
  } else {
141
+ pvcBindMonthEvents( response.months, container );
142
 
143
+ window.chartPVC.config = pvcUpdateConfig( window.chartPVC.config, response );
144
  window.chartPVC.update();
145
  }
146
  }
147
  } );
148
  }
149
 
150
+ function pvcUpdateUserOptions( options ) {
151
  $.ajax( {
152
  url: pvcArgs.ajaxURL,
153
  type: 'POST',
154
  dataType: 'json',
155
  data: {
156
+ action: 'pvc_dashboard_user_options',
157
  nonce: pvcArgs.nonceUser,
158
+ options: options
 
159
  },
160
  success: function ( ) {}
161
  } );
162
  }
163
 
164
+ function pvcUpdateConfig( config, args ) {
165
  // update datasets
166
  config.data = args.data;
167
 
193
  return config;
194
  }
195
 
196
+ function pvcUpdateChart( period ) {
197
+ var container = $( '#pvc-post-views' ).find( '.pvc-dashboard-container' );
198
 
199
  if ( $( container ).length > 0 ) {
200
+ pvcBindMonthEvents( false, container );
201
+
202
+ pvcGetChartData( true, period, container );
203
+ }
204
+ }
205
+
206
+ function pvcUpdateMostViewed( period ) {
207
+ var container = $( '#pvc-most-viewed' ).find( '.pvc-dashboard-container' );
208
 
209
+ if ( $( container ).length > 0 ) {
210
+ pvcBindMonthEvents( false, container );
211
 
212
+ pvcGetViewedData( true, period, container );
213
  }
214
  }
215
 
216
+ function pvcBindMonthEvents( newMonths, container ) {
217
+ var months = $( container ).find( '.pvc-months' );
218
 
219
  // replace months?
220
  if ( newMonths !== false )
223
  var prev = months[0].getElementsByClassName( 'prev' );
224
  var next = months[0].getElementsByClassName( 'next' );
225
 
226
+ if ( $( container ).closest( '.pvc-accordion-item' ).attr( 'id' ) === 'pvc-most-viewed' ) {
227
+ prev[0].addEventListener( 'click', pvcLoadMostViewedData );
228
+ } else {
229
+ prev[0].addEventListener( 'click', pvcLoadChartData );
230
+ }
231
 
232
  // skip span
233
+ if ( next[0].tagName === 'A' ) {
234
+ if ( $( container ).closest( '.pvc-accordion-item' ).attr( 'id' ) === 'pvc-most-viewed' ) {
235
+ next[0].addEventListener( 'click', pvcLoadMostViewedData );
236
+ } else {
237
+ next[0].addEventListener( 'click', pvcLoadChartData );
238
+ }
239
+ }
240
  }
241
 
242
+ function pvcLoadChartData( e ) {
243
+ e.preventDefault();
244
+
245
+ var container = $( '#pvc-post-views' ).find( '.pvc-dashboard-container' );
246
+
247
+ pvcGetChartData( false, e.target.dataset.date, container );
248
+ }
249
+
250
+ function pvcLoadMostViewedData( e ) {
251
  e.preventDefault();
252
+
253
+ var container = $( '#pvc-most-viewed' ).find( '.pvc-dashboard-container' );
254
 
255
+ pvcGetViewedData( false, e.target.dataset.date, container );
256
  }
257
 
258
  } )( jQuery );
js/admin-post.js CHANGED
@@ -1,46 +1,47 @@
1
- ( function( $ ) {
2
-
3
- $( document ).ready( function() {
4
- // post views input
5
- $( '#post-views .edit-post-views' ).click( function() {
6
- if ( $( '#post-views-input-container' ).is( ":hidden" ) ) {
7
- $( '#post-views-input-container' ).slideDown( 'fast' );
8
- $( this ).hide();
9
- }
10
-
11
- return false;
12
- } );
13
-
14
- // save post views
15
- $( '#post-views .save-post-views' ).click( function() {
16
- var views = $.trim( $( '#post-views-display b' ).text() );
17
-
18
- $( '#post-views-input-container' ).slideUp( 'fast' );
19
- $( '#post-views .edit-post-views' ).show();
20
-
21
- views = parseInt( $( '#post-views-input' ).val() );
22
- // reassign value as integer
23
- $( '#post-views-input' ).val( views );
24
-
25
- $( '#post-views-display b' ).text( views );
26
-
27
- return false;
28
- } );
29
-
30
- // cancel post views
31
- $( '#post-views .cancel-post-views' ).click( function() {
32
- var views = $.trim( $( '#post-views-display b' ).text() );
33
-
34
- $( '#post-views-input-container' ).slideUp( 'fast' );
35
- $( '#post-views .edit-post-views' ).show();
36
-
37
- views = parseInt( $( '#post-views-current' ).val() );
38
-
39
- $( '#post-views-display b' ).text( views );
40
- $( '#post-views-input' ).val( views );
41
-
42
- return false;
43
- } );
44
- } );
45
-
 
46
  } )( jQuery );
1
+ ( function( $ ) {
2
+
3
+ // ready event
4
+ $( function() {
5
+ // post views input
6
+ $( '#post-views .edit-post-views' ).on( 'click', function() {
7
+ if ( $( '#post-views-input-container' ).is( ":hidden" ) ) {
8
+ $( '#post-views-input-container' ).slideDown( 'fast' );
9
+ $( this ).hide();
10
+ }
11
+
12
+ return false;
13
+ } );
14
+
15
+ // save post views
16
+ $( '#post-views .save-post-views' ).on( 'click', function() {
17
+ var views = ( $( '#post-views-display b' ).text() ).trim();
18
+
19
+ $( '#post-views-input-container' ).slideUp( 'fast' );
20
+ $( '#post-views .edit-post-views' ).show();
21
+
22
+ views = parseInt( $( '#post-views-input' ).val() );
23
+ // reassign value as integer
24
+ $( '#post-views-input' ).val( views );
25
+
26
+ $( '#post-views-display b' ).text( views );
27
+
28
+ return false;
29
+ } );
30
+
31
+ // cancel post views
32
+ $( '#post-views .cancel-post-views' ).on( 'click', function() {
33
+ var views = ( $( '#post-views-display b' ).text() ).trim();
34
+
35
+ $( '#post-views-input-container' ).slideUp( 'fast' );
36
+ $( '#post-views .edit-post-views' ).show();
37
+
38
+ views = parseInt( $( '#post-views-current' ).val() );
39
+
40
+ $( '#post-views-display b' ).text( views );
41
+ $( '#post-views-input' ).val( views );
42
+
43
+ return false;
44
+ } );
45
+ } );
46
+
47
  } )( jQuery );
js/admin-quick-edit.js CHANGED
@@ -1,65 +1,62 @@
1
- ( function( $ ) {
2
-
3
- // we create a copy of the WP inline edit post function
4
- var $wp_inline_edit = inlineEditPost.edit;
5
-
6
- // and then we overwrite the function with our own code
7
- inlineEditPost.edit = function( id ) {
8
- console.log( 'edit' );
9
- // call the original WP edit function
10
- // we don't want to leave WordPress hanging
11
- $wp_inline_edit.apply( this, arguments );
12
-
13
- // get the post ID
14
- var $post_id = 0;
15
-
16
- if ( typeof ( id ) == 'object' )
17
- $post_id = parseInt( this.getId( id ) );
18
-
19
- if ( $post_id > 0 ) {
20
- // define the edit row
21
- var $edit_row = $( '#edit-' + $post_id ),
22
- $post_row = $( '#post-' + $post_id );
23
-
24
- // get the data
25
- var $post_views = $( '.column-post_views', $post_row ).text();
26
-
27
- // populate the data
28
- $( ':input[name="post_views"]', $edit_row ).val( $post_views );
29
- $( ':input[name="current_post_views"]', $edit_row ).val( $post_views );
30
- }
31
-
32
- return false;
33
- };
34
-
35
- $( document ).on( 'click', '#bulk_edit', function() {
36
- console.log( 'bulk edit' );
37
- // define the bulk edit row
38
- var $bulk_row = $( '#bulk-edit' );
39
-
40
- // get the selected post ids that are being edited
41
- var $post_ids = new Array();
42
-
43
- $bulk_row.find( '#bulk-titles' ).children().each( function() {
44
- $post_ids.push( $( this ).attr( 'id' ).replace( /^(ttle)/i, '' ) );
45
- } );
46
-
47
- // get the data
48
- var $post_views = $bulk_row.find( 'input[name="post_views"]' ).val();
49
-
50
- // save the data
51
- $.ajax( {
52
- url: ajaxurl, // this is a variable that WordPress has already defined for us
53
- type: 'post',
54
- async: false,
55
- cache: false,
56
- data: {
57
- action: 'save_bulk_post_views', // this is the name of our WP AJAX function that we'll set up next
58
- post_ids: $post_ids, // and these are the 2 parameters we're passing to our function
59
- post_views: $post_views,
60
- current_post_views: $post_views,
61
- }
62
- } );
63
- } );
64
-
65
  } )( jQuery );
1
+ ( function( $ ) {
2
+
3
+ // we create a copy of the WP inline edit post function
4
+ var $wp_inline_edit = inlineEditPost.edit;
5
+
6
+ // and then we overwrite the function with our own code
7
+ inlineEditPost.edit = function( id ) {
8
+ // call the original WP edit function, we don't want to leave WordPress hanging
9
+ $wp_inline_edit.apply( this, arguments );
10
+
11
+ // get the post ID
12
+ var $post_id = 0;
13
+
14
+ if ( typeof ( id ) == 'object' )
15
+ $post_id = parseInt( this.getId( id ) );
16
+
17
+ if ( $post_id > 0 ) {
18
+ // define the edit row
19
+ var $edit_row = $( '#edit-' + $post_id ),
20
+ $post_row = $( '#post-' + $post_id );
21
+
22
+ // get the data
23
+ var $post_views = $( '.column-post_views', $post_row ).text();
24
+
25
+ // populate the data
26
+ $( ':input[name="post_views"]', $edit_row ).val( $post_views );
27
+ $( ':input[name="current_post_views"]', $edit_row ).val( $post_views );
28
+ }
29
+
30
+ return false;
31
+ };
32
+
33
+ $( document ).on( 'click', '#bulk_edit', function() {
34
+ // define the bulk edit row
35
+ var $bulk_row = $( '#bulk-edit' );
36
+
37
+ // get the selected post ids that are being edited
38
+ var $post_ids = new Array();
39
+
40
+ $bulk_row.find( '#bulk-titles' ).children().each( function() {
41
+ $post_ids.push( $( this ).attr( 'id' ).replace( /^(ttle)/i, '' ) );
42
+ } );
43
+
44
+ // get the data
45
+ var $post_views = $bulk_row.find( 'input[name="post_views"]' ).val();
46
+
47
+ // save the data
48
+ $.ajax( {
49
+ url: ajaxurl, // this is a variable that WordPress has already defined for us
50
+ type: 'post',
51
+ async: false,
52
+ cache: false,
53
+ data: {
54
+ action: 'save_bulk_post_views', // this is the name of our WP AJAX function that we'll set up next
55
+ post_ids: $post_ids, // and these are the 2 parameters we're passing to our function
56
+ post_views: $post_views,
57
+ current_post_views: $post_views,
58
+ }
59
+ } );
60
+ } );
61
+
 
 
 
62
  } )( jQuery );
js/admin-settings.js CHANGED
@@ -1,133 +1,66 @@
1
- ( function ( $ ) {
2
-
3
- $( document ).ready( function () {
4
-
5
- $( '.post-views-counter-settings' ).checkBo();
6
-
7
- var ip_boxes = $( '#pvc_exclude_ips' ).find( '.ip-box' ).length;
8
-
9
- $( '#pvc_exclude_ips .ip-box:first' ).find( '.remove-exclude-ip' ).hide();
10
-
11
- // ask whether to reset options to defaults
12
- $( document ).on( 'click', '.reset_pvc_settings', function () {
13
- return confirm( pvcArgsSettings.resetToDefaults );
14
- } );
15
-
16
- // ask whether to reset views
17
- $( document ).on( 'click', 'input[name="post_views_counter_reset_views"]', function () {
18
- return confirm( pvcArgsSettings.resetViews );
19
- } );
20
-
21
- // remove ip box
22
- $( document ).on( 'click', '.remove-exclude-ip', function ( e ) {
23
- e.preventDefault();
24
-
25
- ip_boxes--;
26
-
27
- var parent = $( this ).parent();
28
-
29
- // remove ip box
30
- parent.slideUp( 'fast', function () {
31
- $( this ).remove();
32
- } );
33
- } );
34
-
35
- // add ip box
36
- $( document ).on( 'click', '.add-exclude-ip', function () {
37
- ip_boxes++;
38
-
39
- var parent = $( this ).parents( '#pvc_exclude_ips' ),
40
- new_ip_box = parent.find( '.ip-box:last' ).clone().hide();
41
-
42
- // clear value
43
- new_ip_box.find( 'input' ).val( '' );
44
-
45
- if ( ip_boxes > 1 ) {
46
- new_ip_box.find( '.remove-exclude-ip' ).show();
47
- }
48
-
49
- // add and display new ip box
50
- parent.find( '.ip-box:last' ).after( new_ip_box ).next().slideDown( 'fast' );
51
- } );
52
-
53
- // add current ip
54
- $( document ).on( 'click', '.add-current-ip', function () {
55
- // fill input with user's current ip
56
- $( this ).parents( '#pvc_exclude_ips' ).find( '.ip-box' ).last().find( 'input' ).val( $( this ).attr( 'data-rel' ) );
57
- } );
58
-
59
- // toggle user roles
60
- $( '#pvc_exclude-roles, #pvc_restrict_display-roles' ).change( function () {
61
- if ( $( this ).is( ':checked' ) ) {
62
- $( '.pvc_user_roles' ).slideDown( 'fast' );
63
- } else {
64
- $( '.pvc_user_roles' ).slideUp( 'fast' );
65
- }
66
- } );
67
-
68
- } );
69
-
70
- } )( jQuery );
71
-
72
- /*
73
- * checkBo lightweight jQuery plugin v0.1.4 by @ElmahdiMahmoud
74
- * Licensed under the MIT license - https://github.com/elmahdim/checkbo/blob/master/LICENSE
75
- *
76
- * Custom checkbox and radio
77
- * Author URL: elmahdim.com
78
- */
79
- !function ( e ) {
80
- e.fn.checkBo = function ( c ) {
81
- return c = e.extend( { }, { checkAllButton: null, checkAllTarget: null, checkAllTextDefault: null, checkAllTextToggle: null }, c ), this.each( function () {
82
- function t( e ) {
83
- this.input = e
84
- }
85
- function n() {
86
- var c = e( this ).is( ":checked" );
87
- e( this ).closest( "label" ).toggleClass( "checked", c )
88
- }
89
- function i( e, c, t ) {
90
- e.text( e.parent( a ).hasClass( "checked" ) ? t : c )
91
- }
92
- function h( c ) {
93
- var t = c.attr( "data-show" );
94
- c = c.attr( "data-hide" ), e( t ).removeClass( "is-hidden" ), e( c ).addClass( "is-hidden" )
95
- }
96
- var l = e( this ), a = l.find( ".cb-checkbox" ), d = l.find( ".cb-radio" ), o = l.find( ".cb-switcher" ), s = a.find( "input:checkbox" ), f = d.find( "input:radio" );
97
- s.wrap( '<span class="cb-inner"><i></i></span>' ), f.wrap( '<span class="cb-inner"><i></i></span>' );
98
- var k = new t( "input:checkbox" ), r = new t( "input:radio" );
99
- if ( t.prototype.checkbox = function ( e ) {
100
- var c = e.find( this.input ).is( ":checked" );
101
- e.find( this.input ).prop( "checked", !c ).trigger( "change" )
102
- }, t.prototype.radiobtn = function ( c, t ) {
103
- var n = e( 'input:radio[name="' + t + '"]' );
104
- n.prop( "checked", !1 ), n.closest( n.closest( d ) ).removeClass( "checked" ), c.addClass( "checked" ), c.find( this.input ).get( 0 ).checked = c.hasClass( "checked" ), c.find( this.input ).change()
105
- }, s.on( "change", n ), f.on( "change", n ), a.find( "a" ).on( "click", function ( e ) {
106
- e.stopPropagation()
107
- } ), a.on( "click", function ( c ) {
108
- c.preventDefault(), k.checkbox( e( this ) ), c = e( this ).attr( "data-toggle" ), e( c ).toggleClass( "is-hidden" ), h( e( this ) )
109
- } ), d.on( "click", function ( c ) {
110
- c.preventDefault(), r.radiobtn( e( this ), e( this ).find( "input:radio" ).attr( "name" ) ), h( e( this ) )
111
- } ), e.fn.toggleCheckbox = function () {
112
- this.prop( "checked", !this.is( ":checked" ) )
113
- }, e.fn.switcherChecker = function () {
114
- var c = e( this ), t = c.find( "input" ), n = c.find( ".cb-state" );
115
- t.is( ":checked" ) ? ( c.addClass( "checked" ), n.html( t.attr( "data-state-on" ) ) ) : ( c.removeClass( "checked" ), n.html( t.attr( "data-state-off" ) ) )
116
- }, o.on( "click", function ( c ) {
117
- c.preventDefault(), c = e( this ), c.find( "input" ).toggleCheckbox(), c.switcherChecker(), e( c.attr( "data-toggle" ) ).toggleClass( "is-hidden" )
118
- } ), o.each( function () {
119
- e( this ).switcherChecker()
120
- } ), c.checkAllButton && c.checkAllTarget ) {
121
- var u = e( this );
122
- u.find( e( c.checkAllButton ) ).on( "click", function () {
123
- u.find( c.checkAllTarget ).find( "input:checkbox" ).each( function () {
124
- u.find( e( c.checkAllButton ) ).hasClass( "checked" ) ? u.find( c.checkAllTarget ).find( "input:checkbox" ).prop( "checked", !0 ).change() : u.find( c.checkAllTarget ).find( "input:checkbox" ).prop( "checked", !1 ).change()
125
- } ), i( u.find( e( c.checkAllButton ) ).find( ".toggle-text" ), c.checkAllTextDefault, c.checkAllTextToggle )
126
- } ), u.find( c.checkAllTarget ).find( a ).on( "click", function () {
127
- u.find( c.checkAllButton ).find( "input:checkbox" ).prop( "checked", !1 ).change().removeClass( "checked" ), i( u.find( e( c.checkAllButton ) ).find( ".toggle-text" ), c.checkAllTextDefault, c.checkAllTextToggle )
128
- } )
129
- }
130
- l.find( '[checked="checked"]' ).closest( "label" ).addClass( "checked" ), l.find( "input" ).is( "input:disabled" ) && l.find( "input:disabled" ).closest( "label" ).off().addClass( "disabled" )
131
- } )
132
- }
133
- }( jQuery, window, document );
1
+ ( function( $ ) {
2
+
3
+ // ready event
4
+ $( function() {
5
+ var ip_boxes = $( '#pvc_exclude_ips' ).find( '.ip-box' ).length;
6
+
7
+ $( '#pvc_exclude_ips .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( '#pvc_exclude_ips' ),
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
+ // add and display new ip box
48
+ parent.find( '.ip-box:last' ).after( new_ip_box ).next().slideDown( 'fast' );
49
+ } );
50
+
51
+ // add current ip
52
+ $( document ).on( 'click', '.add-current-ip', function() {
53
+ // fill input with user's current ip
54
+ $( this ).parents( '#pvc_exclude_ips' ).find( '.ip-box' ).last().find( 'input' ).val( $( this ).attr( 'data-rel' ) );
55
+ } );
56
+
57
+ // toggle user roles
58
+ $( '#pvc_exclude-roles, #pvc_restrict_display-roles' ).on( 'change', function() {
59
+ if ( $( this ).is( ':checked' ) )
60
+ $( '.pvc_user_roles' ).slideDown( 'fast' );
61
+ else
62
+ $( '.pvc_user_roles' ).slideUp( 'fast' );
63
+ } );
64
+ } );
65
+
66
+ } )( jQuery );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
js/admin-widgets.js CHANGED
@@ -1,11 +1,10 @@
1
- ( function ( $ ) {
2
-
3
- $( document ).ready( function () {
4
-
5
- $( document ).on( 'change', '.pvc-show-post-thumbnail', function () {
6
- $( this ).closest( '.widget-content' ).find( '.pvc-post-thumbnail-size' ).fadeToggle( 300 );
7
- } );
8
-
9
- } );
10
-
11
  } )( jQuery );
1
+ ( function( $ ) {
2
+
3
+ // ready event
4
+ $( function() {
5
+ $( document ).on( 'change', '.pvc-show-post-thumbnail', function() {
6
+ $( this ).closest( '.widget-content' ).find( '.pvc-post-thumbnail-size' ).fadeToggle( 300 );
7
+ } );
8
+ } );
9
+
 
10
  } )( jQuery );
js/frontend.js CHANGED
@@ -1,56 +1,51 @@
1
- ( function ( $ ) {
2
-
3
- $( document ).ready( function () {
4
-
5
- // rest api request
6
- if ( pvcArgsFrontend.mode == 'rest_api' ) {
7
-
8
- var request = {
9
- id: pvcArgsFrontend.postID
10
- };
11
-
12
- $.ajax( {
13
- url: pvcArgsFrontend.requestURL + '?id=' + pvcArgsFrontend.postID,
14
- type: 'post',
15
- async: true,
16
- cache: false,
17
- data: request,
18
- beforeSend: function ( xhr ) {
19
- xhr.setRequestHeader( 'X-WP-Nonce', pvcArgsFrontend.nonce );
20
- }
21
- } ).done( function( response ) {
22
- // trigger pvcCheckPost event
23
- $.event.trigger( {
24
- type: 'pvcCheckPost',
25
- detail: response
26
- } );
27
- } );
28
-
29
- // admin ajax or fast ajax request
30
- } else {
31
-
32
- var request = {
33
- action: 'pvc-check-post',
34
- pvc_nonce: pvcArgsFrontend.nonce,
35
- id: pvcArgsFrontend.postID
36
- };
37
-
38
- $.ajax( {
39
- url: pvcArgsFrontend.requestURL,
40
- type: 'post',
41
- async: true,
42
- cache: false,
43
- data: request
44
- } ).done( function( response ) {
45
- // trigger pvcCheckPost event
46
- $.event.trigger( {
47
- type: 'pvcCheckPost',
48
- detail: response
49
- } );
50
- } );
51
-
52
- }
53
-
54
- } );
55
-
56
  } )( jQuery );
1
+ ( function( $ ) {
2
+
3
+ // ready event
4
+ $( function() {
5
+ // rest api request
6
+ if ( pvcArgsFrontend.mode == 'rest_api' ) {
7
+ var request = {
8
+ id: pvcArgsFrontend.postID
9
+ };
10
+
11
+ $.ajax( {
12
+ url: pvcArgsFrontend.requestURL + '?id=' + pvcArgsFrontend.postID,
13
+ type: 'post',
14
+ async: true,
15
+ cache: false,
16
+ data: request,
17
+ beforeSend: function( xhr ) {
18
+ xhr.setRequestHeader( 'X-WP-Nonce', pvcArgsFrontend.nonce );
19
+ }
20
+ } ).done( function( response ) {
21
+ // trigger pvcCheckPost event
22
+ $.event.trigger( {
23
+ type: 'pvcCheckPost',
24
+ detail: response
25
+ } );
26
+ } );
27
+ // admin ajax or fast ajax request
28
+ } else {
29
+ var request = {
30
+ action: 'pvc-check-post',
31
+ pvc_nonce: pvcArgsFrontend.nonce,
32
+ id: pvcArgsFrontend.postID
33
+ };
34
+
35
+ $.ajax( {
36
+ url: pvcArgsFrontend.requestURL,
37
+ type: 'post',
38
+ async: true,
39
+ cache: false,
40
+ data: request
41
+ } ).done( function( response ) {
42
+ // trigger pvcCheckPost event
43
+ $.event.trigger( {
44
+ type: 'pvcCheckPost',
45
+ detail: response
46
+ } );
47
+ } );
48
+ }
49
+ } );
50
+
 
 
 
 
 
51
  } )( jQuery );
languages/post-views-counter.pot CHANGED
@@ -2,7 +2,7 @@
2
  msgid ""
3
  msgstr ""
4
  "Project-Id-Version: Post Views Counter\n"
5
- "POT-Creation-Date: 2019-07-10 10:32+0200\n"
6
  "PO-Revision-Date: 2015-04-08 18:59+0100\n"
7
  "Last-Translator: Bartosz Arendt <info@dfactory.eu>\n"
8
  "Language-Team: dFactory <info@dfactory.eu>\n"
@@ -10,7 +10,7 @@ msgstr ""
10
  "MIME-Version: 1.0\n"
11
  "Content-Type: text/plain; charset=UTF-8\n"
12
  "Content-Transfer-Encoding: 8bit\n"
13
- "X-Generator: Poedit 2.2.3\n"
14
  "X-Poedit-KeywordsList: gettext;gettext_noop;__;_e;esc_attr__;esc_attr_e;"
15
  "esc_html__;esc_html_e\n"
16
  "X-Poedit-Basepath: .\n"
@@ -18,44 +18,45 @@ msgstr ""
18
  "Plural-Forms: nplurals=2; plural=(n != 1);\n"
19
  "X-Poedit-SearchPath-0: ..\n"
20
 
21
- #: ../includes/columns.php:46 ../includes/columns.php:131
22
- #: ../includes/columns.php:176 ../includes/columns.php:311
23
- #: ../includes/columns.php:317 ../includes/columns.php:367
24
- #: ../includes/dashboard.php:30 ../includes/dashboard.php:102
25
- #: ../includes/dashboard.php:112 ../includes/dashboard.php:121
26
- #: ../includes/dashboard.php:197
27
  msgid "Post Views"
28
  msgstr ""
29
 
30
- #: ../includes/columns.php:86 ../includes/counter.php:218
31
- msgid "Invalid post ID."
 
32
  msgstr ""
33
 
34
- #: ../includes/columns.php:90 ../includes/columns.php:96
35
- msgid "You are not allowed to edit this item."
36
  msgstr ""
37
 
38
- #: ../includes/columns.php:132 ../includes/columns.php:189
39
  msgid "Adjust the views count for this post."
40
  msgstr ""
41
 
42
- #: ../includes/columns.php:133 ../includes/columns.php:194
43
  msgid "Cancel"
44
  msgstr ""
45
 
46
- #: ../includes/columns.php:185
47
  msgid "Edit"
48
  msgstr ""
49
 
50
- #: ../includes/columns.php:193
51
  msgid "OK"
52
  msgstr ""
53
 
54
- #: ../includes/counter.php:210
55
  msgid "REST API method is disabled."
56
  msgstr ""
57
 
58
- #: ../includes/counter.php:224
59
  msgid "Post type excluded."
60
  msgstr ""
61
 
@@ -67,103 +68,131 @@ msgstr ""
67
  msgid "Post Views Counter cache flush interval"
68
  msgstr ""
69
 
70
- #: ../includes/dashboard.php:64 ../includes/dashboard.php:67
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
71
  msgid "You do not have permission to access this page."
72
  msgstr ""
73
 
74
- #: ../includes/dashboard.php:120
 
 
 
 
 
 
 
 
75
  msgid "Year"
76
  msgstr ""
77
 
78
- #: ../includes/dashboard.php:135 ../includes/dashboard.php:211
79
  msgid "Total Views"
80
  msgstr ""
81
 
82
- #: ../includes/functions.php:348
83
  msgid "No Posts"
84
  msgstr ""
85
 
86
- #: ../includes/settings.php:41
87
  msgid "PHP"
88
  msgstr ""
89
 
90
- #: ../includes/settings.php:42
91
  msgid "JavaScript"
92
  msgstr ""
93
 
94
- #: ../includes/settings.php:43
95
  msgid "Fast AJAX"
96
  msgstr ""
97
 
98
- #: ../includes/settings.php:47
99
  msgid "REST API"
100
  msgstr ""
101
 
102
- #: ../includes/settings.php:51
103
  msgid "minutes"
104
  msgstr ""
105
 
106
- #: ../includes/settings.php:52
107
  msgid "hours"
108
  msgstr ""
109
 
110
- #: ../includes/settings.php:53
111
  msgid "days"
112
  msgstr ""
113
 
114
- #: ../includes/settings.php:54
115
  msgid "weeks"
116
  msgstr ""
117
 
118
- #: ../includes/settings.php:55
119
  msgid "months"
120
  msgstr ""
121
 
122
- #: ../includes/settings.php:56
123
  msgid "years"
124
  msgstr ""
125
 
126
- #: ../includes/settings.php:60
127
  msgid "robots"
128
  msgstr ""
129
 
130
- #: ../includes/settings.php:61
131
  msgid "logged in users"
132
  msgstr ""
133
 
134
- #: ../includes/settings.php:62
135
  msgid "guests"
136
  msgstr ""
137
 
138
- #: ../includes/settings.php:63
139
  msgid "selected user roles"
140
  msgstr ""
141
 
142
- #: ../includes/settings.php:67
143
  msgid "before the content"
144
  msgstr ""
145
 
146
- #: ../includes/settings.php:68
147
  msgid "after the content"
148
  msgstr ""
149
 
150
- #: ../includes/settings.php:69
151
  msgid "manual"
152
  msgstr ""
153
 
154
- #: ../includes/settings.php:73
155
  msgid "icon"
156
  msgstr ""
157
 
158
- #: ../includes/settings.php:74
159
  msgid "label"
160
  msgstr ""
161
 
162
- #: ../includes/settings.php:79
163
  msgid "General"
164
  msgstr ""
165
 
166
- #: ../includes/settings.php:85
167
  msgid "Display"
168
  msgstr ""
169
 
@@ -183,16 +212,11 @@ msgstr ""
183
  msgid "Search results"
184
  msgstr ""
185
 
186
- #: ../includes/settings.php:153 ../includes/settings.php:167
187
- #: ../includes/settings.php:179
188
- msgid "Post Views Counter"
189
- msgstr ""
190
-
191
- #: ../includes/settings.php:181
192
  msgid "Need support?"
193
  msgstr ""
194
 
195
- #: ../includes/settings.php:182
196
  #, php-format
197
  msgid ""
198
  "If you are having problems with this plugin, please browse it's <a href=\"%s"
@@ -200,164 +224,160 @@ msgid ""
200
  "\" target=\"_blank\">Support forum</a>"
201
  msgstr ""
202
 
203
- #: ../includes/settings.php:184
204
  msgid "Do you like this plugin?"
205
  msgstr ""
206
 
207
- #: ../includes/settings.php:185
208
  #, php-format
209
  msgid "<a href=\"%s\" target=\"_blank\">Rate it 5</a> on WordPress.org"
210
  msgstr ""
211
 
212
- #: ../includes/settings.php:186
213
  #, php-format
214
  msgid ""
215
  "Blog about it & link to the <a href=\"%s\" target=\"_blank\">plugin page</a>."
216
  msgstr ""
217
 
218
- #: ../includes/settings.php:187
219
  #, php-format
220
  msgid ""
221
  "Check out our other <a href=\"%s\" target=\"_blank\">WordPress plugins</a>."
222
  msgstr ""
223
 
224
- #: ../includes/settings.php:190
225
- msgid "Created by"
226
- msgstr ""
227
-
228
- #: ../includes/settings.php:206
229
  msgid "Reset to defaults"
230
  msgstr ""
231
 
232
- #: ../includes/settings.php:222
233
  msgid "General settings"
234
  msgstr ""
235
 
236
- #: ../includes/settings.php:223
237
  msgid "Post Types Count"
238
  msgstr ""
239
 
240
- #: ../includes/settings.php:224
241
  msgid "Counter Mode"
242
  msgstr ""
243
 
244
- #: ../includes/settings.php:225
245
  msgid "Post Views Column"
246
  msgstr ""
247
 
248
- #: ../includes/settings.php:226
249
  msgid "Restrict Edit"
250
  msgstr ""
251
 
252
- #: ../includes/settings.php:227
253
  msgid "Count Interval"
254
  msgstr ""
255
 
256
- #: ../includes/settings.php:228
257
  msgid "Reset Data Interval"
258
  msgstr ""
259
 
260
- #: ../includes/settings.php:229
261
  msgid "Flush Object Cache Interval"
262
  msgstr ""
263
 
264
- #: ../includes/settings.php:230
265
  msgid "Exclude Visitors"
266
  msgstr ""
267
 
268
- #: ../includes/settings.php:231
269
  msgid "Exclude IPs"
270
  msgstr ""
271
 
272
- #: ../includes/settings.php:232
273
  msgid "Strict counts"
274
  msgstr ""
275
 
276
- #: ../includes/settings.php:233
277
  msgid "Tools"
278
  msgstr ""
279
 
280
- #: ../includes/settings.php:234
281
  msgid "Deactivation"
282
  msgstr ""
283
 
284
- #: ../includes/settings.php:238
285
  msgid "Display settings"
286
  msgstr ""
287
 
288
- #: ../includes/settings.php:239
289
  msgid "Post Views Label"
290
  msgstr ""
291
 
292
- #: ../includes/settings.php:240
293
  msgid "Post Type"
294
  msgstr ""
295
 
296
- #: ../includes/settings.php:241
297
  msgid "Page Type"
298
  msgstr ""
299
 
300
- #: ../includes/settings.php:242
301
  msgid "User Type"
302
  msgstr ""
303
 
304
- #: ../includes/settings.php:243
305
  msgid "Position"
306
  msgstr ""
307
 
308
- #: ../includes/settings.php:244 ../includes/widgets.php:150
309
  msgid "Display Style"
310
  msgstr ""
311
 
312
- #: ../includes/settings.php:245
313
  msgid "Icon Class"
314
  msgstr ""
315
 
316
- #: ../includes/settings.php:256
317
  msgid "Enter the label for the post views counter field."
318
  msgstr ""
319
 
320
- #: ../includes/settings.php:274
321
  msgid "Select post types for which post views will be counted."
322
  msgstr ""
323
 
324
- #: ../includes/settings.php:291
325
  msgid "Select post types for which the views count will be displayed."
326
  msgstr ""
327
 
328
- #: ../includes/settings.php:310
329
  msgid ""
330
  "Select the method of collecting post views data. If you are using any of the "
331
  "caching plugins select Javascript or REST API (if available)."
332
  msgstr ""
333
 
334
- #: ../includes/settings.php:310
335
  msgid ""
336
  "Optionally try the Fast AJAX experimental method, usually 10+ times faster "
337
  "than Javascript or REST API."
338
  msgstr ""
339
 
340
- #: ../includes/settings.php:320
341
  msgid ""
342
  "Enable to display post views count column for each of the selected post "
343
  "types."
344
  msgstr ""
345
 
346
- #: ../includes/settings.php:340
347
  msgid "Enter the time between single user visit count."
348
  msgstr ""
349
 
350
- #: ../includes/settings.php:360
351
  msgid ""
352
  "Delete single day post views data older than specified above. Enter 0 "
353
  "(number zero) if you want to preserve your data regardless of its age."
354
  msgstr ""
355
 
356
- #: ../includes/settings.php:380
357
  msgid ""
358
  "How often to flush cached view counts from the object cache into the "
359
  "database. This feature is used only if a persistent object cache is detected "
360
- "and the interval is greater than 0 (number zero)). When used, view counts "
361
  "will be collected and stored in the object cache instead of the database and "
362
  "will then be asynchronously flushed to the database according to the "
363
  "specified interval.<br /><strong>Notice:</strong> Potential data loss may "
@@ -365,106 +385,106 @@ msgid ""
365
  "interval."
366
  msgstr ""
367
 
368
- #: ../includes/settings.php:398 ../includes/settings.php:571
369
  msgid "Use it to hide the post views counter from selected type of visitors."
370
  msgstr ""
371
 
372
- #: ../includes/settings.php:406 ../includes/settings.php:580
373
  msgid "Use it to hide the post views counter from selected user roles."
374
  msgstr ""
375
 
376
- #: ../includes/settings.php:426 ../includes/settings.php:432
377
  msgid "Remove"
378
  msgstr ""
379
 
380
- #: ../includes/settings.php:437
381
  msgid "Add new"
382
  msgstr ""
383
 
384
- #: ../includes/settings.php:437
385
  msgid "Add my current IP"
386
  msgstr ""
387
 
388
- #: ../includes/settings.php:438
389
  msgid "Enter the IP addresses to be excluded from post views count."
390
  msgstr ""
391
 
392
- #: ../includes/settings.php:448
393
  msgid ""
394
  "Enable to prevent bypassing the counts interval (for e.g. using incognito "
395
  "browser window or by clearing cookies)."
396
  msgstr ""
397
 
398
- #: ../includes/settings.php:459
399
  msgid "Import views"
400
  msgstr ""
401
 
402
- #: ../includes/settings.php:459
403
  msgid "Override existing views data."
404
  msgstr ""
405
 
406
- #: ../includes/settings.php:460
407
  msgid "Import post views data from WP-PostViews plugin."
408
  msgstr ""
409
 
410
- #: ../includes/settings.php:461
411
  msgid "Delete views"
412
  msgstr ""
413
 
414
- #: ../includes/settings.php:462
415
  msgid "Delete ALL the existing post views data."
416
  msgstr ""
417
 
418
- #: ../includes/settings.php:473
419
  msgid "Enable to restrict post views editing to admins only."
420
  msgstr ""
421
 
422
- #: ../includes/settings.php:483
423
  msgid "Enable to delete all plugin data on deactivation."
424
  msgstr ""
425
 
426
- #: ../includes/settings.php:500
427
  msgid "Select page types where the views count will be displayed."
428
  msgstr ""
429
 
430
- #: ../includes/settings.php:519
431
  msgid ""
432
  "Select where would you like to display the post views counter. Use [post-"
433
  "views] shortcode for manual display."
434
  msgstr ""
435
 
436
- #: ../includes/settings.php:538
437
  msgid "Choose how to display the post views counter."
438
  msgstr ""
439
 
440
- #: ../includes/settings.php:549
441
  #, php-format
442
  msgid ""
443
  "Enter the post views icon class. Any of the <a href=\"%s\" target=\"_blank"
444
  "\">Dashicons</a> classes are available."
445
  msgstr ""
446
 
447
- #: ../includes/settings.php:609
448
  msgid "Post views data imported succesfully."
449
  msgstr ""
450
 
451
- #: ../includes/settings.php:611
452
  msgid "There was no post views data to import."
453
  msgstr ""
454
 
455
- #: ../includes/settings.php:617
456
  msgid "All existing data deleted succesfully."
457
  msgstr ""
458
 
459
- #: ../includes/settings.php:619
460
  msgid "Error occurred. All existing data were not deleted."
461
  msgstr ""
462
 
463
- #: ../includes/settings.php:795
464
  msgid "General settings restored to defaults."
465
  msgstr ""
466
 
467
- #: ../includes/settings.php:799
468
  msgid "Display settings restored to defaults."
469
  msgstr ""
470
 
@@ -490,10 +510,6 @@ msgstr ""
490
  msgid "Displays a list of the most viewed posts"
491
  msgstr ""
492
 
493
- #: ../includes/widgets.php:58
494
- msgid "No Posts found"
495
- msgstr ""
496
-
497
  #: ../includes/widgets.php:62
498
  msgid "Ascending"
499
  msgstr ""
@@ -550,18 +566,49 @@ msgstr ""
550
  msgid "Thumbnail size"
551
  msgstr ""
552
 
553
- #: ../post-views-counter.php:387
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
554
  msgid "Are you sure you want to reset these settings to defaults?"
555
  msgstr ""
556
 
557
- #: ../post-views-counter.php:388
558
  msgid "Are you sure you want to delete all existing data?"
559
  msgstr ""
560
 
561
- #: ../post-views-counter.php:437
562
  msgid "Support"
563
  msgstr ""
564
 
565
- #: ../post-views-counter.php:461
566
  msgid "Settings"
567
  msgstr ""
2
  msgid ""
3
  msgstr ""
4
  "Project-Id-Version: Post Views Counter\n"
5
+ "POT-Creation-Date: 2021-03-11 16:50+0100\n"
6
  "PO-Revision-Date: 2015-04-08 18:59+0100\n"
7
  "Last-Translator: Bartosz Arendt <info@dfactory.eu>\n"
8
  "Language-Team: dFactory <info@dfactory.eu>\n"
10
  "MIME-Version: 1.0\n"
11
  "Content-Type: text/plain; charset=UTF-8\n"
12
  "Content-Transfer-Encoding: 8bit\n"
13
+ "X-Generator: Poedit 2.4.2\n"
14
  "X-Poedit-KeywordsList: gettext;gettext_noop;__;_e;esc_attr__;esc_attr_e;"
15
  "esc_html__;esc_html_e\n"
16
  "X-Poedit-Basepath: .\n"
18
  "Plural-Forms: nplurals=2; plural=(n != 1);\n"
19
  "X-Poedit-SearchPath-0: ..\n"
20
 
21
+ #: ../includes/columns.php:51 ../includes/columns.php:154
22
+ #: ../includes/columns.php:197 ../includes/columns.php:348
23
+ #: ../includes/columns.php:354 ../includes/columns.php:404
24
+ #: ../includes/dashboard.php:60 ../includes/dashboard.php:252
25
+ #: ../includes/dashboard.php:347 ../includes/dashboard.php:356
26
+ #: ../includes/dashboard.php:365 ../includes/dashboard.php:451
27
  msgid "Post Views"
28
  msgstr ""
29
 
30
+ #: ../includes/columns.php:87 ../includes/columns.php:91
31
+ #: ../includes/columns.php:118 ../includes/columns.php:122
32
+ msgid "You are not allowed to edit this item."
33
  msgstr ""
34
 
35
+ #: ../includes/columns.php:114 ../includes/counter.php:220
36
+ msgid "Invalid post ID."
37
  msgstr ""
38
 
39
+ #: ../includes/columns.php:155 ../includes/columns.php:210
40
  msgid "Adjust the views count for this post."
41
  msgstr ""
42
 
43
+ #: ../includes/columns.php:156 ../includes/columns.php:215
44
  msgid "Cancel"
45
  msgstr ""
46
 
47
+ #: ../includes/columns.php:206
48
  msgid "Edit"
49
  msgstr ""
50
 
51
+ #: ../includes/columns.php:214
52
  msgid "OK"
53
  msgstr ""
54
 
55
+ #: ../includes/counter.php:212
56
  msgid "REST API method is disabled."
57
  msgstr ""
58
 
59
+ #: ../includes/counter.php:226
60
  msgid "Post type excluded."
61
  msgstr ""
62
 
68
  msgid "Post Views Counter cache flush interval"
69
  msgstr ""
70
 
71
+ #: ../includes/dashboard.php:32 ../includes/settings.php:160
72
+ #: ../includes/settings.php:173 ../includes/settings.php:185
73
+ msgid "Post Views Counter"
74
+ msgstr ""
75
+
76
+ #: ../includes/dashboard.php:60
77
+ msgid ""
78
+ "Displays the chart of most viewed post types for a selected time period."
79
+ msgstr ""
80
+
81
+ #: ../includes/dashboard.php:79
82
+ msgid "Top Posts"
83
+ msgstr ""
84
+
85
+ #: ../includes/dashboard.php:79
86
+ msgid "Displays the list of most viewed posts and pages on your website."
87
+ msgstr ""
88
+
89
+ #: ../includes/dashboard.php:136 ../includes/dashboard.php:207
90
+ #: ../includes/dashboard.php:210 ../includes/dashboard.php:296
91
+ #: ../includes/dashboard.php:299
92
  msgid "You do not have permission to access this page."
93
  msgstr ""
94
 
95
+ #: ../includes/dashboard.php:251
96
+ msgid "Post"
97
+ msgstr ""
98
+
99
+ #: ../includes/dashboard.php:275 ../includes/widgets.php:58
100
+ msgid "No most viewed posts found"
101
+ msgstr ""
102
+
103
+ #: ../includes/dashboard.php:364
104
  msgid "Year"
105
  msgstr ""
106
 
107
+ #: ../includes/dashboard.php:379 ../includes/dashboard.php:465
108
  msgid "Total Views"
109
  msgstr ""
110
 
111
+ #: ../includes/functions.php:476
112
  msgid "No Posts"
113
  msgstr ""
114
 
115
+ #: ../includes/settings.php:40
116
  msgid "PHP"
117
  msgstr ""
118
 
119
+ #: ../includes/settings.php:41
120
  msgid "JavaScript"
121
  msgstr ""
122
 
123
+ #: ../includes/settings.php:42
124
  msgid "Fast AJAX"
125
  msgstr ""
126
 
127
+ #: ../includes/settings.php:46
128
  msgid "REST API"
129
  msgstr ""
130
 
131
+ #: ../includes/settings.php:49
132
  msgid "minutes"
133
  msgstr ""
134
 
135
+ #: ../includes/settings.php:50
136
  msgid "hours"
137
  msgstr ""
138
 
139
+ #: ../includes/settings.php:51
140
  msgid "days"
141
  msgstr ""
142
 
143
+ #: ../includes/settings.php:52
144
  msgid "weeks"
145
  msgstr ""
146
 
147
+ #: ../includes/settings.php:53
148
  msgid "months"
149
  msgstr ""
150
 
151
+ #: ../includes/settings.php:54
152
  msgid "years"
153
  msgstr ""
154
 
155
+ #: ../includes/settings.php:58
156
  msgid "robots"
157
  msgstr ""
158
 
159
+ #: ../includes/settings.php:59
160
  msgid "logged in users"
161
  msgstr ""
162
 
163
+ #: ../includes/settings.php:60
164
  msgid "guests"
165
  msgstr ""
166
 
167
+ #: ../includes/settings.php:61
168
  msgid "selected user roles"
169
  msgstr ""
170
 
171
+ #: ../includes/settings.php:65
172
  msgid "before the content"
173
  msgstr ""
174
 
175
+ #: ../includes/settings.php:66
176
  msgid "after the content"
177
  msgstr ""
178
 
179
+ #: ../includes/settings.php:67
180
  msgid "manual"
181
  msgstr ""
182
 
183
+ #: ../includes/settings.php:71
184
  msgid "icon"
185
  msgstr ""
186
 
187
+ #: ../includes/settings.php:72
188
  msgid "label"
189
  msgstr ""
190
 
191
+ #: ../includes/settings.php:77
192
  msgid "General"
193
  msgstr ""
194
 
195
+ #: ../includes/settings.php:83
196
  msgid "Display"
197
  msgstr ""
198
 
212
  msgid "Search results"
213
  msgstr ""
214
 
215
+ #: ../includes/settings.php:187
 
 
 
 
 
216
  msgid "Need support?"
217
  msgstr ""
218
 
219
+ #: ../includes/settings.php:188
220
  #, php-format
221
  msgid ""
222
  "If you are having problems with this plugin, please browse it's <a href=\"%s"
224
  "\" target=\"_blank\">Support forum</a>"
225
  msgstr ""
226
 
227
+ #: ../includes/settings.php:190
228
  msgid "Do you like this plugin?"
229
  msgstr ""
230
 
231
+ #: ../includes/settings.php:191
232
  #, php-format
233
  msgid "<a href=\"%s\" target=\"_blank\">Rate it 5</a> on WordPress.org"
234
  msgstr ""
235
 
236
+ #: ../includes/settings.php:192
237
  #, php-format
238
  msgid ""
239
  "Blog about it & link to the <a href=\"%s\" target=\"_blank\">plugin page</a>."
240
  msgstr ""
241
 
242
+ #: ../includes/settings.php:193
243
  #, php-format
244
  msgid ""
245
  "Check out our other <a href=\"%s\" target=\"_blank\">WordPress plugins</a>."
246
  msgstr ""
247
 
248
+ #: ../includes/settings.php:212
 
 
 
 
249
  msgid "Reset to defaults"
250
  msgstr ""
251
 
252
+ #: ../includes/settings.php:228
253
  msgid "General settings"
254
  msgstr ""
255
 
256
+ #: ../includes/settings.php:229
257
  msgid "Post Types Count"
258
  msgstr ""
259
 
260
+ #: ../includes/settings.php:230
261
  msgid "Counter Mode"
262
  msgstr ""
263
 
264
+ #: ../includes/settings.php:231
265
  msgid "Post Views Column"
266
  msgstr ""
267
 
268
+ #: ../includes/settings.php:232
269
  msgid "Restrict Edit"
270
  msgstr ""
271
 
272
+ #: ../includes/settings.php:233
273
  msgid "Count Interval"
274
  msgstr ""
275
 
276
+ #: ../includes/settings.php:234
277
  msgid "Reset Data Interval"
278
  msgstr ""
279
 
280
+ #: ../includes/settings.php:235
281
  msgid "Flush Object Cache Interval"
282
  msgstr ""
283
 
284
+ #: ../includes/settings.php:236
285
  msgid "Exclude Visitors"
286
  msgstr ""
287
 
288
+ #: ../includes/settings.php:237
289
  msgid "Exclude IPs"
290
  msgstr ""
291
 
292
+ #: ../includes/settings.php:238
293
  msgid "Strict counts"
294
  msgstr ""
295
 
296
+ #: ../includes/settings.php:239
297
  msgid "Tools"
298
  msgstr ""
299
 
300
+ #: ../includes/settings.php:240
301
  msgid "Deactivation"
302
  msgstr ""
303
 
304
+ #: ../includes/settings.php:244
305
  msgid "Display settings"
306
  msgstr ""
307
 
308
+ #: ../includes/settings.php:245
309
  msgid "Post Views Label"
310
  msgstr ""
311
 
312
+ #: ../includes/settings.php:246
313
  msgid "Post Type"
314
  msgstr ""
315
 
316
+ #: ../includes/settings.php:247
317
  msgid "Page Type"
318
  msgstr ""
319
 
320
+ #: ../includes/settings.php:248
321
  msgid "User Type"
322
  msgstr ""
323
 
324
+ #: ../includes/settings.php:249
325
  msgid "Position"
326
  msgstr ""
327
 
328
+ #: ../includes/settings.php:250 ../includes/widgets.php:150
329
  msgid "Display Style"
330
  msgstr ""
331
 
332
+ #: ../includes/settings.php:251
333
  msgid "Icon Class"
334
  msgstr ""
335
 
336
+ #: ../includes/settings.php:262
337
  msgid "Enter the label for the post views counter field."
338
  msgstr ""
339
 
340
+ #: ../includes/settings.php:280
341
  msgid "Select post types for which post views will be counted."
342
  msgstr ""
343
 
344
+ #: ../includes/settings.php:297
345
  msgid "Select post types for which the views count will be displayed."
346
  msgstr ""
347
 
348
+ #: ../includes/settings.php:316
349
  msgid ""
350
  "Select the method of collecting post views data. If you are using any of the "
351
  "caching plugins select Javascript or REST API (if available)."
352
  msgstr ""
353
 
354
+ #: ../includes/settings.php:316
355
  msgid ""
356
  "Optionally try the Fast AJAX experimental method, usually 10+ times faster "
357
  "than Javascript or REST API."
358
  msgstr ""
359
 
360
+ #: ../includes/settings.php:326
361
  msgid ""
362
  "Enable to display post views count column for each of the selected post "
363
  "types."
364
  msgstr ""
365
 
366
+ #: ../includes/settings.php:346
367
  msgid "Enter the time between single user visit count."
368
  msgstr ""
369
 
370
+ #: ../includes/settings.php:366
371
  msgid ""
372
  "Delete single day post views data older than specified above. Enter 0 "
373
  "(number zero) if you want to preserve your data regardless of its age."
374
  msgstr ""
375
 
376
+ #: ../includes/settings.php:386
377
  msgid ""
378
  "How often to flush cached view counts from the object cache into the "
379
  "database. This feature is used only if a persistent object cache is detected "
380
+ "and the interval is greater than 0 (number zero). When used, view counts "
381
  "will be collected and stored in the object cache instead of the database and "
382
  "will then be asynchronously flushed to the database according to the "
383
  "specified interval.<br /><strong>Notice:</strong> Potential data loss may "
385
  "interval."
386
  msgstr ""
387
 
388
+ #: ../includes/settings.php:404 ../includes/settings.php:577
389
  msgid "Use it to hide the post views counter from selected type of visitors."
390
  msgstr ""
391
 
392
+ #: ../includes/settings.php:412 ../includes/settings.php:586
393
  msgid "Use it to hide the post views counter from selected user roles."
394
  msgstr ""
395
 
396
+ #: ../includes/settings.php:432 ../includes/settings.php:438
397
  msgid "Remove"
398
  msgstr ""
399
 
400
+ #: ../includes/settings.php:443
401
  msgid "Add new"
402
  msgstr ""
403
 
404
+ #: ../includes/settings.php:443
405
  msgid "Add my current IP"
406
  msgstr ""
407
 
408
+ #: ../includes/settings.php:444
409
  msgid "Enter the IP addresses to be excluded from post views count."
410
  msgstr ""
411
 
412
+ #: ../includes/settings.php:454
413
  msgid ""
414
  "Enable to prevent bypassing the counts interval (for e.g. using incognito "
415
  "browser window or by clearing cookies)."
416
  msgstr ""
417
 
418
+ #: ../includes/settings.php:465
419
  msgid "Import views"
420
  msgstr ""
421
 
422
+ #: ../includes/settings.php:465
423
  msgid "Override existing views data."
424
  msgstr ""
425
 
426
+ #: ../includes/settings.php:466
427
  msgid "Import post views data from WP-PostViews plugin."
428
  msgstr ""
429
 
430
+ #: ../includes/settings.php:467
431
  msgid "Delete views"
432
  msgstr ""
433
 
434
+ #: ../includes/settings.php:468
435
  msgid "Delete ALL the existing post views data."
436
  msgstr ""
437
 
438
+ #: ../includes/settings.php:479
439
  msgid "Enable to restrict post views editing to admins only."
440
  msgstr ""
441
 
442
+ #: ../includes/settings.php:489
443
  msgid "Enable to delete all plugin data on deactivation."
444
  msgstr ""
445
 
446
+ #: ../includes/settings.php:506
447
  msgid "Select page types where the views count will be displayed."
448
  msgstr ""
449
 
450
+ #: ../includes/settings.php:525
451
  msgid ""
452
  "Select where would you like to display the post views counter. Use [post-"
453
  "views] shortcode for manual display."
454
  msgstr ""
455
 
456
+ #: ../includes/settings.php:544
457
  msgid "Choose how to display the post views counter."
458
  msgstr ""
459
 
460
+ #: ../includes/settings.php:555
461
  #, php-format
462
  msgid ""
463
  "Enter the post views icon class. Any of the <a href=\"%s\" target=\"_blank"
464
  "\">Dashicons</a> classes are available."
465
  msgstr ""
466
 
467
+ #: ../includes/settings.php:618
468
  msgid "Post views data imported succesfully."
469
  msgstr ""
470
 
471
+ #: ../includes/settings.php:620
472
  msgid "There was no post views data to import."
473
  msgstr ""
474
 
475
+ #: ../includes/settings.php:626
476
  msgid "All existing data deleted succesfully."
477
  msgstr ""
478
 
479
+ #: ../includes/settings.php:628
480
  msgid "Error occurred. All existing data were not deleted."
481
  msgstr ""
482
 
483
+ #: ../includes/settings.php:807
484
  msgid "General settings restored to defaults."
485
  msgstr ""
486
 
487
+ #: ../includes/settings.php:811
488
  msgid "Display settings restored to defaults."
489
  msgstr ""
490
 
510
  msgid "Displays a list of the most viewed posts"
511
  msgstr ""
512
 
 
 
 
 
513
  #: ../includes/widgets.php:62
514
  msgid "Ascending"
515
  msgstr ""
566
  msgid "Thumbnail size"
567
  msgstr ""
568
 
569
+ #: ../post-views-counter.php:252
570
+ #, php-format
571
+ msgid ""
572
+ "Hey, you've been using <strong>Post Views Counter</strong> for more than %s."
573
+ msgstr ""
574
+
575
+ #: ../post-views-counter.php:252
576
+ msgid ""
577
+ "Could you please do me a BIG favor and give it a 5-star rating on WordPress "
578
+ "to help us spread the word and boost our motivation."
579
+ msgstr ""
580
+
581
+ #: ../post-views-counter.php:252
582
+ msgid "Your help is much appreciated. Thank you very much"
583
+ msgstr ""
584
+
585
+ #: ../post-views-counter.php:252
586
+ #, php-format
587
+ msgid "founder of <a href=\"%s\" target=\"_blank\">dFactory</a> plugins."
588
+ msgstr ""
589
+
590
+ #: ../post-views-counter.php:252
591
+ #, php-format
592
+ msgid ""
593
+ "<a href=\"%s\" class=\"pvc-dismissible-notice\" target=\"_blank\" rel="
594
+ "\"noopener\">Ok, you deserve it</a><br /><a href=\"javascript:void(0);\" "
595
+ "class=\"pvc-dismissible-notice pvc-delay-notice\" rel=\"noopener\">Nope, "
596
+ "maybe later</a><br /><a href=\"javascript:void(0);\" class=\"pvc-dismissible-"
597
+ "notice\" rel=\"noopener\">I already did</a>"
598
+ msgstr ""
599
+
600
+ #: ../post-views-counter.php:534
601
  msgid "Are you sure you want to reset these settings to defaults?"
602
  msgstr ""
603
 
604
+ #: ../post-views-counter.php:535
605
  msgid "Are you sure you want to delete all existing data?"
606
  msgstr ""
607
 
608
+ #: ../post-views-counter.php:589
609
  msgid "Support"
610
  msgstr ""
611
 
612
+ #: ../post-views-counter.php:613
613
  msgid "Settings"
614
  msgstr ""
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.3
6
  Author: Digital Factory
7
  Author URI: http://www.dfactory.eu/
8
  Plugin URI: http://www.dfactory.eu/plugins/post-views-counter/
@@ -12,7 +12,7 @@ Text Domain: post-views-counter
12
  Domain Path: /languages
13
 
14
  Post Views Counter
15
- Copyright (C) 2014-2020, Digital Factory - info@digitalfactory.pl
16
 
17
  Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
18
 
@@ -31,7 +31,7 @@ if ( ! class_exists( 'Post_Views_Counter' ) ) :
31
  * Post Views Counter final class.
32
  *
33
  * @class Post_Views_Counter
34
- * @version 1.3.3
35
  */
36
  final class Post_Views_Counter {
37
 
@@ -84,18 +84,18 @@ if ( ! class_exists( 'Post_Views_Counter' ) ) :
84
  'link_to_post' => true,
85
  'icon_class' => 'dashicons-chart-bar'
86
  ),
87
- 'version' => '1.3.3'
88
  );
89
 
90
  /**
91
- * Disable object clone.
92
  */
93
- private function __clone() {}
94
 
95
  /**
96
  * Disable unserializing of the class.
97
  */
98
- private function __wakeup() {}
99
 
100
  /**
101
  * Main plugin instance,
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.4
6
  Author: Digital Factory
7
  Author URI: http://www.dfactory.eu/
8
  Plugin URI: http://www.dfactory.eu/plugins/post-views-counter/
12
  Domain Path: /languages
13
 
14
  Post Views Counter
15
+ Copyright (C) 2014-2021, Digital Factory - info@digitalfactory.pl
16
 
17
  Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
18
 
31
  * Post Views Counter final class.
32
  *
33
  * @class Post_Views_Counter
34
+ * @version 1.3.4
35
  */
36
  final class Post_Views_Counter {
37
 
84
  'link_to_post' => true,
85
  'icon_class' => 'dashicons-chart-bar'
86
  ),
87
+ 'version' => '1.3.4'
88
  );
89
 
90
  /**
91
+ * Disable object cloning.
92
  */
93
+ public function __clone() {}
94
 
95
  /**
96
  * Disable unserializing of the class.
97
  */
98
+ public function __wakeup() {}
99
 
100
  /**
101
  * Main plugin instance,
readme.txt CHANGED
@@ -2,10 +2,10 @@
2
  Contributors: dfactory
3
  Donate link: http://dfactory.eu/
4
  Tags: counter, hits, posts, postviews, post views, views, count, statistics, stats, analytics, pageviews, tracking
5
- Requires at least: 4.0
6
  Requires PHP: 5.2.4
7
- Tested up to: 5.5.3
8
- Stable tag: 1.3.3
9
  License: MIT License
10
  License URI: http://opensource.org/licenses/MIT
11
 
@@ -21,7 +21,7 @@ For more information, check out plugin page at [dFactory](http://dfactory.eu/) o
21
 
22
  * Option to select post types for which post views will be counted and displayed.
23
  * 4 methods of collecting post views data: PHP, Javascript, Fast AJAX and REST API for greater flexibility
24
- * GDPR compatibility with [Cookie Notice](https://wordpress.org/plugins/cookie-notice/) plugin
25
  * Possibility to manually set views count for each post
26
  * Dashboard post views stats widget
27
  * Capability to query posts according to its views count
@@ -62,6 +62,12 @@ No questions yet.
62
 
63
  == Changelog ==
64
 
 
 
 
 
 
 
65
  = 1.3.3 =
66
  * Fix: PHP Notice: Trying to get property 'colors' of non-object
67
  * Fix: PHP Notice: register_rest_route was called incorrectly
@@ -205,6 +211,8 @@ Initial release
205
 
206
  == Upgrade Notice ==
207
 
208
- = 1.3.3 =
209
- * Fix: PHP Notice: Trying to get property 'colors' of non-object
210
- * Fix: PHP Notice: register_rest_route was called incorrectly
 
 
2
  Contributors: dfactory
3
  Donate link: http://dfactory.eu/
4
  Tags: counter, hits, posts, postviews, post views, views, count, statistics, stats, analytics, pageviews, tracking
5
+ Requires at least: 5.0
6
  Requires PHP: 5.2.4
7
+ Tested up to: 5.7
8
+ Stable tag: 1.3.4
9
  License: MIT License
10
  License URI: http://opensource.org/licenses/MIT
11
 
21
 
22
  * Option to select post types for which post views will be counted and displayed.
23
  * 4 methods of collecting post views data: PHP, Javascript, Fast AJAX and REST API for greater flexibility
24
+ * Compatible with data privacy regulations
25
  * Possibility to manually set views count for each post
26
  * Dashboard post views stats widget
27
  * Capability to query posts according to its views count
62
 
63
  == Changelog ==
64
 
65
+ = 1.3.4 =
66
+ * New: Post Views stats preview in the admin bar
67
+ * New: Top Posts data available in the dashboard widget
68
+ * Tweak: Improved privacy using IP encrypting
69
+ * Tweak: PHP 8.x compatibility
70
+
71
  = 1.3.3 =
72
  * Fix: PHP Notice: Trying to get property 'colors' of non-object
73
  * Fix: PHP Notice: register_rest_route was called incorrectly
211
 
212
  == Upgrade Notice ==
213
 
214
+ = 1.3.4 =
215
+ * New: Post Views stats preview in the admin bar
216
+ * New: Top Posts data available in the dashboard widget
217
+ * Tweak: Improved privacy using IP encrypting
218
+ * Tweak: PHP 8.x compatibility