Post Expirator - Version 2.5.0

Version Description

Download this release

Release Info

Developer publishpress
Plugin Icon 128x128 Post Expirator
Version 2.5.0
Comparing to
See all releases

Code changes from version 2.4.4 to 2.5.0

Files changed (50) hide show
  1. assets/css/edit.css +15 -2
  2. assets/css/lib/jquery-ui/images/ui-bg_glass_55_fbf9ee_1x400.png +0 -0
  3. assets/css/lib/jquery-ui/images/ui-bg_glass_65_ffffff_1x400.png +0 -0
  4. assets/css/lib/jquery-ui/images/ui-bg_glass_75_dadada_1x400.png +0 -0
  5. assets/css/lib/jquery-ui/images/ui-bg_glass_75_e6e6e6_1x400.png +0 -0
  6. assets/css/lib/jquery-ui/images/ui-bg_glass_95_fef1ec_1x400.png +0 -0
  7. assets/css/lib/jquery-ui/images/ui-bg_highlight-soft_75_cccccc_1x100.png +0 -0
  8. assets/css/lib/jquery-ui/images/ui-icons_222222_256x240.png +0 -0
  9. assets/css/lib/jquery-ui/images/ui-icons_2e83ff_256x240.png +0 -0
  10. assets/css/lib/jquery-ui/images/ui-icons_454545_256x240.png +0 -0
  11. assets/css/lib/jquery-ui/images/ui-icons_888888_256x240.png +0 -0
  12. assets/css/lib/jquery-ui/images/ui-icons_cd0a0a_256x240.png +0 -0
  13. assets/css/lib/jquery-ui/jquery-ui.css +1311 -0
  14. assets/css/lib/jquery-ui/jquery-ui.min.css +7 -0
  15. assets/css/lib/jquery-ui/theme.css +443 -0
  16. assets/css/settings.css +27 -0
  17. admin-edit.js → assets/js/admin-edit.js +69 -4
  18. assets/js/block.js +2 -0
  19. assets/js/block.js.map +1 -0
  20. assets/js/settings.js +15 -0
  21. assets/jsx/block.jsx +264 -0
  22. classes/Display.class.php +258 -0
  23. classes/Facade.class.php +372 -0
  24. classes/Util.class.php +51 -0
  25. composer.json +39 -0
  26. composer.lock +2454 -0
  27. languages/post-expirator.pot +316 -281
  28. legacy-functions.php +63 -61
  29. post-expirator-debug.php +87 -87
  30. post-expirator.php +1674 -2253
  31. readme.txt +346 -359
  32. vendor/autoload.php +7 -0
  33. vendor/composer/ClassLoader.php +445 -0
  34. vendor/composer/InstalledVersions.php +219 -0
  35. vendor/composer/LICENSE +21 -0
  36. vendor/composer/autoload_classmap.php +10 -0
  37. vendor/composer/autoload_namespaces.php +9 -0
  38. vendor/composer/autoload_psr4.php +9 -0
  39. vendor/composer/autoload_real.php +55 -0
  40. vendor/composer/autoload_static.php +20 -0
  41. vendor/composer/installed.json +5 -0
  42. vendor/composer/installed.php +24 -0
  43. views/bulk-edit.php +96 -0
  44. views/expire-column.php +55 -0
  45. views/how-to-expire.php +42 -0
  46. views/menu-defaults.php +131 -0
  47. views/menu-diagnostics.php +89 -0
  48. views/menu-general.php +194 -0
  49. views/quick-edit.php +74 -0
  50. views/tabs.php +20 -0
assets/css/edit.css CHANGED
@@ -1,11 +1,24 @@
1
- div.timestamp-wrap label {
 
 
 
 
2
  vertical-align: middle !important;
3
  }
4
 
5
- div.timestamp-wrap > span.post-expirator-date-fields {
 
6
  display: none;
7
  }
8
 
 
 
 
 
 
 
 
 
9
  .post-expirator-quickedit input {
10
  font-size: 12px;
11
  }
1
+ div.pe-qe-fields {
2
+ padding: .2em .5em;
3
+ }
4
+
5
+ div.pe-qe-fields label {
6
  vertical-align: middle !important;
7
  }
8
 
9
+ div.pe-qe-fields .post-expirator-date-fields,
10
+ div.pe-qe-fields > .pe-category-list {
11
  display: none;
12
  }
13
 
14
+ div.pe-qe-fields > div {
15
+ margin: 5px 0px;
16
+ }
17
+
18
+ #bulk-edit div.pe-qe-fields > .pe-category-list {
19
+ max-width: 25%;
20
+ }
21
+
22
  .post-expirator-quickedit input {
23
  font-size: 12px;
24
  }
assets/css/lib/jquery-ui/images/ui-bg_glass_55_fbf9ee_1x400.png ADDED
Binary file
assets/css/lib/jquery-ui/images/ui-bg_glass_65_ffffff_1x400.png ADDED
Binary file
assets/css/lib/jquery-ui/images/ui-bg_glass_75_dadada_1x400.png ADDED
Binary file
assets/css/lib/jquery-ui/images/ui-bg_glass_75_e6e6e6_1x400.png ADDED
Binary file
assets/css/lib/jquery-ui/images/ui-bg_glass_95_fef1ec_1x400.png ADDED
Binary file
assets/css/lib/jquery-ui/images/ui-bg_highlight-soft_75_cccccc_1x100.png ADDED
Binary file
assets/css/lib/jquery-ui/images/ui-icons_222222_256x240.png ADDED
Binary file
assets/css/lib/jquery-ui/images/ui-icons_2e83ff_256x240.png ADDED
Binary file
assets/css/lib/jquery-ui/images/ui-icons_454545_256x240.png ADDED
Binary file
assets/css/lib/jquery-ui/images/ui-icons_888888_256x240.png ADDED
Binary file
assets/css/lib/jquery-ui/images/ui-icons_cd0a0a_256x240.png ADDED
Binary file
assets/css/lib/jquery-ui/jquery-ui.css ADDED
@@ -0,0 +1,1311 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /*! jQuery UI - v1.12.1 - 2016-09-14
2
+ * http://jqueryui.com
3
+ * Includes: core.css, accordion.css, autocomplete.css, menu.css, button.css, controlgroup.css, checkboxradio.css, datepicker.css, dialog.css, draggable.css, resizable.css, progressbar.css, selectable.css, selectmenu.css, slider.css, sortable.css, spinner.css, tabs.css, tooltip.css, theme.css
4
+ * To view and modify this theme, visit http://jqueryui.com/themeroller/?ffDefault=Verdana%2CArial%2Csans-serif&fwDefault=normal&fsDefault=1.1em&cornerRadius=4px&bgColorHeader=cccccc&bgTextureHeader=highlight_soft&bgImgOpacityHeader=75&borderColorHeader=aaaaaa&fcHeader=222222&iconColorHeader=222222&bgColorContent=ffffff&bgTextureContent=flat&bgImgOpacityContent=75&borderColorContent=aaaaaa&fcContent=222222&iconColorContent=222222&bgColorDefault=e6e6e6&bgTextureDefault=glass&bgImgOpacityDefault=75&borderColorDefault=d3d3d3&fcDefault=555555&iconColorDefault=888888&bgColorHover=dadada&bgTextureHover=glass&bgImgOpacityHover=75&borderColorHover=999999&fcHover=212121&iconColorHover=454545&bgColorActive=ffffff&bgTextureActive=glass&bgImgOpacityActive=65&borderColorActive=aaaaaa&fcActive=212121&iconColorActive=454545&bgColorHighlight=fbf9ee&bgTextureHighlight=glass&bgImgOpacityHighlight=55&borderColorHighlight=fcefa1&fcHighlight=363636&iconColorHighlight=2e83ff&bgColorError=fef1ec&bgTextureError=glass&bgImgOpacityError=95&borderColorError=cd0a0a&fcError=cd0a0a&iconColorError=cd0a0a&bgColorOverlay=aaaaaa&bgTextureOverlay=flat&bgImgOpacityOverlay=0&opacityOverlay=30&bgColorShadow=aaaaaa&bgTextureShadow=flat&bgImgOpacityShadow=0&opacityShadow=30&thicknessShadow=8px&offsetTopShadow=-8px&offsetLeftShadow=-8px&cornerRadiusShadow=8px
5
+ * Copyright jQuery Foundation and other contributors; Licensed MIT */
6
+
7
+ /* Layout helpers
8
+ ----------------------------------*/
9
+ .ui-helper-hidden {
10
+ display: none;
11
+ }
12
+ .ui-helper-hidden-accessible {
13
+ border: 0;
14
+ clip: rect(0 0 0 0);
15
+ height: 1px;
16
+ margin: -1px;
17
+ overflow: hidden;
18
+ padding: 0;
19
+ position: absolute;
20
+ width: 1px;
21
+ }
22
+ .ui-helper-reset {
23
+ margin: 0;
24
+ padding: 0;
25
+ border: 0;
26
+ outline: 0;
27
+ line-height: 1.3;
28
+ text-decoration: none;
29
+ font-size: 100%;
30
+ list-style: none;
31
+ }
32
+ .ui-helper-clearfix:before,
33
+ .ui-helper-clearfix:after {
34
+ content: "";
35
+ display: table;
36
+ border-collapse: collapse;
37
+ }
38
+ .ui-helper-clearfix:after {
39
+ clear: both;
40
+ }
41
+ .ui-helper-zfix {
42
+ width: 100%;
43
+ height: 100%;
44
+ top: 0;
45
+ left: 0;
46
+ position: absolute;
47
+ opacity: 0;
48
+ filter:Alpha(Opacity=0); /* support: IE8 */
49
+ }
50
+
51
+ .ui-front {
52
+ z-index: 100;
53
+ }
54
+
55
+
56
+ /* Interaction Cues
57
+ ----------------------------------*/
58
+ .ui-state-disabled {
59
+ cursor: default !important;
60
+ pointer-events: none;
61
+ }
62
+
63
+
64
+ /* Icons
65
+ ----------------------------------*/
66
+ .ui-icon {
67
+ display: inline-block;
68
+ vertical-align: middle;
69
+ margin-top: -.25em;
70
+ position: relative;
71
+ text-indent: -99999px;
72
+ overflow: hidden;
73
+ background-repeat: no-repeat;
74
+ }
75
+
76
+ .ui-widget-icon-block {
77
+ left: 50%;
78
+ margin-left: -8px;
79
+ display: block;
80
+ }
81
+
82
+ /* Misc visuals
83
+ ----------------------------------*/
84
+
85
+ /* Overlays */
86
+ .ui-widget-overlay {
87
+ position: fixed;
88
+ top: 0;
89
+ left: 0;
90
+ width: 100%;
91
+ height: 100%;
92
+ }
93
+ .ui-accordion .ui-accordion-header {
94
+ display: block;
95
+ cursor: pointer;
96
+ position: relative;
97
+ margin: 2px 0 0 0;
98
+ padding: .5em .5em .5em .7em;
99
+ font-size: 100%;
100
+ }
101
+ .ui-accordion .ui-accordion-content {
102
+ padding: 1em 2.2em;
103
+ border-top: 0;
104
+ overflow: auto;
105
+ }
106
+ .ui-autocomplete {
107
+ position: absolute;
108
+ top: 0;
109
+ left: 0;
110
+ cursor: default;
111
+ }
112
+ .ui-menu {
113
+ list-style: none;
114
+ padding: 0;
115
+ margin: 0;
116
+ display: block;
117
+ outline: 0;
118
+ }
119
+ .ui-menu .ui-menu {
120
+ position: absolute;
121
+ }
122
+ .ui-menu .ui-menu-item {
123
+ margin: 0;
124
+ cursor: pointer;
125
+ /* support: IE10, see #8844 */
126
+ list-style-image: url("data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7");
127
+ }
128
+ .ui-menu .ui-menu-item-wrapper {
129
+ position: relative;
130
+ padding: 3px 1em 3px .4em;
131
+ }
132
+ .ui-menu .ui-menu-divider {
133
+ margin: 5px 0;
134
+ height: 0;
135
+ font-size: 0;
136
+ line-height: 0;
137
+ border-width: 1px 0 0 0;
138
+ }
139
+ .ui-menu .ui-state-focus,
140
+ .ui-menu .ui-state-active {
141
+ margin: -1px;
142
+ }
143
+
144
+ /* icon support */
145
+ .ui-menu-icons {
146
+ position: relative;
147
+ }
148
+ .ui-menu-icons .ui-menu-item-wrapper {
149
+ padding-left: 2em;
150
+ }
151
+
152
+ /* left-aligned */
153
+ .ui-menu .ui-icon {
154
+ position: absolute;
155
+ top: 0;
156
+ bottom: 0;
157
+ left: .2em;
158
+ margin: auto 0;
159
+ }
160
+
161
+ /* right-aligned */
162
+ .ui-menu .ui-menu-icon {
163
+ left: auto;
164
+ right: 0;
165
+ }
166
+ .ui-button {
167
+ padding: .4em 1em;
168
+ display: inline-block;
169
+ position: relative;
170
+ line-height: normal;
171
+ margin-right: .1em;
172
+ cursor: pointer;
173
+ vertical-align: middle;
174
+ text-align: center;
175
+ -webkit-user-select: none;
176
+ -moz-user-select: none;
177
+ -ms-user-select: none;
178
+ user-select: none;
179
+
180
+ /* Support: IE <= 11 */
181
+ overflow: visible;
182
+ }
183
+
184
+ .ui-button,
185
+ .ui-button:link,
186
+ .ui-button:visited,
187
+ .ui-button:hover,
188
+ .ui-button:active {
189
+ text-decoration: none;
190
+ }
191
+
192
+ /* to make room for the icon, a width needs to be set here */
193
+ .ui-button-icon-only {
194
+ width: 2em;
195
+ box-sizing: border-box;
196
+ text-indent: -9999px;
197
+ white-space: nowrap;
198
+ }
199
+
200
+ /* no icon support for input elements */
201
+ input.ui-button.ui-button-icon-only {
202
+ text-indent: 0;
203
+ }
204
+
205
+ /* button icon element(s) */
206
+ .ui-button-icon-only .ui-icon {
207
+ position: absolute;
208
+ top: 50%;
209
+ left: 50%;
210
+ margin-top: -8px;
211
+ margin-left: -8px;
212
+ }
213
+
214
+ .ui-button.ui-icon-notext .ui-icon {
215
+ padding: 0;
216
+ width: 2.1em;
217
+ height: 2.1em;
218
+ text-indent: -9999px;
219
+ white-space: nowrap;
220
+
221
+ }
222
+
223
+ input.ui-button.ui-icon-notext .ui-icon {
224
+ width: auto;
225
+ height: auto;
226
+ text-indent: 0;
227
+ white-space: normal;
228
+ padding: .4em 1em;
229
+ }
230
+
231
+ /* workarounds */
232
+ /* Support: Firefox 5 - 40 */
233
+ input.ui-button::-moz-focus-inner,
234
+ button.ui-button::-moz-focus-inner {
235
+ border: 0;
236
+ padding: 0;
237
+ }
238
+ .ui-controlgroup {
239
+ vertical-align: middle;
240
+ display: inline-block;
241
+ }
242
+ .ui-controlgroup > .ui-controlgroup-item {
243
+ float: left;
244
+ margin-left: 0;
245
+ margin-right: 0;
246
+ }
247
+ .ui-controlgroup > .ui-controlgroup-item:focus,
248
+ .ui-controlgroup > .ui-controlgroup-item.ui-visual-focus {
249
+ z-index: 9999;
250
+ }
251
+ .ui-controlgroup-vertical > .ui-controlgroup-item {
252
+ display: block;
253
+ float: none;
254
+ width: 100%;
255
+ margin-top: 0;
256
+ margin-bottom: 0;
257
+ text-align: left;
258
+ }
259
+ .ui-controlgroup-vertical .ui-controlgroup-item {
260
+ box-sizing: border-box;
261
+ }
262
+ .ui-controlgroup .ui-controlgroup-label {
263
+ padding: .4em 1em;
264
+ }
265
+ .ui-controlgroup .ui-controlgroup-label span {
266
+ font-size: 80%;
267
+ }
268
+ .ui-controlgroup-horizontal .ui-controlgroup-label + .ui-controlgroup-item {
269
+ border-left: none;
270
+ }
271
+ .ui-controlgroup-vertical .ui-controlgroup-label + .ui-controlgroup-item {
272
+ border-top: none;
273
+ }
274
+ .ui-controlgroup-horizontal .ui-controlgroup-label.ui-widget-content {
275
+ border-right: none;
276
+ }
277
+ .ui-controlgroup-vertical .ui-controlgroup-label.ui-widget-content {
278
+ border-bottom: none;
279
+ }
280
+
281
+ /* Spinner specific style fixes */
282
+ .ui-controlgroup-vertical .ui-spinner-input {
283
+
284
+ /* Support: IE8 only, Android < 4.4 only */
285
+ width: 75%;
286
+ width: calc( 100% - 2.4em );
287
+ }
288
+ .ui-controlgroup-vertical .ui-spinner .ui-spinner-up {
289
+ border-top-style: solid;
290
+ }
291
+
292
+ .ui-checkboxradio-label .ui-icon-background {
293
+ box-shadow: inset 1px 1px 1px #ccc;
294
+ border-radius: .12em;
295
+ border: none;
296
+ }
297
+ .ui-checkboxradio-radio-label .ui-icon-background {
298
+ width: 16px;
299
+ height: 16px;
300
+ border-radius: 1em;
301
+ overflow: visible;
302
+ border: none;
303
+ }
304
+ .ui-checkboxradio-radio-label.ui-checkboxradio-checked .ui-icon,
305
+ .ui-checkboxradio-radio-label.ui-checkboxradio-checked:hover .ui-icon {
306
+ background-image: none;
307
+ width: 8px;
308
+ height: 8px;
309
+ border-width: 4px;
310
+ border-style: solid;
311
+ }
312
+ .ui-checkboxradio-disabled {
313
+ pointer-events: none;
314
+ }
315
+ .ui-datepicker {
316
+ width: 17em;
317
+ padding: .2em .2em 0;
318
+ display: none;
319
+ }
320
+ .ui-datepicker .ui-datepicker-header {
321
+ position: relative;
322
+ padding: .2em 0;
323
+ }
324
+ .ui-datepicker .ui-datepicker-prev,
325
+ .ui-datepicker .ui-datepicker-next {
326
+ position: absolute;
327
+ top: 2px;
328
+ width: 1.8em;
329
+ height: 1.8em;
330
+ }
331
+ .ui-datepicker .ui-datepicker-prev-hover,
332
+ .ui-datepicker .ui-datepicker-next-hover {
333
+ top: 1px;
334
+ }
335
+ .ui-datepicker .ui-datepicker-prev {
336
+ left: 2px;
337
+ }
338
+ .ui-datepicker .ui-datepicker-next {
339
+ right: 2px;
340
+ }
341
+ .ui-datepicker .ui-datepicker-prev-hover {
342
+ left: 1px;
343
+ }
344
+ .ui-datepicker .ui-datepicker-next-hover {
345
+ right: 1px;
346
+ }
347
+ .ui-datepicker .ui-datepicker-prev span,
348
+ .ui-datepicker .ui-datepicker-next span {
349
+ display: block;
350
+ position: absolute;
351
+ left: 50%;
352
+ margin-left: -8px;
353
+ top: 50%;
354
+ margin-top: -8px;
355
+ }
356
+ .ui-datepicker .ui-datepicker-title {
357
+ margin: 0 2.3em;
358
+ line-height: 1.8em;
359
+ text-align: center;
360
+ }
361
+ .ui-datepicker .ui-datepicker-title select {
362
+ font-size: 1em;
363
+ margin: 1px 0;
364
+ }
365
+ .ui-datepicker select.ui-datepicker-month,
366
+ .ui-datepicker select.ui-datepicker-year {
367
+ width: 45%;
368
+ }
369
+ .ui-datepicker table {
370
+ width: 100%;
371
+ font-size: .9em;
372
+ border-collapse: collapse;
373
+ margin: 0 0 .4em;
374
+ }
375
+ .ui-datepicker th {
376
+ padding: .7em .3em;
377
+ text-align: center;
378
+ font-weight: bold;
379
+ border: 0;
380
+ }
381
+ .ui-datepicker td {
382
+ border: 0;
383
+ padding: 1px;
384
+ }
385
+ .ui-datepicker td span,
386
+ .ui-datepicker td a {
387
+ display: block;
388
+ padding: .2em;
389
+ text-align: right;
390
+ text-decoration: none;
391
+ }
392
+ .ui-datepicker .ui-datepicker-buttonpane {
393
+ background-image: none;
394
+ margin: .7em 0 0 0;
395
+ padding: 0 .2em;
396
+ border-left: 0;
397
+ border-right: 0;
398
+ border-bottom: 0;
399
+ }
400
+ .ui-datepicker .ui-datepicker-buttonpane button {
401
+ float: right;
402
+ margin: .5em .2em .4em;
403
+ cursor: pointer;
404
+ padding: .2em .6em .3em .6em;
405
+ width: auto;
406
+ overflow: visible;
407
+ }
408
+ .ui-datepicker .ui-datepicker-buttonpane button.ui-datepicker-current {
409
+ float: left;
410
+ }
411
+
412
+ /* with multiple calendars */
413
+ .ui-datepicker.ui-datepicker-multi {
414
+ width: auto;
415
+ }
416
+ .ui-datepicker-multi .ui-datepicker-group {
417
+ float: left;
418
+ }
419
+ .ui-datepicker-multi .ui-datepicker-group table {
420
+ width: 95%;
421
+ margin: 0 auto .4em;
422
+ }
423
+ .ui-datepicker-multi-2 .ui-datepicker-group {
424
+ width: 50%;
425
+ }
426
+ .ui-datepicker-multi-3 .ui-datepicker-group {
427
+ width: 33.3%;
428
+ }
429
+ .ui-datepicker-multi-4 .ui-datepicker-group {
430
+ width: 25%;
431
+ }
432
+ .ui-datepicker-multi .ui-datepicker-group-last .ui-datepicker-header,
433
+ .ui-datepicker-multi .ui-datepicker-group-middle .ui-datepicker-header {
434
+ border-left-width: 0;
435
+ }
436
+ .ui-datepicker-multi .ui-datepicker-buttonpane {
437
+ clear: left;
438
+ }
439
+ .ui-datepicker-row-break {
440
+ clear: both;
441
+ width: 100%;
442
+ font-size: 0;
443
+ }
444
+
445
+ /* RTL support */
446
+ .ui-datepicker-rtl {
447
+ direction: rtl;
448
+ }
449
+ .ui-datepicker-rtl .ui-datepicker-prev {
450
+ right: 2px;
451
+ left: auto;
452
+ }
453
+ .ui-datepicker-rtl .ui-datepicker-next {
454
+ left: 2px;
455
+ right: auto;
456
+ }
457
+ .ui-datepicker-rtl .ui-datepicker-prev:hover {
458
+ right: 1px;
459
+ left: auto;
460
+ }
461
+ .ui-datepicker-rtl .ui-datepicker-next:hover {
462
+ left: 1px;
463
+ right: auto;
464
+ }
465
+ .ui-datepicker-rtl .ui-datepicker-buttonpane {
466
+ clear: right;
467
+ }
468
+ .ui-datepicker-rtl .ui-datepicker-buttonpane button {
469
+ float: left;
470
+ }
471
+ .ui-datepicker-rtl .ui-datepicker-buttonpane button.ui-datepicker-current,
472
+ .ui-datepicker-rtl .ui-datepicker-group {
473
+ float: right;
474
+ }
475
+ .ui-datepicker-rtl .ui-datepicker-group-last .ui-datepicker-header,
476
+ .ui-datepicker-rtl .ui-datepicker-group-middle .ui-datepicker-header {
477
+ border-right-width: 0;
478
+ border-left-width: 1px;
479
+ }
480
+
481
+ /* Icons */
482
+ .ui-datepicker .ui-icon {
483
+ display: block;
484
+ text-indent: -99999px;
485
+ overflow: hidden;
486
+ background-repeat: no-repeat;
487
+ left: .5em;
488
+ top: .3em;
489
+ }
490
+ .ui-dialog {
491
+ position: absolute;
492
+ top: 0;
493
+ left: 0;
494
+ padding: .2em;
495
+ outline: 0;
496
+ }
497
+ .ui-dialog .ui-dialog-titlebar {
498
+ padding: .4em 1em;
499
+ position: relative;
500
+ }
501
+ .ui-dialog .ui-dialog-title {
502
+ float: left;
503
+ margin: .1em 0;
504
+ white-space: nowrap;
505
+ width: 90%;
506
+ overflow: hidden;
507
+ text-overflow: ellipsis;
508
+ }
509
+ .ui-dialog .ui-dialog-titlebar-close {
510
+ position: absolute;
511
+ right: .3em;
512
+ top: 50%;
513
+ width: 20px;
514
+ margin: -10px 0 0 0;
515
+ padding: 1px;
516
+ height: 20px;
517
+ }
518
+ .ui-dialog .ui-dialog-content {
519
+ position: relative;
520
+ border: 0;
521
+ padding: .5em 1em;
522
+ background: none;
523
+ overflow: auto;
524
+ }
525
+ .ui-dialog .ui-dialog-buttonpane {
526
+ text-align: left;
527
+ border-width: 1px 0 0 0;
528
+ background-image: none;
529
+ margin-top: .5em;
530
+ padding: .3em 1em .5em .4em;
531
+ }
532
+ .ui-dialog .ui-dialog-buttonpane .ui-dialog-buttonset {
533
+ float: right;
534
+ }
535
+ .ui-dialog .ui-dialog-buttonpane button {
536
+ margin: .5em .4em .5em 0;
537
+ cursor: pointer;
538
+ }
539
+ .ui-dialog .ui-resizable-n {
540
+ height: 2px;
541
+ top: 0;
542
+ }
543
+ .ui-dialog .ui-resizable-e {
544
+ width: 2px;
545
+ right: 0;
546
+ }
547
+ .ui-dialog .ui-resizable-s {
548
+ height: 2px;
549
+ bottom: 0;
550
+ }
551
+ .ui-dialog .ui-resizable-w {
552
+ width: 2px;
553
+ left: 0;
554
+ }
555
+ .ui-dialog .ui-resizable-se,
556
+ .ui-dialog .ui-resizable-sw,
557
+ .ui-dialog .ui-resizable-ne,
558
+ .ui-dialog .ui-resizable-nw {
559
+ width: 7px;
560
+ height: 7px;
561
+ }
562
+ .ui-dialog .ui-resizable-se {
563
+ right: 0;
564
+ bottom: 0;
565
+ }
566
+ .ui-dialog .ui-resizable-sw {
567
+ left: 0;
568
+ bottom: 0;
569
+ }
570
+ .ui-dialog .ui-resizable-ne {
571
+ right: 0;
572
+ top: 0;
573
+ }
574
+ .ui-dialog .ui-resizable-nw {
575
+ left: 0;
576
+ top: 0;
577
+ }
578
+ .ui-draggable .ui-dialog-titlebar {
579
+ cursor: move;
580
+ }
581
+ .ui-draggable-handle {
582
+ -ms-touch-action: none;
583
+ touch-action: none;
584
+ }
585
+ .ui-resizable {
586
+ position: relative;
587
+ }
588
+ .ui-resizable-handle {
589
+ position: absolute;
590
+ font-size: 0.1px;
591
+ display: block;
592
+ -ms-touch-action: none;
593
+ touch-action: none;
594
+ }
595
+ .ui-resizable-disabled .ui-resizable-handle,
596
+ .ui-resizable-autohide .ui-resizable-handle {
597
+ display: none;
598
+ }
599
+ .ui-resizable-n {
600
+ cursor: n-resize;
601
+ height: 7px;
602
+ width: 100%;
603
+ top: -5px;
604
+ left: 0;
605
+ }
606
+ .ui-resizable-s {
607
+ cursor: s-resize;
608
+ height: 7px;
609
+ width: 100%;
610
+ bottom: -5px;
611
+ left: 0;
612
+ }
613
+ .ui-resizable-e {
614
+ cursor: e-resize;
615
+ width: 7px;
616
+ right: -5px;
617
+ top: 0;
618
+ height: 100%;
619
+ }
620
+ .ui-resizable-w {
621
+ cursor: w-resize;
622
+ width: 7px;
623
+ left: -5px;
624
+ top: 0;
625
+ height: 100%;
626
+ }
627
+ .ui-resizable-se {
628
+ cursor: se-resize;
629
+ width: 12px;
630
+ height: 12px;
631
+ right: 1px;
632
+ bottom: 1px;
633
+ }
634
+ .ui-resizable-sw {
635
+ cursor: sw-resize;
636
+ width: 9px;
637
+ height: 9px;
638
+ left: -5px;
639
+ bottom: -5px;
640
+ }
641
+ .ui-resizable-nw {
642
+ cursor: nw-resize;
643
+ width: 9px;
644
+ height: 9px;
645
+ left: -5px;
646
+ top: -5px;
647
+ }
648
+ .ui-resizable-ne {
649
+ cursor: ne-resize;
650
+ width: 9px;
651
+ height: 9px;
652
+ right: -5px;
653
+ top: -5px;
654
+ }
655
+ .ui-progressbar {
656
+ height: 2em;
657
+ text-align: left;
658
+ overflow: hidden;
659
+ }
660
+ .ui-progressbar .ui-progressbar-value {
661
+ margin: -1px;
662
+ height: 100%;
663
+ }
664
+ .ui-progressbar .ui-progressbar-overlay {
665
+ background: url("data:image/gif;base64,R0lGODlhKAAoAIABAAAAAP///yH/C05FVFNDQVBFMi4wAwEAAAAh+QQJAQABACwAAAAAKAAoAAACkYwNqXrdC52DS06a7MFZI+4FHBCKoDeWKXqymPqGqxvJrXZbMx7Ttc+w9XgU2FB3lOyQRWET2IFGiU9m1frDVpxZZc6bfHwv4c1YXP6k1Vdy292Fb6UkuvFtXpvWSzA+HycXJHUXiGYIiMg2R6W459gnWGfHNdjIqDWVqemH2ekpObkpOlppWUqZiqr6edqqWQAAIfkECQEAAQAsAAAAACgAKAAAApSMgZnGfaqcg1E2uuzDmmHUBR8Qil95hiPKqWn3aqtLsS18y7G1SzNeowWBENtQd+T1JktP05nzPTdJZlR6vUxNWWjV+vUWhWNkWFwxl9VpZRedYcflIOLafaa28XdsH/ynlcc1uPVDZxQIR0K25+cICCmoqCe5mGhZOfeYSUh5yJcJyrkZWWpaR8doJ2o4NYq62lAAACH5BAkBAAEALAAAAAAoACgAAAKVDI4Yy22ZnINRNqosw0Bv7i1gyHUkFj7oSaWlu3ovC8GxNso5fluz3qLVhBVeT/Lz7ZTHyxL5dDalQWPVOsQWtRnuwXaFTj9jVVh8pma9JjZ4zYSj5ZOyma7uuolffh+IR5aW97cHuBUXKGKXlKjn+DiHWMcYJah4N0lYCMlJOXipGRr5qdgoSTrqWSq6WFl2ypoaUAAAIfkECQEAAQAsAAAAACgAKAAAApaEb6HLgd/iO7FNWtcFWe+ufODGjRfoiJ2akShbueb0wtI50zm02pbvwfWEMWBQ1zKGlLIhskiEPm9R6vRXxV4ZzWT2yHOGpWMyorblKlNp8HmHEb/lCXjcW7bmtXP8Xt229OVWR1fod2eWqNfHuMjXCPkIGNileOiImVmCOEmoSfn3yXlJWmoHGhqp6ilYuWYpmTqKUgAAIfkECQEAAQAsAAAAACgAKAAAApiEH6kb58biQ3FNWtMFWW3eNVcojuFGfqnZqSebuS06w5V80/X02pKe8zFwP6EFWOT1lDFk8rGERh1TTNOocQ61Hm4Xm2VexUHpzjymViHrFbiELsefVrn6XKfnt2Q9G/+Xdie499XHd2g4h7ioOGhXGJboGAnXSBnoBwKYyfioubZJ2Hn0RuRZaflZOil56Zp6iioKSXpUAAAh+QQJAQABACwAAAAAKAAoAAACkoQRqRvnxuI7kU1a1UU5bd5tnSeOZXhmn5lWK3qNTWvRdQxP8qvaC+/yaYQzXO7BMvaUEmJRd3TsiMAgswmNYrSgZdYrTX6tSHGZO73ezuAw2uxuQ+BbeZfMxsexY35+/Qe4J1inV0g4x3WHuMhIl2jXOKT2Q+VU5fgoSUI52VfZyfkJGkha6jmY+aaYdirq+lQAACH5BAkBAAEALAAAAAAoACgAAAKWBIKpYe0L3YNKToqswUlvznigd4wiR4KhZrKt9Upqip61i9E3vMvxRdHlbEFiEXfk9YARYxOZZD6VQ2pUunBmtRXo1Lf8hMVVcNl8JafV38aM2/Fu5V16Bn63r6xt97j09+MXSFi4BniGFae3hzbH9+hYBzkpuUh5aZmHuanZOZgIuvbGiNeomCnaxxap2upaCZsq+1kAACH5BAkBAAEALAAAAAAoACgAAAKXjI8By5zf4kOxTVrXNVlv1X0d8IGZGKLnNpYtm8Lr9cqVeuOSvfOW79D9aDHizNhDJidFZhNydEahOaDH6nomtJjp1tutKoNWkvA6JqfRVLHU/QUfau9l2x7G54d1fl995xcIGAdXqMfBNadoYrhH+Mg2KBlpVpbluCiXmMnZ2Sh4GBqJ+ckIOqqJ6LmKSllZmsoq6wpQAAAh+QQJAQABACwAAAAAKAAoAAAClYx/oLvoxuJDkU1a1YUZbJ59nSd2ZXhWqbRa2/gF8Gu2DY3iqs7yrq+xBYEkYvFSM8aSSObE+ZgRl1BHFZNr7pRCavZ5BW2142hY3AN/zWtsmf12p9XxxFl2lpLn1rseztfXZjdIWIf2s5dItwjYKBgo9yg5pHgzJXTEeGlZuenpyPmpGQoKOWkYmSpaSnqKileI2FAAACH5BAkBAAEALAAAAAAoACgAAAKVjB+gu+jG4kORTVrVhRlsnn2dJ3ZleFaptFrb+CXmO9OozeL5VfP99HvAWhpiUdcwkpBH3825AwYdU8xTqlLGhtCosArKMpvfa1mMRae9VvWZfeB2XfPkeLmm18lUcBj+p5dnN8jXZ3YIGEhYuOUn45aoCDkp16hl5IjYJvjWKcnoGQpqyPlpOhr3aElaqrq56Bq7VAAAOw==");
666
+ height: 100%;
667
+ filter: alpha(opacity=25); /* support: IE8 */
668
+ opacity: 0.25;
669
+ }
670
+ .ui-progressbar-indeterminate .ui-progressbar-value {
671
+ background-image: none;
672
+ }
673
+ .ui-selectable {
674
+ -ms-touch-action: none;
675
+ touch-action: none;
676
+ }
677
+ .ui-selectable-helper {
678
+ position: absolute;
679
+ z-index: 100;
680
+ border: 1px dotted black;
681
+ }
682
+ .ui-selectmenu-menu {
683
+ padding: 0;
684
+ margin: 0;
685
+ position: absolute;
686
+ top: 0;
687
+ left: 0;
688
+ display: none;
689
+ }
690
+ .ui-selectmenu-menu .ui-menu {
691
+ overflow: auto;
692
+ overflow-x: hidden;
693
+ padding-bottom: 1px;
694
+ }
695
+ .ui-selectmenu-menu .ui-menu .ui-selectmenu-optgroup {
696
+ font-size: 1em;
697
+ font-weight: bold;
698
+ line-height: 1.5;
699
+ padding: 2px 0.4em;
700
+ margin: 0.5em 0 0 0;
701
+ height: auto;
702
+ border: 0;
703
+ }
704
+ .ui-selectmenu-open {
705
+ display: block;
706
+ }
707
+ .ui-selectmenu-text {
708
+ display: block;
709
+ margin-right: 20px;
710
+ overflow: hidden;
711
+ text-overflow: ellipsis;
712
+ }
713
+ .ui-selectmenu-button.ui-button {
714
+ text-align: left;
715
+ white-space: nowrap;
716
+ width: 14em;
717
+ }
718
+ .ui-selectmenu-icon.ui-icon {
719
+ float: right;
720
+ margin-top: 0;
721
+ }
722
+ .ui-slider {
723
+ position: relative;
724
+ text-align: left;
725
+ }
726
+ .ui-slider .ui-slider-handle {
727
+ position: absolute;
728
+ z-index: 2;
729
+ width: 1.2em;
730
+ height: 1.2em;
731
+ cursor: default;
732
+ -ms-touch-action: none;
733
+ touch-action: none;
734
+ }
735
+ .ui-slider .ui-slider-range {
736
+ position: absolute;
737
+ z-index: 1;
738
+ font-size: .7em;
739
+ display: block;
740
+ border: 0;
741
+ background-position: 0 0;
742
+ }
743
+
744
+ /* support: IE8 - See #6727 */
745
+ .ui-slider.ui-state-disabled .ui-slider-handle,
746
+ .ui-slider.ui-state-disabled .ui-slider-range {
747
+ filter: inherit;
748
+ }
749
+
750
+ .ui-slider-horizontal {
751
+ height: .8em;
752
+ }
753
+ .ui-slider-horizontal .ui-slider-handle {
754
+ top: -.3em;
755
+ margin-left: -.6em;
756
+ }
757
+ .ui-slider-horizontal .ui-slider-range {
758
+ top: 0;
759
+ height: 100%;
760
+ }
761
+ .ui-slider-horizontal .ui-slider-range-min {
762
+ left: 0;
763
+ }
764
+ .ui-slider-horizontal .ui-slider-range-max {
765
+ right: 0;
766
+ }
767
+
768
+ .ui-slider-vertical {
769
+ width: .8em;
770
+ height: 100px;
771
+ }
772
+ .ui-slider-vertical .ui-slider-handle {
773
+ left: -.3em;
774
+ margin-left: 0;
775
+ margin-bottom: -.6em;
776
+ }
777
+ .ui-slider-vertical .ui-slider-range {
778
+ left: 0;
779
+ width: 100%;
780
+ }
781
+ .ui-slider-vertical .ui-slider-range-min {
782
+ bottom: 0;
783
+ }
784
+ .ui-slider-vertical .ui-slider-range-max {
785
+ top: 0;
786
+ }
787
+ .ui-sortable-handle {
788
+ -ms-touch-action: none;
789
+ touch-action: none;
790
+ }
791
+ .ui-spinner {
792
+ position: relative;
793
+ display: inline-block;
794
+ overflow: hidden;
795
+ padding: 0;
796
+ vertical-align: middle;
797
+ }
798
+ .ui-spinner-input {
799
+ border: none;
800
+ background: none;
801
+ color: inherit;
802
+ padding: .222em 0;
803
+ margin: .2em 0;
804
+ vertical-align: middle;
805
+ margin-left: .4em;
806
+ margin-right: 2em;
807
+ }
808
+ .ui-spinner-button {
809
+ width: 1.6em;
810
+ height: 50%;
811
+ font-size: .5em;
812
+ padding: 0;
813
+ margin: 0;
814
+ text-align: center;
815
+ position: absolute;
816
+ cursor: default;
817
+ display: block;
818
+ overflow: hidden;
819
+ right: 0;
820
+ }
821
+ /* more specificity required here to override default borders */
822
+ .ui-spinner a.ui-spinner-button {
823
+ border-top-style: none;
824
+ border-bottom-style: none;
825
+ border-right-style: none;
826
+ }
827
+ .ui-spinner-up {
828
+ top: 0;
829
+ }
830
+ .ui-spinner-down {
831
+ bottom: 0;
832
+ }
833
+ .ui-tabs {
834
+ position: relative;/* position: relative prevents IE scroll bug (element with position: relative inside container with overflow: auto appear as "fixed") */
835
+ padding: .2em;
836
+ }
837
+ .ui-tabs .ui-tabs-nav {
838
+ margin: 0;
839
+ padding: .2em .2em 0;
840
+ }
841
+ .ui-tabs .ui-tabs-nav li {
842
+ list-style: none;
843
+ float: left;
844
+ position: relative;
845
+ top: 0;
846
+ margin: 1px .2em 0 0;
847
+ border-bottom-width: 0;
848
+ padding: 0;
849
+ white-space: nowrap;
850
+ }
851
+ .ui-tabs .ui-tabs-nav .ui-tabs-anchor {
852
+ float: left;
853
+ padding: .5em 1em;
854
+ text-decoration: none;
855
+ }
856
+ .ui-tabs .ui-tabs-nav li.ui-tabs-active {
857
+ margin-bottom: -1px;
858
+ padding-bottom: 1px;
859
+ }
860
+ .ui-tabs .ui-tabs-nav li.ui-tabs-active .ui-tabs-anchor,
861
+ .ui-tabs .ui-tabs-nav li.ui-state-disabled .ui-tabs-anchor,
862
+ .ui-tabs .ui-tabs-nav li.ui-tabs-loading .ui-tabs-anchor {
863
+ cursor: text;
864
+ }
865
+ .ui-tabs-collapsible .ui-tabs-nav li.ui-tabs-active .ui-tabs-anchor {
866
+ cursor: pointer;
867
+ }
868
+ .ui-tabs .ui-tabs-panel {
869
+ display: block;
870
+ border-width: 0;
871
+ padding: 1em 1.4em;
872
+ background: none;
873
+ }
874
+ .ui-tooltip {
875
+ padding: 8px;
876
+ position: absolute;
877
+ z-index: 9999;
878
+ max-width: 300px;
879
+ }
880
+ body .ui-tooltip {
881
+ border-width: 2px;
882
+ }
883
+ /* Component containers
884
+ ----------------------------------*/
885
+ .ui-widget {
886
+ font-family: Verdana,Arial,sans-serif;
887
+ font-size: 1.1em;
888
+ }
889
+ .ui-widget .ui-widget {
890
+ font-size: 1em;
891
+ }
892
+ .ui-widget input,
893
+ .ui-widget select,
894
+ .ui-widget textarea,
895
+ .ui-widget button {
896
+ font-family: Verdana,Arial,sans-serif;
897
+ font-size: 1em;
898
+ }
899
+ .ui-widget.ui-widget-content {
900
+ border: 1px solid #d3d3d3;
901
+ }
902
+ .ui-widget-content {
903
+ border: 1px solid #aaaaaa;
904
+ background: #ffffff;
905
+ color: #222222;
906
+ }
907
+ .ui-widget-content a {
908
+ color: #222222;
909
+ }
910
+ .ui-widget-header {
911
+ border: 1px solid #aaaaaa;
912
+ background: #cccccc url("images/ui-bg_highlight-soft_75_cccccc_1x100.png") 50% 50% repeat-x;
913
+ color: #222222;
914
+ font-weight: bold;
915
+ }
916
+ .ui-widget-header a {
917
+ color: #222222;
918
+ }
919
+
920
+ /* Interaction states
921
+ ----------------------------------*/
922
+ .ui-state-default,
923
+ .ui-widget-content .ui-state-default,
924
+ .ui-widget-header .ui-state-default,
925
+ .ui-button,
926
+
927
+ /* We use html here because we need a greater specificity to make sure disabled
928
+ works properly when clicked or hovered */
929
+ html .ui-button.ui-state-disabled:hover,
930
+ html .ui-button.ui-state-disabled:active {
931
+ border: 1px solid #d3d3d3;
932
+ background: #e6e6e6 url("images/ui-bg_glass_75_e6e6e6_1x400.png") 50% 50% repeat-x;
933
+ font-weight: normal;
934
+ color: #555555;
935
+ }
936
+ .ui-state-default a,
937
+ .ui-state-default a:link,
938
+ .ui-state-default a:visited,
939
+ a.ui-button,
940
+ a:link.ui-button,
941
+ a:visited.ui-button,
942
+ .ui-button {
943
+ color: #555555;
944
+ text-decoration: none;
945
+ }
946
+ .ui-state-hover,
947
+ .ui-widget-content .ui-state-hover,
948
+ .ui-widget-header .ui-state-hover,
949
+ .ui-state-focus,
950
+ .ui-widget-content .ui-state-focus,
951
+ .ui-widget-header .ui-state-focus,
952
+ .ui-button:hover,
953
+ .ui-button:focus {
954
+ border: 1px solid #999999;
955
+ background: #dadada url("images/ui-bg_glass_75_dadada_1x400.png") 50% 50% repeat-x;
956
+ font-weight: normal;
957
+ color: #212121;
958
+ }
959
+ .ui-state-hover a,
960
+ .ui-state-hover a:hover,
961
+ .ui-state-hover a:link,
962
+ .ui-state-hover a:visited,
963
+ .ui-state-focus a,
964
+ .ui-state-focus a:hover,
965
+ .ui-state-focus a:link,
966
+ .ui-state-focus a:visited,
967
+ a.ui-button:hover,
968
+ a.ui-button:focus {
969
+ color: #212121;
970
+ text-decoration: none;
971
+ }
972
+
973
+ .ui-visual-focus {
974
+ box-shadow: 0 0 3px 1px rgb(94, 158, 214);
975
+ }
976
+ .ui-state-active,
977
+ .ui-widget-content .ui-state-active,
978
+ .ui-widget-header .ui-state-active,
979
+ a.ui-button:active,
980
+ .ui-button:active,
981
+ .ui-button.ui-state-active:hover {
982
+ border: 1px solid #aaaaaa;
983
+ background: #ffffff url("images/ui-bg_glass_65_ffffff_1x400.png") 50% 50% repeat-x;
984
+ font-weight: normal;
985
+ color: #212121;
986
+ }
987
+ .ui-icon-background,
988
+ .ui-state-active .ui-icon-background {
989
+ border: #aaaaaa;
990
+ background-color: #212121;
991
+ }
992
+ .ui-state-active a,
993
+ .ui-state-active a:link,
994
+ .ui-state-active a:visited {
995
+ color: #212121;
996
+ text-decoration: none;
997
+ }
998
+
999
+ /* Interaction Cues
1000
+ ----------------------------------*/
1001
+ .ui-state-highlight,
1002
+ .ui-widget-content .ui-state-highlight,
1003
+ .ui-widget-header .ui-state-highlight {
1004
+ border: 1px solid #fcefa1;
1005
+ background: #fbf9ee url("images/ui-bg_glass_55_fbf9ee_1x400.png") 50% 50% repeat-x;
1006
+ color: #363636;
1007
+ }
1008
+ .ui-state-checked {
1009
+ border: 1px solid #fcefa1;
1010
+ background: #fbf9ee;
1011
+ }
1012
+ .ui-state-highlight a,
1013
+ .ui-widget-content .ui-state-highlight a,
1014
+ .ui-widget-header .ui-state-highlight a {
1015
+ color: #363636;
1016
+ }
1017
+ .ui-state-error,
1018
+ .ui-widget-content .ui-state-error,
1019
+ .ui-widget-header .ui-state-error {
1020
+ border: 1px solid #cd0a0a;
1021
+ background: #fef1ec url("images/ui-bg_glass_95_fef1ec_1x400.png") 50% 50% repeat-x;
1022
+ color: #cd0a0a;
1023
+ }
1024
+ .ui-state-error a,
1025
+ .ui-widget-content .ui-state-error a,
1026
+ .ui-widget-header .ui-state-error a {
1027
+ color: #cd0a0a;
1028
+ }
1029
+ .ui-state-error-text,
1030
+ .ui-widget-content .ui-state-error-text,
1031
+ .ui-widget-header .ui-state-error-text {
1032
+ color: #cd0a0a;
1033
+ }
1034
+ .ui-priority-primary,
1035
+ .ui-widget-content .ui-priority-primary,
1036
+ .ui-widget-header .ui-priority-primary {
1037
+ font-weight: bold;
1038
+ }
1039
+ .ui-priority-secondary,
1040
+ .ui-widget-content .ui-priority-secondary,
1041
+ .ui-widget-header .ui-priority-secondary {
1042
+ opacity: .7;
1043
+ filter:Alpha(Opacity=70); /* support: IE8 */
1044
+ font-weight: normal;
1045
+ }
1046
+ .ui-state-disabled,
1047
+ .ui-widget-content .ui-state-disabled,
1048
+ .ui-widget-header .ui-state-disabled {
1049
+ opacity: .35;
1050
+ filter:Alpha(Opacity=35); /* support: IE8 */
1051
+ background-image: none;
1052
+ }
1053
+ .ui-state-disabled .ui-icon {
1054
+ filter:Alpha(Opacity=35); /* support: IE8 - See #6059 */
1055
+ }
1056
+
1057
+ /* Icons
1058
+ ----------------------------------*/
1059
+
1060
+ /* states and images */
1061
+ .ui-icon {
1062
+ width: 16px;
1063
+ height: 16px;
1064
+ }
1065
+ .ui-icon,
1066
+ .ui-widget-content .ui-icon {
1067
+ background-image: url("images/ui-icons_222222_256x240.png");
1068
+ }
1069
+ .ui-widget-header .ui-icon {
1070
+ background-image: url("images/ui-icons_222222_256x240.png");
1071
+ }
1072
+ .ui-state-hover .ui-icon,
1073
+ .ui-state-focus .ui-icon,
1074
+ .ui-button:hover .ui-icon,
1075
+ .ui-button:focus .ui-icon {
1076
+ background-image: url("images/ui-icons_454545_256x240.png");
1077
+ }
1078
+ .ui-state-active .ui-icon,
1079
+ .ui-button:active .ui-icon {
1080
+ background-image: url("images/ui-icons_454545_256x240.png");
1081
+ }
1082
+ .ui-state-highlight .ui-icon,
1083
+ .ui-button .ui-state-highlight.ui-icon {
1084
+ background-image: url("images/ui-icons_2e83ff_256x240.png");
1085
+ }
1086
+ .ui-state-error .ui-icon,
1087
+ .ui-state-error-text .ui-icon {
1088
+ background-image: url("images/ui-icons_cd0a0a_256x240.png");
1089
+ }
1090
+ .ui-button .ui-icon {
1091
+ background-image: url("images/ui-icons_888888_256x240.png");
1092
+ }
1093
+
1094
+ /* positioning */
1095
+ .ui-icon-blank { background-position: 16px 16px; }
1096
+ .ui-icon-caret-1-n { background-position: 0 0; }
1097
+ .ui-icon-caret-1-ne { background-position: -16px 0; }
1098
+ .ui-icon-caret-1-e { background-position: -32px 0; }
1099
+ .ui-icon-caret-1-se { background-position: -48px 0; }
1100
+ .ui-icon-caret-1-s { background-position: -65px 0; }
1101
+ .ui-icon-caret-1-sw { background-position: -80px 0; }
1102
+ .ui-icon-caret-1-w { background-position: -96px 0; }
1103
+ .ui-icon-caret-1-nw { background-position: -112px 0; }
1104
+ .ui-icon-caret-2-n-s { background-position: -128px 0; }
1105
+ .ui-icon-caret-2-e-w { background-position: -144px 0; }
1106
+ .ui-icon-triangle-1-n { background-position: 0 -16px; }
1107
+ .ui-icon-triangle-1-ne { background-position: -16px -16px; }
1108
+ .ui-icon-triangle-1-e { background-position: -32px -16px; }
1109
+ .ui-icon-triangle-1-se { background-position: -48px -16px; }
1110
+ .ui-icon-triangle-1-s { background-position: -65px -16px; }
1111
+ .ui-icon-triangle-1-sw { background-position: -80px -16px; }
1112
+ .ui-icon-triangle-1-w { background-position: -96px -16px; }
1113
+ .ui-icon-triangle-1-nw { background-position: -112px -16px; }
1114
+ .ui-icon-triangle-2-n-s { background-position: -128px -16px; }
1115
+ .ui-icon-triangle-2-e-w { background-position: -144px -16px; }
1116
+ .ui-icon-arrow-1-n { background-position: 0 -32px; }
1117
+ .ui-icon-arrow-1-ne { background-position: -16px -32px; }
1118
+ .ui-icon-arrow-1-e { background-position: -32px -32px; }
1119
+ .ui-icon-arrow-1-se { background-position: -48px -32px; }
1120
+ .ui-icon-arrow-1-s { background-position: -65px -32px; }
1121
+ .ui-icon-arrow-1-sw { background-position: -80px -32px; }
1122
+ .ui-icon-arrow-1-w { background-position: -96px -32px; }
1123
+ .ui-icon-arrow-1-nw { background-position: -112px -32px; }
1124
+ .ui-icon-arrow-2-n-s { background-position: -128px -32px; }
1125
+ .ui-icon-arrow-2-ne-sw { background-position: -144px -32px; }
1126
+ .ui-icon-arrow-2-e-w { background-position: -160px -32px; }
1127
+ .ui-icon-arrow-2-se-nw { background-position: -176px -32px; }
1128
+ .ui-icon-arrowstop-1-n { background-position: -192px -32px; }
1129
+ .ui-icon-arrowstop-1-e { background-position: -208px -32px; }
1130
+ .ui-icon-arrowstop-1-s { background-position: -224px -32px; }
1131
+ .ui-icon-arrowstop-1-w { background-position: -240px -32px; }
1132
+ .ui-icon-arrowthick-1-n { background-position: 1px -48px; }
1133
+ .ui-icon-arrowthick-1-ne { background-position: -16px -48px; }
1134
+ .ui-icon-arrowthick-1-e { background-position: -32px -48px; }
1135
+ .ui-icon-arrowthick-1-se { background-position: -48px -48px; }
1136
+ .ui-icon-arrowthick-1-s { background-position: -64px -48px; }
1137
+ .ui-icon-arrowthick-1-sw { background-position: -80px -48px; }
1138
+ .ui-icon-arrowthick-1-w { background-position: -96px -48px; }
1139
+ .ui-icon-arrowthick-1-nw { background-position: -112px -48px; }
1140
+ .ui-icon-arrowthick-2-n-s { background-position: -128px -48px; }
1141
+ .ui-icon-arrowthick-2-ne-sw { background-position: -144px -48px; }
1142
+ .ui-icon-arrowthick-2-e-w { background-position: -160px -48px; }
1143
+ .ui-icon-arrowthick-2-se-nw { background-position: -176px -48px; }
1144
+ .ui-icon-arrowthickstop-1-n { background-position: -192px -48px; }
1145
+ .ui-icon-arrowthickstop-1-e { background-position: -208px -48px; }
1146
+ .ui-icon-arrowthickstop-1-s { background-position: -224px -48px; }
1147
+ .ui-icon-arrowthickstop-1-w { background-position: -240px -48px; }
1148
+ .ui-icon-arrowreturnthick-1-w { background-position: 0 -64px; }
1149
+ .ui-icon-arrowreturnthick-1-n { background-position: -16px -64px; }
1150
+ .ui-icon-arrowreturnthick-1-e { background-position: -32px -64px; }
1151
+ .ui-icon-arrowreturnthick-1-s { background-position: -48px -64px; }
1152
+ .ui-icon-arrowreturn-1-w { background-position: -64px -64px; }
1153
+ .ui-icon-arrowreturn-1-n { background-position: -80px -64px; }
1154
+ .ui-icon-arrowreturn-1-e { background-position: -96px -64px; }
1155
+ .ui-icon-arrowreturn-1-s { background-position: -112px -64px; }
1156
+ .ui-icon-arrowrefresh-1-w { background-position: -128px -64px; }
1157
+ .ui-icon-arrowrefresh-1-n { background-position: -144px -64px; }
1158
+ .ui-icon-arrowrefresh-1-e { background-position: -160px -64px; }
1159
+ .ui-icon-arrowrefresh-1-s { background-position: -176px -64px; }
1160
+ .ui-icon-arrow-4 { background-position: 0 -80px; }
1161
+ .ui-icon-arrow-4-diag { background-position: -16px -80px; }
1162
+ .ui-icon-extlink { background-position: -32px -80px; }
1163
+ .ui-icon-newwin { background-position: -48px -80px; }
1164
+ .ui-icon-refresh { background-position: -64px -80px; }
1165
+ .ui-icon-shuffle { background-position: -80px -80px; }
1166
+ .ui-icon-transfer-e-w { background-position: -96px -80px; }
1167
+ .ui-icon-transferthick-e-w { background-position: -112px -80px; }
1168
+ .ui-icon-folder-collapsed { background-position: 0 -96px; }
1169
+ .ui-icon-folder-open { background-position: -16px -96px; }
1170
+ .ui-icon-document { background-position: -32px -96px; }
1171
+ .ui-icon-document-b { background-position: -48px -96px; }
1172
+ .ui-icon-note { background-position: -64px -96px; }
1173
+ .ui-icon-mail-closed { background-position: -80px -96px; }
1174
+ .ui-icon-mail-open { background-position: -96px -96px; }
1175
+ .ui-icon-suitcase { background-position: -112px -96px; }
1176
+ .ui-icon-comment { background-position: -128px -96px; }
1177
+ .ui-icon-person { background-position: -144px -96px; }
1178
+ .ui-icon-print { background-position: -160px -96px; }
1179
+ .ui-icon-trash { background-position: -176px -96px; }
1180
+ .ui-icon-locked { background-position: -192px -96px; }
1181
+ .ui-icon-unlocked { background-position: -208px -96px; }
1182
+ .ui-icon-bookmark { background-position: -224px -96px; }
1183
+ .ui-icon-tag { background-position: -240px -96px; }
1184
+ .ui-icon-home { background-position: 0 -112px; }
1185
+ .ui-icon-flag { background-position: -16px -112px; }
1186
+ .ui-icon-calendar { background-position: -32px -112px; }
1187
+ .ui-icon-cart { background-position: -48px -112px; }
1188
+ .ui-icon-pencil { background-position: -64px -112px; }
1189
+ .ui-icon-clock { background-position: -80px -112px; }
1190
+ .ui-icon-disk { background-position: -96px -112px; }
1191
+ .ui-icon-calculator { background-position: -112px -112px; }
1192
+ .ui-icon-zoomin { background-position: -128px -112px; }
1193
+ .ui-icon-zoomout { background-position: -144px -112px; }
1194
+ .ui-icon-search { background-position: -160px -112px; }
1195
+ .ui-icon-wrench { background-position: -176px -112px; }
1196
+ .ui-icon-gear { background-position: -192px -112px; }
1197
+ .ui-icon-heart { background-position: -208px -112px; }
1198
+ .ui-icon-star { background-position: -224px -112px; }
1199
+ .ui-icon-link { background-position: -240px -112px; }
1200
+ .ui-icon-cancel { background-position: 0 -128px; }
1201
+ .ui-icon-plus { background-position: -16px -128px; }
1202
+ .ui-icon-plusthick { background-position: -32px -128px; }
1203
+ .ui-icon-minus { background-position: -48px -128px; }
1204
+ .ui-icon-minusthick { background-position: -64px -128px; }
1205
+ .ui-icon-close { background-position: -80px -128px; }
1206
+ .ui-icon-closethick { background-position: -96px -128px; }
1207
+ .ui-icon-key { background-position: -112px -128px; }
1208
+ .ui-icon-lightbulb { background-position: -128px -128px; }
1209
+ .ui-icon-scissors { background-position: -144px -128px; }
1210
+ .ui-icon-clipboard { background-position: -160px -128px; }
1211
+ .ui-icon-copy { background-position: -176px -128px; }
1212
+ .ui-icon-contact { background-position: -192px -128px; }
1213
+ .ui-icon-image { background-position: -208px -128px; }
1214
+ .ui-icon-video { background-position: -224px -128px; }
1215
+ .ui-icon-script { background-position: -240px -128px; }
1216
+ .ui-icon-alert { background-position: 0 -144px; }
1217
+ .ui-icon-info { background-position: -16px -144px; }
1218
+ .ui-icon-notice { background-position: -32px -144px; }
1219
+ .ui-icon-help { background-position: -48px -144px; }
1220
+ .ui-icon-check { background-position: -64px -144px; }
1221
+ .ui-icon-bullet { background-position: -80px -144px; }
1222
+ .ui-icon-radio-on { background-position: -96px -144px; }
1223
+ .ui-icon-radio-off { background-position: -112px -144px; }
1224
+ .ui-icon-pin-w { background-position: -128px -144px; }
1225
+ .ui-icon-pin-s { background-position: -144px -144px; }
1226
+ .ui-icon-play { background-position: 0 -160px; }
1227
+ .ui-icon-pause { background-position: -16px -160px; }
1228
+ .ui-icon-seek-next { background-position: -32px -160px; }
1229
+ .ui-icon-seek-prev { background-position: -48px -160px; }
1230
+ .ui-icon-seek-end { background-position: -64px -160px; }
1231
+ .ui-icon-seek-start { background-position: -80px -160px; }
1232
+ /* ui-icon-seek-first is deprecated, use ui-icon-seek-start instead */
1233
+ .ui-icon-seek-first { background-position: -80px -160px; }
1234
+ .ui-icon-stop { background-position: -96px -160px; }
1235
+ .ui-icon-eject { background-position: -112px -160px; }
1236
+ .ui-icon-volume-off { background-position: -128px -160px; }
1237
+ .ui-icon-volume-on { background-position: -144px -160px; }
1238
+ .ui-icon-power { background-position: 0 -176px; }
1239
+ .ui-icon-signal-diag { background-position: -16px -176px; }
1240
+ .ui-icon-signal { background-position: -32px -176px; }
1241
+ .ui-icon-battery-0 { background-position: -48px -176px; }
1242
+ .ui-icon-battery-1 { background-position: -64px -176px; }
1243
+ .ui-icon-battery-2 { background-position: -80px -176px; }
1244
+ .ui-icon-battery-3 { background-position: -96px -176px; }
1245
+ .ui-icon-circle-plus { background-position: 0 -192px; }
1246
+ .ui-icon-circle-minus { background-position: -16px -192px; }
1247
+ .ui-icon-circle-close { background-position: -32px -192px; }
1248
+ .ui-icon-circle-triangle-e { background-position: -48px -192px; }
1249
+ .ui-icon-circle-triangle-s { background-position: -64px -192px; }
1250
+ .ui-icon-circle-triangle-w { background-position: -80px -192px; }
1251
+ .ui-icon-circle-triangle-n { background-position: -96px -192px; }
1252
+ .ui-icon-circle-arrow-e { background-position: -112px -192px; }
1253
+ .ui-icon-circle-arrow-s { background-position: -128px -192px; }
1254
+ .ui-icon-circle-arrow-w { background-position: -144px -192px; }
1255
+ .ui-icon-circle-arrow-n { background-position: -160px -192px; }
1256
+ .ui-icon-circle-zoomin { background-position: -176px -192px; }
1257
+ .ui-icon-circle-zoomout { background-position: -192px -192px; }
1258
+ .ui-icon-circle-check { background-position: -208px -192px; }
1259
+ .ui-icon-circlesmall-plus { background-position: 0 -208px; }
1260
+ .ui-icon-circlesmall-minus { background-position: -16px -208px; }
1261
+ .ui-icon-circlesmall-close { background-position: -32px -208px; }
1262
+ .ui-icon-squaresmall-plus { background-position: -48px -208px; }
1263
+ .ui-icon-squaresmall-minus { background-position: -64px -208px; }
1264
+ .ui-icon-squaresmall-close { background-position: -80px -208px; }
1265
+ .ui-icon-grip-dotted-vertical { background-position: 0 -224px; }
1266
+ .ui-icon-grip-dotted-horizontal { background-position: -16px -224px; }
1267
+ .ui-icon-grip-solid-vertical { background-position: -32px -224px; }
1268
+ .ui-icon-grip-solid-horizontal { background-position: -48px -224px; }
1269
+ .ui-icon-gripsmall-diagonal-se { background-position: -64px -224px; }
1270
+ .ui-icon-grip-diagonal-se { background-position: -80px -224px; }
1271
+
1272
+
1273
+ /* Misc visuals
1274
+ ----------------------------------*/
1275
+
1276
+ /* Corner radius */
1277
+ .ui-corner-all,
1278
+ .ui-corner-top,
1279
+ .ui-corner-left,
1280
+ .ui-corner-tl {
1281
+ border-top-left-radius: 4px;
1282
+ }
1283
+ .ui-corner-all,
1284
+ .ui-corner-top,
1285
+ .ui-corner-right,
1286
+ .ui-corner-tr {
1287
+ border-top-right-radius: 4px;
1288
+ }
1289
+ .ui-corner-all,
1290
+ .ui-corner-bottom,
1291
+ .ui-corner-left,
1292
+ .ui-corner-bl {
1293
+ border-bottom-left-radius: 4px;
1294
+ }
1295
+ .ui-corner-all,
1296
+ .ui-corner-bottom,
1297
+ .ui-corner-right,
1298
+ .ui-corner-br {
1299
+ border-bottom-right-radius: 4px;
1300
+ }
1301
+
1302
+ /* Overlays */
1303
+ .ui-widget-overlay {
1304
+ background: #aaaaaa;
1305
+ opacity: .3;
1306
+ filter: Alpha(Opacity=30); /* support: IE8 */
1307
+ }
1308
+ .ui-widget-shadow {
1309
+ -webkit-box-shadow: -8px -8px 8px #aaaaaa;
1310
+ box-shadow: -8px -8px 8px #aaaaaa;
1311
+ }
assets/css/lib/jquery-ui/jquery-ui.min.css ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
1
+ /*! jQuery UI - v1.12.1 - 2016-09-14
2
+ * http://jqueryui.com
3
+ * Includes: core.css, accordion.css, autocomplete.css, menu.css, button.css, controlgroup.css, checkboxradio.css, datepicker.css, dialog.css, draggable.css, resizable.css, progressbar.css, selectable.css, selectmenu.css, slider.css, sortable.css, spinner.css, tabs.css, tooltip.css, theme.css
4
+ * To view and modify this theme, visit http://jqueryui.com/themeroller/?ffDefault=Verdana%2CArial%2Csans-serif&fwDefault=normal&fsDefault=1.1em&cornerRadius=4px&bgColorHeader=cccccc&bgTextureHeader=highlight_soft&bgImgOpacityHeader=75&borderColorHeader=aaaaaa&fcHeader=222222&iconColorHeader=222222&bgColorContent=ffffff&bgTextureContent=flat&bgImgOpacityContent=75&borderColorContent=aaaaaa&fcContent=222222&iconColorContent=222222&bgColorDefault=e6e6e6&bgTextureDefault=glass&bgImgOpacityDefault=75&borderColorDefault=d3d3d3&fcDefault=555555&iconColorDefault=888888&bgColorHover=dadada&bgTextureHover=glass&bgImgOpacityHover=75&borderColorHover=999999&fcHover=212121&iconColorHover=454545&bgColorActive=ffffff&bgTextureActive=glass&bgImgOpacityActive=65&borderColorActive=aaaaaa&fcActive=212121&iconColorActive=454545&bgColorHighlight=fbf9ee&bgTextureHighlight=glass&bgImgOpacityHighlight=55&borderColorHighlight=fcefa1&fcHighlight=363636&iconColorHighlight=2e83ff&bgColorError=fef1ec&bgTextureError=glass&bgImgOpacityError=95&borderColorError=cd0a0a&fcError=cd0a0a&iconColorError=cd0a0a&bgColorOverlay=aaaaaa&bgTextureOverlay=flat&bgImgOpacityOverlay=0&opacityOverlay=30&bgColorShadow=aaaaaa&bgTextureShadow=flat&bgImgOpacityShadow=0&opacityShadow=30&thicknessShadow=8px&offsetTopShadow=-8px&offsetLeftShadow=-8px&cornerRadiusShadow=8px
5
+ * Copyright jQuery Foundation and other contributors; Licensed MIT */
6
+
7
+ .ui-helper-hidden{display:none}.ui-helper-hidden-accessible{border:0;clip:rect(0 0 0 0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.ui-helper-reset{margin:0;padding:0;border:0;outline:0;line-height:1.3;text-decoration:none;font-size:100%;list-style:none}.ui-helper-clearfix:before,.ui-helper-clearfix:after{content:"";display:table;border-collapse:collapse}.ui-helper-clearfix:after{clear:both}.ui-helper-zfix{width:100%;height:100%;top:0;left:0;position:absolute;opacity:0;filter:Alpha(Opacity=0)}.ui-front{z-index:100}.ui-state-disabled{cursor:default!important;pointer-events:none}.ui-icon{display:inline-block;vertical-align:middle;margin-top:-.25em;position:relative;text-indent:-99999px;overflow:hidden;background-repeat:no-repeat}.ui-widget-icon-block{left:50%;margin-left:-8px;display:block}.ui-widget-overlay{position:fixed;top:0;left:0;width:100%;height:100%}.ui-accordion .ui-accordion-header{display:block;cursor:pointer;position:relative;margin:2px 0 0 0;padding:.5em .5em .5em .7em;font-size:100%}.ui-accordion .ui-accordion-content{padding:1em 2.2em;border-top:0;overflow:auto}.ui-autocomplete{position:absolute;top:0;left:0;cursor:default}.ui-menu{list-style:none;padding:0;margin:0;display:block;outline:0}.ui-menu .ui-menu{position:absolute}.ui-menu .ui-menu-item{margin:0;cursor:pointer;list-style-image:url("data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7")}.ui-menu .ui-menu-item-wrapper{position:relative;padding:3px 1em 3px .4em}.ui-menu .ui-menu-divider{margin:5px 0;height:0;font-size:0;line-height:0;border-width:1px 0 0 0}.ui-menu .ui-state-focus,.ui-menu .ui-state-active{margin:-1px}.ui-menu-icons{position:relative}.ui-menu-icons .ui-menu-item-wrapper{padding-left:2em}.ui-menu .ui-icon{position:absolute;top:0;bottom:0;left:.2em;margin:auto 0}.ui-menu .ui-menu-icon{left:auto;right:0}.ui-button{padding:.4em 1em;display:inline-block;position:relative;line-height:normal;margin-right:.1em;cursor:pointer;vertical-align:middle;text-align:center;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;overflow:visible}.ui-button,.ui-button:link,.ui-button:visited,.ui-button:hover,.ui-button:active{text-decoration:none}.ui-button-icon-only{width:2em;box-sizing:border-box;text-indent:-9999px;white-space:nowrap}input.ui-button.ui-button-icon-only{text-indent:0}.ui-button-icon-only .ui-icon{position:absolute;top:50%;left:50%;margin-top:-8px;margin-left:-8px}.ui-button.ui-icon-notext .ui-icon{padding:0;width:2.1em;height:2.1em;text-indent:-9999px;white-space:nowrap}input.ui-button.ui-icon-notext .ui-icon{width:auto;height:auto;text-indent:0;white-space:normal;padding:.4em 1em}input.ui-button::-moz-focus-inner,button.ui-button::-moz-focus-inner{border:0;padding:0}.ui-controlgroup{vertical-align:middle;display:inline-block}.ui-controlgroup > .ui-controlgroup-item{float:left;margin-left:0;margin-right:0}.ui-controlgroup > .ui-controlgroup-item:focus,.ui-controlgroup > .ui-controlgroup-item.ui-visual-focus{z-index:9999}.ui-controlgroup-vertical > .ui-controlgroup-item{display:block;float:none;width:100%;margin-top:0;margin-bottom:0;text-align:left}.ui-controlgroup-vertical .ui-controlgroup-item{box-sizing:border-box}.ui-controlgroup .ui-controlgroup-label{padding:.4em 1em}.ui-controlgroup .ui-controlgroup-label span{font-size:80%}.ui-controlgroup-horizontal .ui-controlgroup-label + .ui-controlgroup-item{border-left:none}.ui-controlgroup-vertical .ui-controlgroup-label + .ui-controlgroup-item{border-top:none}.ui-controlgroup-horizontal .ui-controlgroup-label.ui-widget-content{border-right:none}.ui-controlgroup-vertical .ui-controlgroup-label.ui-widget-content{border-bottom:none}.ui-controlgroup-vertical .ui-spinner-input{width:75%;width:calc( 100% - 2.4em )}.ui-controlgroup-vertical .ui-spinner .ui-spinner-up{border-top-style:solid}.ui-checkboxradio-label .ui-icon-background{box-shadow:inset 1px 1px 1px #ccc;border-radius:.12em;border:none}.ui-checkboxradio-radio-label .ui-icon-background{width:16px;height:16px;border-radius:1em;overflow:visible;border:none}.ui-checkboxradio-radio-label.ui-checkboxradio-checked .ui-icon,.ui-checkboxradio-radio-label.ui-checkboxradio-checked:hover .ui-icon{background-image:none;width:8px;height:8px;border-width:4px;border-style:solid}.ui-checkboxradio-disabled{pointer-events:none}.ui-datepicker{width:17em;padding:.2em .2em 0;display:none}.ui-datepicker .ui-datepicker-header{position:relative;padding:.2em 0}.ui-datepicker .ui-datepicker-prev,.ui-datepicker .ui-datepicker-next{position:absolute;top:2px;width:1.8em;height:1.8em}.ui-datepicker .ui-datepicker-prev-hover,.ui-datepicker .ui-datepicker-next-hover{top:1px}.ui-datepicker .ui-datepicker-prev{left:2px}.ui-datepicker .ui-datepicker-next{right:2px}.ui-datepicker .ui-datepicker-prev-hover{left:1px}.ui-datepicker .ui-datepicker-next-hover{right:1px}.ui-datepicker .ui-datepicker-prev span,.ui-datepicker .ui-datepicker-next span{display:block;position:absolute;left:50%;margin-left:-8px;top:50%;margin-top:-8px}.ui-datepicker .ui-datepicker-title{margin:0 2.3em;line-height:1.8em;text-align:center}.ui-datepicker .ui-datepicker-title select{font-size:1em;margin:1px 0}.ui-datepicker select.ui-datepicker-month,.ui-datepicker select.ui-datepicker-year{width:45%}.ui-datepicker table{width:100%;font-size:.9em;border-collapse:collapse;margin:0 0 .4em}.ui-datepicker th{padding:.7em .3em;text-align:center;font-weight:bold;border:0}.ui-datepicker td{border:0;padding:1px}.ui-datepicker td span,.ui-datepicker td a{display:block;padding:.2em;text-align:right;text-decoration:none}.ui-datepicker .ui-datepicker-buttonpane{background-image:none;margin:.7em 0 0 0;padding:0 .2em;border-left:0;border-right:0;border-bottom:0}.ui-datepicker .ui-datepicker-buttonpane button{float:right;margin:.5em .2em .4em;cursor:pointer;padding:.2em .6em .3em .6em;width:auto;overflow:visible}.ui-datepicker .ui-datepicker-buttonpane button.ui-datepicker-current{float:left}.ui-datepicker.ui-datepicker-multi{width:auto}.ui-datepicker-multi .ui-datepicker-group{float:left}.ui-datepicker-multi .ui-datepicker-group table{width:95%;margin:0 auto .4em}.ui-datepicker-multi-2 .ui-datepicker-group{width:50%}.ui-datepicker-multi-3 .ui-datepicker-group{width:33.3%}.ui-datepicker-multi-4 .ui-datepicker-group{width:25%}.ui-datepicker-multi .ui-datepicker-group-last .ui-datepicker-header,.ui-datepicker-multi .ui-datepicker-group-middle .ui-datepicker-header{border-left-width:0}.ui-datepicker-multi .ui-datepicker-buttonpane{clear:left}.ui-datepicker-row-break{clear:both;width:100%;font-size:0}.ui-datepicker-rtl{direction:rtl}.ui-datepicker-rtl .ui-datepicker-prev{right:2px;left:auto}.ui-datepicker-rtl .ui-datepicker-next{left:2px;right:auto}.ui-datepicker-rtl .ui-datepicker-prev:hover{right:1px;left:auto}.ui-datepicker-rtl .ui-datepicker-next:hover{left:1px;right:auto}.ui-datepicker-rtl .ui-datepicker-buttonpane{clear:right}.ui-datepicker-rtl .ui-datepicker-buttonpane button{float:left}.ui-datepicker-rtl .ui-datepicker-buttonpane button.ui-datepicker-current,.ui-datepicker-rtl .ui-datepicker-group{float:right}.ui-datepicker-rtl .ui-datepicker-group-last .ui-datepicker-header,.ui-datepicker-rtl .ui-datepicker-group-middle .ui-datepicker-header{border-right-width:0;border-left-width:1px}.ui-datepicker .ui-icon{display:block;text-indent:-99999px;overflow:hidden;background-repeat:no-repeat;left:.5em;top:.3em}.ui-dialog{position:absolute;top:0;left:0;padding:.2em;outline:0}.ui-dialog .ui-dialog-titlebar{padding:.4em 1em;position:relative}.ui-dialog .ui-dialog-title{float:left;margin:.1em 0;white-space:nowrap;width:90%;overflow:hidden;text-overflow:ellipsis}.ui-dialog .ui-dialog-titlebar-close{position:absolute;right:.3em;top:50%;width:20px;margin:-10px 0 0 0;padding:1px;height:20px}.ui-dialog .ui-dialog-content{position:relative;border:0;padding:.5em 1em;background:none;overflow:auto}.ui-dialog .ui-dialog-buttonpane{text-align:left;border-width:1px 0 0 0;background-image:none;margin-top:.5em;padding:.3em 1em .5em .4em}.ui-dialog .ui-dialog-buttonpane .ui-dialog-buttonset{float:right}.ui-dialog .ui-dialog-buttonpane button{margin:.5em .4em .5em 0;cursor:pointer}.ui-dialog .ui-resizable-n{height:2px;top:0}.ui-dialog .ui-resizable-e{width:2px;right:0}.ui-dialog .ui-resizable-s{height:2px;bottom:0}.ui-dialog .ui-resizable-w{width:2px;left:0}.ui-dialog .ui-resizable-se,.ui-dialog .ui-resizable-sw,.ui-dialog .ui-resizable-ne,.ui-dialog .ui-resizable-nw{width:7px;height:7px}.ui-dialog .ui-resizable-se{right:0;bottom:0}.ui-dialog .ui-resizable-sw{left:0;bottom:0}.ui-dialog .ui-resizable-ne{right:0;top:0}.ui-dialog .ui-resizable-nw{left:0;top:0}.ui-draggable .ui-dialog-titlebar{cursor:move}.ui-draggable-handle{-ms-touch-action:none;touch-action:none}.ui-resizable{position:relative}.ui-resizable-handle{position:absolute;font-size:0.1px;display:block;-ms-touch-action:none;touch-action:none}.ui-resizable-disabled .ui-resizable-handle,.ui-resizable-autohide .ui-resizable-handle{display:none}.ui-resizable-n{cursor:n-resize;height:7px;width:100%;top:-5px;left:0}.ui-resizable-s{cursor:s-resize;height:7px;width:100%;bottom:-5px;left:0}.ui-resizable-e{cursor:e-resize;width:7px;right:-5px;top:0;height:100%}.ui-resizable-w{cursor:w-resize;width:7px;left:-5px;top:0;height:100%}.ui-resizable-se{cursor:se-resize;width:12px;height:12px;right:1px;bottom:1px}.ui-resizable-sw{cursor:sw-resize;width:9px;height:9px;left:-5px;bottom:-5px}.ui-resizable-nw{cursor:nw-resize;width:9px;height:9px;left:-5px;top:-5px}.ui-resizable-ne{cursor:ne-resize;width:9px;height:9px;right:-5px;top:-5px}.ui-progressbar{height:2em;text-align:left;overflow:hidden}.ui-progressbar .ui-progressbar-value{margin:-1px;height:100%}.ui-progressbar .ui-progressbar-overlay{background:url("data:image/gif;base64,R0lGODlhKAAoAIABAAAAAP///yH/C05FVFNDQVBFMi4wAwEAAAAh+QQJAQABACwAAAAAKAAoAAACkYwNqXrdC52DS06a7MFZI+4FHBCKoDeWKXqymPqGqxvJrXZbMx7Ttc+w9XgU2FB3lOyQRWET2IFGiU9m1frDVpxZZc6bfHwv4c1YXP6k1Vdy292Fb6UkuvFtXpvWSzA+HycXJHUXiGYIiMg2R6W459gnWGfHNdjIqDWVqemH2ekpObkpOlppWUqZiqr6edqqWQAAIfkECQEAAQAsAAAAACgAKAAAApSMgZnGfaqcg1E2uuzDmmHUBR8Qil95hiPKqWn3aqtLsS18y7G1SzNeowWBENtQd+T1JktP05nzPTdJZlR6vUxNWWjV+vUWhWNkWFwxl9VpZRedYcflIOLafaa28XdsH/ynlcc1uPVDZxQIR0K25+cICCmoqCe5mGhZOfeYSUh5yJcJyrkZWWpaR8doJ2o4NYq62lAAACH5BAkBAAEALAAAAAAoACgAAAKVDI4Yy22ZnINRNqosw0Bv7i1gyHUkFj7oSaWlu3ovC8GxNso5fluz3qLVhBVeT/Lz7ZTHyxL5dDalQWPVOsQWtRnuwXaFTj9jVVh8pma9JjZ4zYSj5ZOyma7uuolffh+IR5aW97cHuBUXKGKXlKjn+DiHWMcYJah4N0lYCMlJOXipGRr5qdgoSTrqWSq6WFl2ypoaUAAAIfkECQEAAQAsAAAAACgAKAAAApaEb6HLgd/iO7FNWtcFWe+ufODGjRfoiJ2akShbueb0wtI50zm02pbvwfWEMWBQ1zKGlLIhskiEPm9R6vRXxV4ZzWT2yHOGpWMyorblKlNp8HmHEb/lCXjcW7bmtXP8Xt229OVWR1fod2eWqNfHuMjXCPkIGNileOiImVmCOEmoSfn3yXlJWmoHGhqp6ilYuWYpmTqKUgAAIfkECQEAAQAsAAAAACgAKAAAApiEH6kb58biQ3FNWtMFWW3eNVcojuFGfqnZqSebuS06w5V80/X02pKe8zFwP6EFWOT1lDFk8rGERh1TTNOocQ61Hm4Xm2VexUHpzjymViHrFbiELsefVrn6XKfnt2Q9G/+Xdie499XHd2g4h7ioOGhXGJboGAnXSBnoBwKYyfioubZJ2Hn0RuRZaflZOil56Zp6iioKSXpUAAAh+QQJAQABACwAAAAAKAAoAAACkoQRqRvnxuI7kU1a1UU5bd5tnSeOZXhmn5lWK3qNTWvRdQxP8qvaC+/yaYQzXO7BMvaUEmJRd3TsiMAgswmNYrSgZdYrTX6tSHGZO73ezuAw2uxuQ+BbeZfMxsexY35+/Qe4J1inV0g4x3WHuMhIl2jXOKT2Q+VU5fgoSUI52VfZyfkJGkha6jmY+aaYdirq+lQAACH5BAkBAAEALAAAAAAoACgAAAKWBIKpYe0L3YNKToqswUlvznigd4wiR4KhZrKt9Upqip61i9E3vMvxRdHlbEFiEXfk9YARYxOZZD6VQ2pUunBmtRXo1Lf8hMVVcNl8JafV38aM2/Fu5V16Bn63r6xt97j09+MXSFi4BniGFae3hzbH9+hYBzkpuUh5aZmHuanZOZgIuvbGiNeomCnaxxap2upaCZsq+1kAACH5BAkBAAEALAAAAAAoACgAAAKXjI8By5zf4kOxTVrXNVlv1X0d8IGZGKLnNpYtm8Lr9cqVeuOSvfOW79D9aDHizNhDJidFZhNydEahOaDH6nomtJjp1tutKoNWkvA6JqfRVLHU/QUfau9l2x7G54d1fl995xcIGAdXqMfBNadoYrhH+Mg2KBlpVpbluCiXmMnZ2Sh4GBqJ+ckIOqqJ6LmKSllZmsoq6wpQAAAh+QQJAQABACwAAAAAKAAoAAAClYx/oLvoxuJDkU1a1YUZbJ59nSd2ZXhWqbRa2/gF8Gu2DY3iqs7yrq+xBYEkYvFSM8aSSObE+ZgRl1BHFZNr7pRCavZ5BW2142hY3AN/zWtsmf12p9XxxFl2lpLn1rseztfXZjdIWIf2s5dItwjYKBgo9yg5pHgzJXTEeGlZuenpyPmpGQoKOWkYmSpaSnqKileI2FAAACH5BAkBAAEALAAAAAAoACgAAAKVjB+gu+jG4kORTVrVhRlsnn2dJ3ZleFaptFrb+CXmO9OozeL5VfP99HvAWhpiUdcwkpBH3825AwYdU8xTqlLGhtCosArKMpvfa1mMRae9VvWZfeB2XfPkeLmm18lUcBj+p5dnN8jXZ3YIGEhYuOUn45aoCDkp16hl5IjYJvjWKcnoGQpqyPlpOhr3aElaqrq56Bq7VAAAOw==");height:100%;filter:alpha(opacity=25);opacity:0.25}.ui-progressbar-indeterminate .ui-progressbar-value{background-image:none}.ui-selectable{-ms-touch-action:none;touch-action:none}.ui-selectable-helper{position:absolute;z-index:100;border:1px dotted black}.ui-selectmenu-menu{padding:0;margin:0;position:absolute;top:0;left:0;display:none}.ui-selectmenu-menu .ui-menu{overflow:auto;overflow-x:hidden;padding-bottom:1px}.ui-selectmenu-menu .ui-menu .ui-selectmenu-optgroup{font-size:1em;font-weight:bold;line-height:1.5;padding:2px 0.4em;margin:0.5em 0 0 0;height:auto;border:0}.ui-selectmenu-open{display:block}.ui-selectmenu-text{display:block;margin-right:20px;overflow:hidden;text-overflow:ellipsis}.ui-selectmenu-button.ui-button{text-align:left;white-space:nowrap;width:14em}.ui-selectmenu-icon.ui-icon{float:right;margin-top:0}.ui-slider{position:relative;text-align:left}.ui-slider .ui-slider-handle{position:absolute;z-index:2;width:1.2em;height:1.2em;cursor:default;-ms-touch-action:none;touch-action:none}.ui-slider .ui-slider-range{position:absolute;z-index:1;font-size:.7em;display:block;border:0;background-position:0 0}.ui-slider.ui-state-disabled .ui-slider-handle,.ui-slider.ui-state-disabled .ui-slider-range{filter:inherit}.ui-slider-horizontal{height:.8em}.ui-slider-horizontal .ui-slider-handle{top:-.3em;margin-left:-.6em}.ui-slider-horizontal .ui-slider-range{top:0;height:100%}.ui-slider-horizontal .ui-slider-range-min{left:0}.ui-slider-horizontal .ui-slider-range-max{right:0}.ui-slider-vertical{width:.8em;height:100px}.ui-slider-vertical .ui-slider-handle{left:-.3em;margin-left:0;margin-bottom:-.6em}.ui-slider-vertical .ui-slider-range{left:0;width:100%}.ui-slider-vertical .ui-slider-range-min{bottom:0}.ui-slider-vertical .ui-slider-range-max{top:0}.ui-sortable-handle{-ms-touch-action:none;touch-action:none}.ui-spinner{position:relative;display:inline-block;overflow:hidden;padding:0;vertical-align:middle}.ui-spinner-input{border:none;background:none;color:inherit;padding:.222em 0;margin:.2em 0;vertical-align:middle;margin-left:.4em;margin-right:2em}.ui-spinner-button{width:1.6em;height:50%;font-size:.5em;padding:0;margin:0;text-align:center;position:absolute;cursor:default;display:block;overflow:hidden;right:0}.ui-spinner a.ui-spinner-button{border-top-style:none;border-bottom-style:none;border-right-style:none}.ui-spinner-up{top:0}.ui-spinner-down{bottom:0}.ui-tabs{position:relative;padding:.2em}.ui-tabs .ui-tabs-nav{margin:0;padding:.2em .2em 0}.ui-tabs .ui-tabs-nav li{list-style:none;float:left;position:relative;top:0;margin:1px .2em 0 0;border-bottom-width:0;padding:0;white-space:nowrap}.ui-tabs .ui-tabs-nav .ui-tabs-anchor{float:left;padding:.5em 1em;text-decoration:none}.ui-tabs .ui-tabs-nav li.ui-tabs-active{margin-bottom:-1px;padding-bottom:1px}.ui-tabs .ui-tabs-nav li.ui-tabs-active .ui-tabs-anchor,.ui-tabs .ui-tabs-nav li.ui-state-disabled .ui-tabs-anchor,.ui-tabs .ui-tabs-nav li.ui-tabs-loading .ui-tabs-anchor{cursor:text}.ui-tabs-collapsible .ui-tabs-nav li.ui-tabs-active .ui-tabs-anchor{cursor:pointer}.ui-tabs .ui-tabs-panel{display:block;border-width:0;padding:1em 1.4em;background:none}.ui-tooltip{padding:8px;position:absolute;z-index:9999;max-width:300px}body .ui-tooltip{border-width:2px}.ui-widget{font-family:Verdana,Arial,sans-serif;font-size:1.1em}.ui-widget .ui-widget{font-size:1em}.ui-widget input,.ui-widget select,.ui-widget textarea,.ui-widget button{font-family:Verdana,Arial,sans-serif;font-size:1em}.ui-widget.ui-widget-content{border:1px solid #d3d3d3}.ui-widget-content{border:1px solid #aaa;background:#fff;color:#222}.ui-widget-content a{color:#222}.ui-widget-header{border:1px solid #aaa;background:#ccc url("images/ui-bg_highlight-soft_75_cccccc_1x100.png") 50% 50% repeat-x;color:#222;font-weight:bold}.ui-widget-header a{color:#222}.ui-state-default,.ui-widget-content .ui-state-default,.ui-widget-header .ui-state-default,.ui-button,html .ui-button.ui-state-disabled:hover,html .ui-button.ui-state-disabled:active{border:1px solid #d3d3d3;background:#e6e6e6 url("images/ui-bg_glass_75_e6e6e6_1x400.png") 50% 50% repeat-x;font-weight:normal;color:#555}.ui-state-default a,.ui-state-default a:link,.ui-state-default a:visited,a.ui-button,a:link.ui-button,a:visited.ui-button,.ui-button{color:#555;text-decoration:none}.ui-state-hover,.ui-widget-content .ui-state-hover,.ui-widget-header .ui-state-hover,.ui-state-focus,.ui-widget-content .ui-state-focus,.ui-widget-header .ui-state-focus,.ui-button:hover,.ui-button:focus{border:1px solid #999;background:#dadada url("images/ui-bg_glass_75_dadada_1x400.png") 50% 50% repeat-x;font-weight:normal;color:#212121}.ui-state-hover a,.ui-state-hover a:hover,.ui-state-hover a:link,.ui-state-hover a:visited,.ui-state-focus a,.ui-state-focus a:hover,.ui-state-focus a:link,.ui-state-focus a:visited,a.ui-button:hover,a.ui-button:focus{color:#212121;text-decoration:none}.ui-visual-focus{box-shadow:0 0 3px 1px rgb(94,158,214)}.ui-state-active,.ui-widget-content .ui-state-active,.ui-widget-header .ui-state-active,a.ui-button:active,.ui-button:active,.ui-button.ui-state-active:hover{border:1px solid #aaa;background:#fff url("images/ui-bg_glass_65_ffffff_1x400.png") 50% 50% repeat-x;font-weight:normal;color:#212121}.ui-icon-background,.ui-state-active .ui-icon-background{border:#aaa;background-color:#212121}.ui-state-active a,.ui-state-active a:link,.ui-state-active a:visited{color:#212121;text-decoration:none}.ui-state-highlight,.ui-widget-content .ui-state-highlight,.ui-widget-header .ui-state-highlight{border:1px solid #fcefa1;background:#fbf9ee url("images/ui-bg_glass_55_fbf9ee_1x400.png") 50% 50% repeat-x;color:#363636}.ui-state-checked{border:1px solid #fcefa1;background:#fbf9ee}.ui-state-highlight a,.ui-widget-content .ui-state-highlight a,.ui-widget-header .ui-state-highlight a{color:#363636}.ui-state-error,.ui-widget-content .ui-state-error,.ui-widget-header .ui-state-error{border:1px solid #cd0a0a;background:#fef1ec url("images/ui-bg_glass_95_fef1ec_1x400.png") 50% 50% repeat-x;color:#cd0a0a}.ui-state-error a,.ui-widget-content .ui-state-error a,.ui-widget-header .ui-state-error a{color:#cd0a0a}.ui-state-error-text,.ui-widget-content .ui-state-error-text,.ui-widget-header .ui-state-error-text{color:#cd0a0a}.ui-priority-primary,.ui-widget-content .ui-priority-primary,.ui-widget-header .ui-priority-primary{font-weight:bold}.ui-priority-secondary,.ui-widget-content .ui-priority-secondary,.ui-widget-header .ui-priority-secondary{opacity:.7;filter:Alpha(Opacity=70);font-weight:normal}.ui-state-disabled,.ui-widget-content .ui-state-disabled,.ui-widget-header .ui-state-disabled{opacity:.35;filter:Alpha(Opacity=35);background-image:none}.ui-state-disabled .ui-icon{filter:Alpha(Opacity=35)}.ui-icon{width:16px;height:16px}.ui-icon,.ui-widget-content .ui-icon{background-image:url("images/ui-icons_222222_256x240.png")}.ui-widget-header .ui-icon{background-image:url("images/ui-icons_222222_256x240.png")}.ui-state-hover .ui-icon,.ui-state-focus .ui-icon,.ui-button:hover .ui-icon,.ui-button:focus .ui-icon{background-image:url("images/ui-icons_454545_256x240.png")}.ui-state-active .ui-icon,.ui-button:active .ui-icon{background-image:url("images/ui-icons_454545_256x240.png")}.ui-state-highlight .ui-icon,.ui-button .ui-state-highlight.ui-icon{background-image:url("images/ui-icons_2e83ff_256x240.png")}.ui-state-error .ui-icon,.ui-state-error-text .ui-icon{background-image:url("images/ui-icons_cd0a0a_256x240.png")}.ui-button .ui-icon{background-image:url("images/ui-icons_888888_256x240.png")}.ui-icon-blank{background-position:16px 16px}.ui-icon-caret-1-n{background-position:0 0}.ui-icon-caret-1-ne{background-position:-16px 0}.ui-icon-caret-1-e{background-position:-32px 0}.ui-icon-caret-1-se{background-position:-48px 0}.ui-icon-caret-1-s{background-position:-65px 0}.ui-icon-caret-1-sw{background-position:-80px 0}.ui-icon-caret-1-w{background-position:-96px 0}.ui-icon-caret-1-nw{background-position:-112px 0}.ui-icon-caret-2-n-s{background-position:-128px 0}.ui-icon-caret-2-e-w{background-position:-144px 0}.ui-icon-triangle-1-n{background-position:0 -16px}.ui-icon-triangle-1-ne{background-position:-16px -16px}.ui-icon-triangle-1-e{background-position:-32px -16px}.ui-icon-triangle-1-se{background-position:-48px -16px}.ui-icon-triangle-1-s{background-position:-65px -16px}.ui-icon-triangle-1-sw{background-position:-80px -16px}.ui-icon-triangle-1-w{background-position:-96px -16px}.ui-icon-triangle-1-nw{background-position:-112px -16px}.ui-icon-triangle-2-n-s{background-position:-128px -16px}.ui-icon-triangle-2-e-w{background-position:-144px -16px}.ui-icon-arrow-1-n{background-position:0 -32px}.ui-icon-arrow-1-ne{background-position:-16px -32px}.ui-icon-arrow-1-e{background-position:-32px -32px}.ui-icon-arrow-1-se{background-position:-48px -32px}.ui-icon-arrow-1-s{background-position:-65px -32px}.ui-icon-arrow-1-sw{background-position:-80px -32px}.ui-icon-arrow-1-w{background-position:-96px -32px}.ui-icon-arrow-1-nw{background-position:-112px -32px}.ui-icon-arrow-2-n-s{background-position:-128px -32px}.ui-icon-arrow-2-ne-sw{background-position:-144px -32px}.ui-icon-arrow-2-e-w{background-position:-160px -32px}.ui-icon-arrow-2-se-nw{background-position:-176px -32px}.ui-icon-arrowstop-1-n{background-position:-192px -32px}.ui-icon-arrowstop-1-e{background-position:-208px -32px}.ui-icon-arrowstop-1-s{background-position:-224px -32px}.ui-icon-arrowstop-1-w{background-position:-240px -32px}.ui-icon-arrowthick-1-n{background-position:1px -48px}.ui-icon-arrowthick-1-ne{background-position:-16px -48px}.ui-icon-arrowthick-1-e{background-position:-32px -48px}.ui-icon-arrowthick-1-se{background-position:-48px -48px}.ui-icon-arrowthick-1-s{background-position:-64px -48px}.ui-icon-arrowthick-1-sw{background-position:-80px -48px}.ui-icon-arrowthick-1-w{background-position:-96px -48px}.ui-icon-arrowthick-1-nw{background-position:-112px -48px}.ui-icon-arrowthick-2-n-s{background-position:-128px -48px}.ui-icon-arrowthick-2-ne-sw{background-position:-144px -48px}.ui-icon-arrowthick-2-e-w{background-position:-160px -48px}.ui-icon-arrowthick-2-se-nw{background-position:-176px -48px}.ui-icon-arrowthickstop-1-n{background-position:-192px -48px}.ui-icon-arrowthickstop-1-e{background-position:-208px -48px}.ui-icon-arrowthickstop-1-s{background-position:-224px -48px}.ui-icon-arrowthickstop-1-w{background-position:-240px -48px}.ui-icon-arrowreturnthick-1-w{background-position:0 -64px}.ui-icon-arrowreturnthick-1-n{background-position:-16px -64px}.ui-icon-arrowreturnthick-1-e{background-position:-32px -64px}.ui-icon-arrowreturnthick-1-s{background-position:-48px -64px}.ui-icon-arrowreturn-1-w{background-position:-64px -64px}.ui-icon-arrowreturn-1-n{background-position:-80px -64px}.ui-icon-arrowreturn-1-e{background-position:-96px -64px}.ui-icon-arrowreturn-1-s{background-position:-112px -64px}.ui-icon-arrowrefresh-1-w{background-position:-128px -64px}.ui-icon-arrowrefresh-1-n{background-position:-144px -64px}.ui-icon-arrowrefresh-1-e{background-position:-160px -64px}.ui-icon-arrowrefresh-1-s{background-position:-176px -64px}.ui-icon-arrow-4{background-position:0 -80px}.ui-icon-arrow-4-diag{background-position:-16px -80px}.ui-icon-extlink{background-position:-32px -80px}.ui-icon-newwin{background-position:-48px -80px}.ui-icon-refresh{background-position:-64px -80px}.ui-icon-shuffle{background-position:-80px -80px}.ui-icon-transfer-e-w{background-position:-96px -80px}.ui-icon-transferthick-e-w{background-position:-112px -80px}.ui-icon-folder-collapsed{background-position:0 -96px}.ui-icon-folder-open{background-position:-16px -96px}.ui-icon-document{background-position:-32px -96px}.ui-icon-document-b{background-position:-48px -96px}.ui-icon-note{background-position:-64px -96px}.ui-icon-mail-closed{background-position:-80px -96px}.ui-icon-mail-open{background-position:-96px -96px}.ui-icon-suitcase{background-position:-112px -96px}.ui-icon-comment{background-position:-128px -96px}.ui-icon-person{background-position:-144px -96px}.ui-icon-print{background-position:-160px -96px}.ui-icon-trash{background-position:-176px -96px}.ui-icon-locked{background-position:-192px -96px}.ui-icon-unlocked{background-position:-208px -96px}.ui-icon-bookmark{background-position:-224px -96px}.ui-icon-tag{background-position:-240px -96px}.ui-icon-home{background-position:0 -112px}.ui-icon-flag{background-position:-16px -112px}.ui-icon-calendar{background-position:-32px -112px}.ui-icon-cart{background-position:-48px -112px}.ui-icon-pencil{background-position:-64px -112px}.ui-icon-clock{background-position:-80px -112px}.ui-icon-disk{background-position:-96px -112px}.ui-icon-calculator{background-position:-112px -112px}.ui-icon-zoomin{background-position:-128px -112px}.ui-icon-zoomout{background-position:-144px -112px}.ui-icon-search{background-position:-160px -112px}.ui-icon-wrench{background-position:-176px -112px}.ui-icon-gear{background-position:-192px -112px}.ui-icon-heart{background-position:-208px -112px}.ui-icon-star{background-position:-224px -112px}.ui-icon-link{background-position:-240px -112px}.ui-icon-cancel{background-position:0 -128px}.ui-icon-plus{background-position:-16px -128px}.ui-icon-plusthick{background-position:-32px -128px}.ui-icon-minus{background-position:-48px -128px}.ui-icon-minusthick{background-position:-64px -128px}.ui-icon-close{background-position:-80px -128px}.ui-icon-closethick{background-position:-96px -128px}.ui-icon-key{background-position:-112px -128px}.ui-icon-lightbulb{background-position:-128px -128px}.ui-icon-scissors{background-position:-144px -128px}.ui-icon-clipboard{background-position:-160px -128px}.ui-icon-copy{background-position:-176px -128px}.ui-icon-contact{background-position:-192px -128px}.ui-icon-image{background-position:-208px -128px}.ui-icon-video{background-position:-224px -128px}.ui-icon-script{background-position:-240px -128px}.ui-icon-alert{background-position:0 -144px}.ui-icon-info{background-position:-16px -144px}.ui-icon-notice{background-position:-32px -144px}.ui-icon-help{background-position:-48px -144px}.ui-icon-check{background-position:-64px -144px}.ui-icon-bullet{background-position:-80px -144px}.ui-icon-radio-on{background-position:-96px -144px}.ui-icon-radio-off{background-position:-112px -144px}.ui-icon-pin-w{background-position:-128px -144px}.ui-icon-pin-s{background-position:-144px -144px}.ui-icon-play{background-position:0 -160px}.ui-icon-pause{background-position:-16px -160px}.ui-icon-seek-next{background-position:-32px -160px}.ui-icon-seek-prev{background-position:-48px -160px}.ui-icon-seek-end{background-position:-64px -160px}.ui-icon-seek-start{background-position:-80px -160px}.ui-icon-seek-first{background-position:-80px -160px}.ui-icon-stop{background-position:-96px -160px}.ui-icon-eject{background-position:-112px -160px}.ui-icon-volume-off{background-position:-128px -160px}.ui-icon-volume-on{background-position:-144px -160px}.ui-icon-power{background-position:0 -176px}.ui-icon-signal-diag{background-position:-16px -176px}.ui-icon-signal{background-position:-32px -176px}.ui-icon-battery-0{background-position:-48px -176px}.ui-icon-battery-1{background-position:-64px -176px}.ui-icon-battery-2{background-position:-80px -176px}.ui-icon-battery-3{background-position:-96px -176px}.ui-icon-circle-plus{background-position:0 -192px}.ui-icon-circle-minus{background-position:-16px -192px}.ui-icon-circle-close{background-position:-32px -192px}.ui-icon-circle-triangle-e{background-position:-48px -192px}.ui-icon-circle-triangle-s{background-position:-64px -192px}.ui-icon-circle-triangle-w{background-position:-80px -192px}.ui-icon-circle-triangle-n{background-position:-96px -192px}.ui-icon-circle-arrow-e{background-position:-112px -192px}.ui-icon-circle-arrow-s{background-position:-128px -192px}.ui-icon-circle-arrow-w{background-position:-144px -192px}.ui-icon-circle-arrow-n{background-position:-160px -192px}.ui-icon-circle-zoomin{background-position:-176px -192px}.ui-icon-circle-zoomout{background-position:-192px -192px}.ui-icon-circle-check{background-position:-208px -192px}.ui-icon-circlesmall-plus{background-position:0 -208px}.ui-icon-circlesmall-minus{background-position:-16px -208px}.ui-icon-circlesmall-close{background-position:-32px -208px}.ui-icon-squaresmall-plus{background-position:-48px -208px}.ui-icon-squaresmall-minus{background-position:-64px -208px}.ui-icon-squaresmall-close{background-position:-80px -208px}.ui-icon-grip-dotted-vertical{background-position:0 -224px}.ui-icon-grip-dotted-horizontal{background-position:-16px -224px}.ui-icon-grip-solid-vertical{background-position:-32px -224px}.ui-icon-grip-solid-horizontal{background-position:-48px -224px}.ui-icon-gripsmall-diagonal-se{background-position:-64px -224px}.ui-icon-grip-diagonal-se{background-position:-80px -224px}.ui-corner-all,.ui-corner-top,.ui-corner-left,.ui-corner-tl{border-top-left-radius:4px}.ui-corner-all,.ui-corner-top,.ui-corner-right,.ui-corner-tr{border-top-right-radius:4px}.ui-corner-all,.ui-corner-bottom,.ui-corner-left,.ui-corner-bl{border-bottom-left-radius:4px}.ui-corner-all,.ui-corner-bottom,.ui-corner-right,.ui-corner-br{border-bottom-right-radius:4px}.ui-widget-overlay{background:#aaa;opacity:.3;filter:Alpha(Opacity=30)}.ui-widget-shadow{-webkit-box-shadow:-8px -8px 8px #aaa;box-shadow:-8px -8px 8px #aaa}
assets/css/lib/jquery-ui/theme.css ADDED
@@ -0,0 +1,443 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /*!
2
+ * jQuery UI CSS Framework 1.12.1
3
+ * http://jqueryui.com
4
+ *
5
+ * Copyright jQuery Foundation and other contributors
6
+ * Released under the MIT license.
7
+ * http://jquery.org/license
8
+ *
9
+ * http://api.jqueryui.com/category/theming/
10
+ *
11
+ * To view and modify this theme, visit http://jqueryui.com/themeroller/?ffDefault=Verdana%2CArial%2Csans-serif&fwDefault=normal&fsDefault=1.1em&cornerRadius=4px&bgColorHeader=cccccc&bgTextureHeader=highlight_soft&bgImgOpacityHeader=75&borderColorHeader=aaaaaa&fcHeader=222222&iconColorHeader=222222&bgColorContent=ffffff&bgTextureContent=flat&bgImgOpacityContent=75&borderColorContent=aaaaaa&fcContent=222222&iconColorContent=222222&bgColorDefault=e6e6e6&bgTextureDefault=glass&bgImgOpacityDefault=75&borderColorDefault=d3d3d3&fcDefault=555555&iconColorDefault=888888&bgColorHover=dadada&bgTextureHover=glass&bgImgOpacityHover=75&borderColorHover=999999&fcHover=212121&iconColorHover=454545&bgColorActive=ffffff&bgTextureActive=glass&bgImgOpacityActive=65&borderColorActive=aaaaaa&fcActive=212121&iconColorActive=454545&bgColorHighlight=fbf9ee&bgTextureHighlight=glass&bgImgOpacityHighlight=55&borderColorHighlight=fcefa1&fcHighlight=363636&iconColorHighlight=2e83ff&bgColorError=fef1ec&bgTextureError=glass&bgImgOpacityError=95&borderColorError=cd0a0a&fcError=cd0a0a&iconColorError=cd0a0a&bgColorOverlay=aaaaaa&bgTextureOverlay=flat&bgImgOpacityOverlay=0&opacityOverlay=30&bgColorShadow=aaaaaa&bgTextureShadow=flat&bgImgOpacityShadow=0&opacityShadow=30&thicknessShadow=8px&offsetTopShadow=-8px&offsetLeftShadow=-8px&cornerRadiusShadow=8px
12
+ */
13
+
14
+
15
+ /* Component containers
16
+ ----------------------------------*/
17
+ .ui-widget {
18
+ font-family: Verdana,Arial,sans-serif;
19
+ font-size: 1.1em;
20
+ }
21
+ .ui-widget .ui-widget {
22
+ font-size: 1em;
23
+ }
24
+ .ui-widget input,
25
+ .ui-widget select,
26
+ .ui-widget textarea,
27
+ .ui-widget button {
28
+ font-family: Verdana,Arial,sans-serif;
29
+ font-size: 1em;
30
+ }
31
+ .ui-widget.ui-widget-content {
32
+ border: 1px solid #d3d3d3;
33
+ }
34
+ .ui-widget-content {
35
+ border: 1px solid #aaaaaa;
36
+ background: #ffffff;
37
+ color: #222222;
38
+ }
39
+ .ui-widget-content a {
40
+ color: #222222;
41
+ }
42
+ .ui-widget-header {
43
+ border: 1px solid #aaaaaa;
44
+ background: #cccccc url("images/ui-bg_highlight-soft_75_cccccc_1x100.png") 50% 50% repeat-x;
45
+ color: #222222;
46
+ font-weight: bold;
47
+ }
48
+ .ui-widget-header a {
49
+ color: #222222;
50
+ }
51
+
52
+ /* Interaction states
53
+ ----------------------------------*/
54
+ .ui-state-default,
55
+ .ui-widget-content .ui-state-default,
56
+ .ui-widget-header .ui-state-default,
57
+ .ui-button,
58
+
59
+ /* We use html here because we need a greater specificity to make sure disabled
60
+ works properly when clicked or hovered */
61
+ html .ui-button.ui-state-disabled:hover,
62
+ html .ui-button.ui-state-disabled:active {
63
+ border: 1px solid #d3d3d3;
64
+ background: #e6e6e6 url("images/ui-bg_glass_75_e6e6e6_1x400.png") 50% 50% repeat-x;
65
+ font-weight: normal;
66
+ color: #555555;
67
+ }
68
+ .ui-state-default a,
69
+ .ui-state-default a:link,
70
+ .ui-state-default a:visited,
71
+ a.ui-button,
72
+ a:link.ui-button,
73
+ a:visited.ui-button,
74
+ .ui-button {
75
+ color: #555555;
76
+ text-decoration: none;
77
+ }
78
+ .ui-state-hover,
79
+ .ui-widget-content .ui-state-hover,
80
+ .ui-widget-header .ui-state-hover,
81
+ .ui-state-focus,
82
+ .ui-widget-content .ui-state-focus,
83
+ .ui-widget-header .ui-state-focus,
84
+ .ui-button:hover,
85
+ .ui-button:focus {
86
+ border: 1px solid #999999;
87
+ background: #dadada url("images/ui-bg_glass_75_dadada_1x400.png") 50% 50% repeat-x;
88
+ font-weight: normal;
89
+ color: #212121;
90
+ }
91
+ .ui-state-hover a,
92
+ .ui-state-hover a:hover,
93
+ .ui-state-hover a:link,
94
+ .ui-state-hover a:visited,
95
+ .ui-state-focus a,
96
+ .ui-state-focus a:hover,
97
+ .ui-state-focus a:link,
98
+ .ui-state-focus a:visited,
99
+ a.ui-button:hover,
100
+ a.ui-button:focus {
101
+ color: #212121;
102
+ text-decoration: none;
103
+ }
104
+
105
+ .ui-visual-focus {
106
+ box-shadow: 0 0 3px 1px rgb(94, 158, 214);
107
+ }
108
+ .ui-state-active,
109
+ .ui-widget-content .ui-state-active,
110
+ .ui-widget-header .ui-state-active,
111
+ a.ui-button:active,
112
+ .ui-button:active,
113
+ .ui-button.ui-state-active:hover {
114
+ border: 1px solid #aaaaaa;
115
+ background: #ffffff url("images/ui-bg_glass_65_ffffff_1x400.png") 50% 50% repeat-x;
116
+ font-weight: normal;
117
+ color: #212121;
118
+ }
119
+ .ui-icon-background,
120
+ .ui-state-active .ui-icon-background {
121
+ border: #aaaaaa;
122
+ background-color: #212121;
123
+ }
124
+ .ui-state-active a,
125
+ .ui-state-active a:link,
126
+ .ui-state-active a:visited {
127
+ color: #212121;
128
+ text-decoration: none;
129
+ }
130
+
131
+ /* Interaction Cues
132
+ ----------------------------------*/
133
+ .ui-state-highlight,
134
+ .ui-widget-content .ui-state-highlight,
135
+ .ui-widget-header .ui-state-highlight {
136
+ border: 1px solid #fcefa1;
137
+ background: #fbf9ee url("images/ui-bg_glass_55_fbf9ee_1x400.png") 50% 50% repeat-x;
138
+ color: #363636;
139
+ }
140
+ .ui-state-checked {
141
+ border: 1px solid #fcefa1;
142
+ background: #fbf9ee;
143
+ }
144
+ .ui-state-highlight a,
145
+ .ui-widget-content .ui-state-highlight a,
146
+ .ui-widget-header .ui-state-highlight a {
147
+ color: #363636;
148
+ }
149
+ .ui-state-error,
150
+ .ui-widget-content .ui-state-error,
151
+ .ui-widget-header .ui-state-error {
152
+ border: 1px solid #cd0a0a;
153
+ background: #fef1ec url("images/ui-bg_glass_95_fef1ec_1x400.png") 50% 50% repeat-x;
154
+ color: #cd0a0a;
155
+ }
156
+ .ui-state-error a,
157
+ .ui-widget-content .ui-state-error a,
158
+ .ui-widget-header .ui-state-error a {
159
+ color: #cd0a0a;
160
+ }
161
+ .ui-state-error-text,
162
+ .ui-widget-content .ui-state-error-text,
163
+ .ui-widget-header .ui-state-error-text {
164
+ color: #cd0a0a;
165
+ }
166
+ .ui-priority-primary,
167
+ .ui-widget-content .ui-priority-primary,
168
+ .ui-widget-header .ui-priority-primary {
169
+ font-weight: bold;
170
+ }
171
+ .ui-priority-secondary,
172
+ .ui-widget-content .ui-priority-secondary,
173
+ .ui-widget-header .ui-priority-secondary {
174
+ opacity: .7;
175
+ filter:Alpha(Opacity=70); /* support: IE8 */
176
+ font-weight: normal;
177
+ }
178
+ .ui-state-disabled,
179
+ .ui-widget-content .ui-state-disabled,
180
+ .ui-widget-header .ui-state-disabled {
181
+ opacity: .35;
182
+ filter:Alpha(Opacity=35); /* support: IE8 */
183
+ background-image: none;
184
+ }
185
+ .ui-state-disabled .ui-icon {
186
+ filter:Alpha(Opacity=35); /* support: IE8 - See #6059 */
187
+ }
188
+
189
+ /* Icons
190
+ ----------------------------------*/
191
+
192
+ /* states and images */
193
+ .ui-icon {
194
+ width: 16px;
195
+ height: 16px;
196
+ }
197
+ .ui-icon,
198
+ .ui-widget-content .ui-icon {
199
+ background-image: url("images/ui-icons_222222_256x240.png");
200
+ }
201
+ .ui-widget-header .ui-icon {
202
+ background-image: url("images/ui-icons_222222_256x240.png");
203
+ }
204
+ .ui-state-hover .ui-icon,
205
+ .ui-state-focus .ui-icon,
206
+ .ui-button:hover .ui-icon,
207
+ .ui-button:focus .ui-icon {
208
+ background-image: url("images/ui-icons_454545_256x240.png");
209
+ }
210
+ .ui-state-active .ui-icon,
211
+ .ui-button:active .ui-icon {
212
+ background-image: url("images/ui-icons_454545_256x240.png");
213
+ }
214
+ .ui-state-highlight .ui-icon,
215
+ .ui-button .ui-state-highlight.ui-icon {
216
+ background-image: url("images/ui-icons_2e83ff_256x240.png");
217
+ }
218
+ .ui-state-error .ui-icon,
219
+ .ui-state-error-text .ui-icon {
220
+ background-image: url("images/ui-icons_cd0a0a_256x240.png");
221
+ }
222
+ .ui-button .ui-icon {
223
+ background-image: url("images/ui-icons_888888_256x240.png");
224
+ }
225
+
226
+ /* positioning */
227
+ .ui-icon-blank { background-position: 16px 16px; }
228
+ .ui-icon-caret-1-n { background-position: 0 0; }
229
+ .ui-icon-caret-1-ne { background-position: -16px 0; }
230
+ .ui-icon-caret-1-e { background-position: -32px 0; }
231
+ .ui-icon-caret-1-se { background-position: -48px 0; }
232
+ .ui-icon-caret-1-s { background-position: -65px 0; }
233
+ .ui-icon-caret-1-sw { background-position: -80px 0; }
234
+ .ui-icon-caret-1-w { background-position: -96px 0; }
235
+ .ui-icon-caret-1-nw { background-position: -112px 0; }
236
+ .ui-icon-caret-2-n-s { background-position: -128px 0; }
237
+ .ui-icon-caret-2-e-w { background-position: -144px 0; }
238
+ .ui-icon-triangle-1-n { background-position: 0 -16px; }
239
+ .ui-icon-triangle-1-ne { background-position: -16px -16px; }
240
+ .ui-icon-triangle-1-e { background-position: -32px -16px; }
241
+ .ui-icon-triangle-1-se { background-position: -48px -16px; }
242
+ .ui-icon-triangle-1-s { background-position: -65px -16px; }
243
+ .ui-icon-triangle-1-sw { background-position: -80px -16px; }
244
+ .ui-icon-triangle-1-w { background-position: -96px -16px; }
245
+ .ui-icon-triangle-1-nw { background-position: -112px -16px; }
246
+ .ui-icon-triangle-2-n-s { background-position: -128px -16px; }
247
+ .ui-icon-triangle-2-e-w { background-position: -144px -16px; }
248
+ .ui-icon-arrow-1-n { background-position: 0 -32px; }
249
+ .ui-icon-arrow-1-ne { background-position: -16px -32px; }
250
+ .ui-icon-arrow-1-e { background-position: -32px -32px; }
251
+ .ui-icon-arrow-1-se { background-position: -48px -32px; }
252
+ .ui-icon-arrow-1-s { background-position: -65px -32px; }
253
+ .ui-icon-arrow-1-sw { background-position: -80px -32px; }
254
+ .ui-icon-arrow-1-w { background-position: -96px -32px; }
255
+ .ui-icon-arrow-1-nw { background-position: -112px -32px; }
256
+ .ui-icon-arrow-2-n-s { background-position: -128px -32px; }
257
+ .ui-icon-arrow-2-ne-sw { background-position: -144px -32px; }
258
+ .ui-icon-arrow-2-e-w { background-position: -160px -32px; }
259
+ .ui-icon-arrow-2-se-nw { background-position: -176px -32px; }
260
+ .ui-icon-arrowstop-1-n { background-position: -192px -32px; }
261
+ .ui-icon-arrowstop-1-e { background-position: -208px -32px; }
262
+ .ui-icon-arrowstop-1-s { background-position: -224px -32px; }
263
+ .ui-icon-arrowstop-1-w { background-position: -240px -32px; }
264
+ .ui-icon-arrowthick-1-n { background-position: 1px -48px; }
265
+ .ui-icon-arrowthick-1-ne { background-position: -16px -48px; }
266
+ .ui-icon-arrowthick-1-e { background-position: -32px -48px; }
267
+ .ui-icon-arrowthick-1-se { background-position: -48px -48px; }
268
+ .ui-icon-arrowthick-1-s { background-position: -64px -48px; }
269
+ .ui-icon-arrowthick-1-sw { background-position: -80px -48px; }
270
+ .ui-icon-arrowthick-1-w { background-position: -96px -48px; }
271
+ .ui-icon-arrowthick-1-nw { background-position: -112px -48px; }
272
+ .ui-icon-arrowthick-2-n-s { background-position: -128px -48px; }
273
+ .ui-icon-arrowthick-2-ne-sw { background-position: -144px -48px; }
274
+ .ui-icon-arrowthick-2-e-w { background-position: -160px -48px; }
275
+ .ui-icon-arrowthick-2-se-nw { background-position: -176px -48px; }
276
+ .ui-icon-arrowthickstop-1-n { background-position: -192px -48px; }
277
+ .ui-icon-arrowthickstop-1-e { background-position: -208px -48px; }
278
+ .ui-icon-arrowthickstop-1-s { background-position: -224px -48px; }
279
+ .ui-icon-arrowthickstop-1-w { background-position: -240px -48px; }
280
+ .ui-icon-arrowreturnthick-1-w { background-position: 0 -64px; }
281
+ .ui-icon-arrowreturnthick-1-n { background-position: -16px -64px; }
282
+ .ui-icon-arrowreturnthick-1-e { background-position: -32px -64px; }
283
+ .ui-icon-arrowreturnthick-1-s { background-position: -48px -64px; }
284
+ .ui-icon-arrowreturn-1-w { background-position: -64px -64px; }
285
+ .ui-icon-arrowreturn-1-n { background-position: -80px -64px; }
286
+ .ui-icon-arrowreturn-1-e { background-position: -96px -64px; }
287
+ .ui-icon-arrowreturn-1-s { background-position: -112px -64px; }
288
+ .ui-icon-arrowrefresh-1-w { background-position: -128px -64px; }
289
+ .ui-icon-arrowrefresh-1-n { background-position: -144px -64px; }
290
+ .ui-icon-arrowrefresh-1-e { background-position: -160px -64px; }
291
+ .ui-icon-arrowrefresh-1-s { background-position: -176px -64px; }
292
+ .ui-icon-arrow-4 { background-position: 0 -80px; }
293
+ .ui-icon-arrow-4-diag { background-position: -16px -80px; }
294
+ .ui-icon-extlink { background-position: -32px -80px; }
295
+ .ui-icon-newwin { background-position: -48px -80px; }
296
+ .ui-icon-refresh { background-position: -64px -80px; }
297
+ .ui-icon-shuffle { background-position: -80px -80px; }
298
+ .ui-icon-transfer-e-w { background-position: -96px -80px; }
299
+ .ui-icon-transferthick-e-w { background-position: -112px -80px; }
300
+ .ui-icon-folder-collapsed { background-position: 0 -96px; }
301
+ .ui-icon-folder-open { background-position: -16px -96px; }
302
+ .ui-icon-document { background-position: -32px -96px; }
303
+ .ui-icon-document-b { background-position: -48px -96px; }
304
+ .ui-icon-note { background-position: -64px -96px; }
305
+ .ui-icon-mail-closed { background-position: -80px -96px; }
306
+ .ui-icon-mail-open { background-position: -96px -96px; }
307
+ .ui-icon-suitcase { background-position: -112px -96px; }
308
+ .ui-icon-comment { background-position: -128px -96px; }
309
+ .ui-icon-person { background-position: -144px -96px; }
310
+ .ui-icon-print { background-position: -160px -96px; }
311
+ .ui-icon-trash { background-position: -176px -96px; }
312
+ .ui-icon-locked { background-position: -192px -96px; }
313
+ .ui-icon-unlocked { background-position: -208px -96px; }
314
+ .ui-icon-bookmark { background-position: -224px -96px; }
315
+ .ui-icon-tag { background-position: -240px -96px; }
316
+ .ui-icon-home { background-position: 0 -112px; }
317
+ .ui-icon-flag { background-position: -16px -112px; }
318
+ .ui-icon-calendar { background-position: -32px -112px; }
319
+ .ui-icon-cart { background-position: -48px -112px; }
320
+ .ui-icon-pencil { background-position: -64px -112px; }
321
+ .ui-icon-clock { background-position: -80px -112px; }
322
+ .ui-icon-disk { background-position: -96px -112px; }
323
+ .ui-icon-calculator { background-position: -112px -112px; }
324
+ .ui-icon-zoomin { background-position: -128px -112px; }
325
+ .ui-icon-zoomout { background-position: -144px -112px; }
326
+ .ui-icon-search { background-position: -160px -112px; }
327
+ .ui-icon-wrench { background-position: -176px -112px; }
328
+ .ui-icon-gear { background-position: -192px -112px; }
329
+ .ui-icon-heart { background-position: -208px -112px; }
330
+ .ui-icon-star { background-position: -224px -112px; }
331
+ .ui-icon-link { background-position: -240px -112px; }
332
+ .ui-icon-cancel { background-position: 0 -128px; }
333
+ .ui-icon-plus { background-position: -16px -128px; }
334
+ .ui-icon-plusthick { background-position: -32px -128px; }
335
+ .ui-icon-minus { background-position: -48px -128px; }
336
+ .ui-icon-minusthick { background-position: -64px -128px; }
337
+ .ui-icon-close { background-position: -80px -128px; }
338
+ .ui-icon-closethick { background-position: -96px -128px; }
339
+ .ui-icon-key { background-position: -112px -128px; }
340
+ .ui-icon-lightbulb { background-position: -128px -128px; }
341
+ .ui-icon-scissors { background-position: -144px -128px; }
342
+ .ui-icon-clipboard { background-position: -160px -128px; }
343
+ .ui-icon-copy { background-position: -176px -128px; }
344
+ .ui-icon-contact { background-position: -192px -128px; }
345
+ .ui-icon-image { background-position: -208px -128px; }
346
+ .ui-icon-video { background-position: -224px -128px; }
347
+ .ui-icon-script { background-position: -240px -128px; }
348
+ .ui-icon-alert { background-position: 0 -144px; }
349
+ .ui-icon-info { background-position: -16px -144px; }
350
+ .ui-icon-notice { background-position: -32px -144px; }
351
+ .ui-icon-help { background-position: -48px -144px; }
352
+ .ui-icon-check { background-position: -64px -144px; }
353
+ .ui-icon-bullet { background-position: -80px -144px; }
354
+ .ui-icon-radio-on { background-position: -96px -144px; }
355
+ .ui-icon-radio-off { background-position: -112px -144px; }
356
+ .ui-icon-pin-w { background-position: -128px -144px; }
357
+ .ui-icon-pin-s { background-position: -144px -144px; }
358
+ .ui-icon-play { background-position: 0 -160px; }
359
+ .ui-icon-pause { background-position: -16px -160px; }
360
+ .ui-icon-seek-next { background-position: -32px -160px; }
361
+ .ui-icon-seek-prev { background-position: -48px -160px; }
362
+ .ui-icon-seek-end { background-position: -64px -160px; }
363
+ .ui-icon-seek-start { background-position: -80px -160px; }
364
+ /* ui-icon-seek-first is deprecated, use ui-icon-seek-start instead */
365
+ .ui-icon-seek-first { background-position: -80px -160px; }
366
+ .ui-icon-stop { background-position: -96px -160px; }
367
+ .ui-icon-eject { background-position: -112px -160px; }
368
+ .ui-icon-volume-off { background-position: -128px -160px; }
369
+ .ui-icon-volume-on { background-position: -144px -160px; }
370
+ .ui-icon-power { background-position: 0 -176px; }
371
+ .ui-icon-signal-diag { background-position: -16px -176px; }
372
+ .ui-icon-signal { background-position: -32px -176px; }
373
+ .ui-icon-battery-0 { background-position: -48px -176px; }
374
+ .ui-icon-battery-1 { background-position: -64px -176px; }
375
+ .ui-icon-battery-2 { background-position: -80px -176px; }
376
+ .ui-icon-battery-3 { background-position: -96px -176px; }
377
+ .ui-icon-circle-plus { background-position: 0 -192px; }
378
+ .ui-icon-circle-minus { background-position: -16px -192px; }
379
+ .ui-icon-circle-close { background-position: -32px -192px; }
380
+ .ui-icon-circle-triangle-e { background-position: -48px -192px; }
381
+ .ui-icon-circle-triangle-s { background-position: -64px -192px; }
382
+ .ui-icon-circle-triangle-w { background-position: -80px -192px; }
383
+ .ui-icon-circle-triangle-n { background-position: -96px -192px; }
384
+ .ui-icon-circle-arrow-e { background-position: -112px -192px; }
385
+ .ui-icon-circle-arrow-s { background-position: -128px -192px; }
386
+ .ui-icon-circle-arrow-w { background-position: -144px -192px; }
387
+ .ui-icon-circle-arrow-n { background-position: -160px -192px; }
388
+ .ui-icon-circle-zoomin { background-position: -176px -192px; }
389
+ .ui-icon-circle-zoomout { background-position: -192px -192px; }
390
+ .ui-icon-circle-check { background-position: -208px -192px; }
391
+ .ui-icon-circlesmall-plus { background-position: 0 -208px; }
392
+ .ui-icon-circlesmall-minus { background-position: -16px -208px; }
393
+ .ui-icon-circlesmall-close { background-position: -32px -208px; }
394
+ .ui-icon-squaresmall-plus { background-position: -48px -208px; }
395
+ .ui-icon-squaresmall-minus { background-position: -64px -208px; }
396
+ .ui-icon-squaresmall-close { background-position: -80px -208px; }
397
+ .ui-icon-grip-dotted-vertical { background-position: 0 -224px; }
398
+ .ui-icon-grip-dotted-horizontal { background-position: -16px -224px; }
399
+ .ui-icon-grip-solid-vertical { background-position: -32px -224px; }
400
+ .ui-icon-grip-solid-horizontal { background-position: -48px -224px; }
401
+ .ui-icon-gripsmall-diagonal-se { background-position: -64px -224px; }
402
+ .ui-icon-grip-diagonal-se { background-position: -80px -224px; }
403
+
404
+
405
+ /* Misc visuals
406
+ ----------------------------------*/
407
+
408
+ /* Corner radius */
409
+ .ui-corner-all,
410
+ .ui-corner-top,
411
+ .ui-corner-left,
412
+ .ui-corner-tl {
413
+ border-top-left-radius: 4px;
414
+ }
415
+ .ui-corner-all,
416
+ .ui-corner-top,
417
+ .ui-corner-right,
418
+ .ui-corner-tr {
419
+ border-top-right-radius: 4px;
420
+ }
421
+ .ui-corner-all,
422
+ .ui-corner-bottom,
423
+ .ui-corner-left,
424
+ .ui-corner-bl {
425
+ border-bottom-left-radius: 4px;
426
+ }
427
+ .ui-corner-all,
428
+ .ui-corner-bottom,
429
+ .ui-corner-right,
430
+ .ui-corner-br {
431
+ border-bottom-right-radius: 4px;
432
+ }
433
+
434
+ /* Overlays */
435
+ .ui-widget-overlay {
436
+ background: #aaaaaa;
437
+ opacity: .3;
438
+ filter: Alpha(Opacity=30); /* support: IE8 */
439
+ }
440
+ .ui-widget-shadow {
441
+ -webkit-box-shadow: -8px -8px 8px #aaaaaa;
442
+ box-shadow: -8px -8px 8px #aaaaaa;
443
+ }
assets/css/settings.css ADDED
@@ -0,0 +1,27 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ul.pe-list {
2
+ list-style: disc !important;
3
+ }
4
+
5
+ ul.pe-list > li {
6
+ margin-left: 3%;
7
+ }
8
+
9
+ .pe-scroll {
10
+ height: 300px;
11
+ overflow-y: scroll;
12
+ }
13
+
14
+ .pe-scroll > table td {
15
+ padding: 5px;
16
+ }
17
+
18
+ tr.pe-event {
19
+ background-color: #ddd !important;
20
+ }
21
+
22
+ #pe-settings-tabs fieldset {
23
+ border: 1px solid black;
24
+ border-radius: 6px;
25
+ padding: 0px 12px;
26
+ margin-bottom: 20px;
27
+ }
admin-edit.js → assets/js/admin-edit.js RENAMED
@@ -1,15 +1,51 @@
1
  (function($, config) {
2
 
3
- // show/hide the date fields when the user chooses the intent.
4
  $('body').on('change', 'select[name="expirationdate_status"]', function(e){
5
  var $show = $(this).find('option:selected').attr('data-show-fields');
6
  if($show === 'true'){
7
- $(this).parents('.timestamp-wrap').find('span.post-expirator-date-fields').show();
8
  }else{
9
- $(this).parents('.timestamp-wrap').find('span.post-expirator-date-fields').hide();
10
  }
11
  });
12
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
13
  // we create a copy of the WP inline edit post function
14
  var $wp_inline_edit = inlineEditPost.edit;
15
 
@@ -52,10 +88,32 @@
52
  var $minute = $( '#expirationdate_minute-' + $post_id ).text();
53
  $edit_row.find( 'input[name="expirationdate_minute"]' ).val( $minute );
54
 
 
 
 
 
 
55
  var $enabled = $( '#expirationdate_enabled-' + $post_id ).text();
56
  if ($enabled == "true") {
57
  $edit_row.find( 'input[name="enable-expirationdate"]' ).prop( 'checked', true );
 
58
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
59
  }
60
  };
61
 
@@ -77,7 +135,12 @@
77
  var $expirationdate_hour = $bulk_row.find( 'input[name="expirationdate_hour"]' ).val();
78
  var $expirationdate_minute = $bulk_row.find( 'input[name="expirationdate_minute"]' ).val();
79
  var $expirationdate_status = $bulk_row.find( 'select[name="expirationdate_status"]' ).val();
80
-
 
 
 
 
 
81
  // save the data
82
  $.ajax({
83
  url: ajaxurl, // this is a variable that WordPress has already defined for us
@@ -93,6 +156,8 @@
93
  expirationdate_hour: $expirationdate_hour,
94
  expirationdate_minute: $expirationdate_minute,
95
  expirationdate_status: $expirationdate_status,
 
 
96
  nonce: config.ajax.nonce
97
  }
98
  });
1
  (function($, config) {
2
 
3
+ // show/hide the date fields when the user chooses the intent in bulk edit
4
  $('body').on('change', 'select[name="expirationdate_status"]', function(e){
5
  var $show = $(this).find('option:selected').attr('data-show-fields');
6
  if($show === 'true'){
7
+ $(this).parents('.pe-qe-fields').find('.post-expirator-date-fields').show();
8
  }else{
9
+ $(this).parents('.pe-qe-fields').find('.post-expirator-date-fields').hide();
10
  }
11
  });
12
 
13
+ // show/hide the date fields when the user chooses the intent in quick edit
14
+ $('body').on('click', 'input[name="enable-expirationdate"]', function(e){
15
+ if($(this).is(':checked')){
16
+ $(this).parents('.post-expirator-quickedit').find('.pe-qe-fields').show();
17
+ }else{
18
+ $(this).parents('.post-expirator-quickedit').find('.pe-qe-fields').hide();
19
+ }
20
+ });
21
+
22
+ // hide/show the categories selection checkbox list in bulk/quick edit
23
+ $('body').on('change', 'select[name="expirationdate_expiretype"]', function(e){
24
+ var $show = $(this).val().indexOf('category') !== -1;
25
+ if($show){
26
+ $(this).parents('.pe-qe-fields').find('.pe-category-list').show();
27
+ }else{
28
+ $(this).parents('.pe-qe-fields').find('.pe-category-list').hide();
29
+ }
30
+ });
31
+
32
+ // we create a copy of the WP bulk edit post function
33
+ var $wp_bulk_edit = inlineEditPost.setBulk;
34
+
35
+ // and then we overwrite the function with our own code
36
+ inlineEditPost.setBulk = function( id ) {
37
+ // "call" the original WP edit function
38
+ // we don't want to leave WordPress hanging
39
+ $wp_bulk_edit.apply( this, arguments );
40
+
41
+ var $bulk_row = $( '#bulk-edit' );
42
+
43
+ // hide the fields for bulk edit till action is taken by the user
44
+ $bulk_row.find('.pe-qe-fields select[name="expirationdate_status"]').prop('selectedIndex', 0);
45
+ $bulk_row.find('.pe-qe-fields .post-expirator-date-fields').hide();
46
+ $bulk_row.find('.pe-qe-fields .pe-category-list').hide();
47
+ };
48
+
49
  // we create a copy of the WP inline edit post function
50
  var $wp_inline_edit = inlineEditPost.edit;
51
 
88
  var $minute = $( '#expirationdate_minute-' + $post_id ).text();
89
  $edit_row.find( 'input[name="expirationdate_minute"]' ).val( $minute );
90
 
91
+ // expire type
92
+ var $type = $( '#expirationdate_expireType-' + $post_id ).text();
93
+ $edit_row.find( 'select[name="expirationdate_expiretype"]' ).val( $type );
94
+
95
+ // enabled or not
96
  var $enabled = $( '#expirationdate_enabled-' + $post_id ).text();
97
  if ($enabled == "true") {
98
  $edit_row.find( 'input[name="enable-expirationdate"]' ).prop( 'checked', true );
99
+ $edit_row.find('.pe-qe-fields').show();
100
  }
101
+
102
+ // categories
103
+ var $categories = $( '#expirationdate_categories-' + $post_id ).text();
104
+ if ($categories !== ''){
105
+ $.each($categories.split(','), function(index, value){
106
+ $edit_row.find( 'input[name="expirationdate_category[]"][value="' + value + '"]' ).prop( 'checked', true );
107
+ });
108
+ }
109
+
110
+ // show or hide categories
111
+ if($type.indexOf('category') !== -1){
112
+ $edit_row.find('.pe-category-list').show();
113
+ }else{
114
+ $edit_row.find('.pe-category-list').hide();
115
+ }
116
+
117
  }
118
  };
119
 
135
  var $expirationdate_hour = $bulk_row.find( 'input[name="expirationdate_hour"]' ).val();
136
  var $expirationdate_minute = $bulk_row.find( 'input[name="expirationdate_minute"]' ).val();
137
  var $expirationdate_status = $bulk_row.find( 'select[name="expirationdate_status"]' ).val();
138
+ var $expirationdate_expireType = $bulk_row.find( 'select[name="expirationdate_expiretype"]' ).val();
139
+ var expirationdate_category = [];
140
+ $bulk_row.find( 'input[name="expirationdate_category[]"]:checked' ).each(function(){
141
+ expirationdate_category.push($(this).val());
142
+ });
143
+
144
  // save the data
145
  $.ajax({
146
  url: ajaxurl, // this is a variable that WordPress has already defined for us
156
  expirationdate_hour: $expirationdate_hour,
157
  expirationdate_minute: $expirationdate_minute,
158
  expirationdate_status: $expirationdate_status,
159
+ expirationdate_expiretype: $expirationdate_expireType,
160
+ expirationdate_category: expirationdate_category,
161
  nonce: config.ajax.nonce
162
  }
163
  });
assets/js/block.js ADDED
@@ -0,0 +1,2 @@
 
 
1
+ !function(e){var t={};function a(o){if(t[o])return t[o].exports;var r=t[o]={i:o,l:!1,exports:{}};return e[o].call(r.exports,r,r.exports,a),r.l=!0,r.exports}a.m=e,a.c=t,a.d=function(e,t,o){a.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:o})},a.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},a.t=function(e,t){if(1&t&&(e=a(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var o=Object.create(null);if(a.r(o),Object.defineProperty(o,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var r in e)a.d(o,r,function(t){return e[t]}.bind(null,r));return o},a.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return a.d(t,"a",t),t},a.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},a.p="",a(a.s=0)}([function(e,t,a){e.exports=a(1)},function(e,t,a){"use strict";var o="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},r=function(){function e(e,t){for(var a=0;a<t.length;a++){var o=t[a];o.enumerable=o.enumerable||!1,o.configurable=!0,"value"in o&&(o.writable=!0),Object.defineProperty(e,o.key,o)}}return function(t,a,o){return a&&e(t.prototype,a),o&&e(t,o),t}}();function n(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function i(e,t){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!t||"object"!=typeof t&&"function"!=typeof t?e:t}!function(e,t){var a=e.plugins.registerPlugin,c=e.i18n.__,s=e.editPost.PluginDocumentSettingPanel,u=e.components,l=u.PanelRow,p=u.DateTimePicker,d=u.CheckboxControl,f=u.SelectControl,g=u.FormTokenField,y=u.Spinner,m=e.element,b=m.Fragment,x=m.Component,v=e.htmlEntities.decodeEntities,h=lodash,E=h.isEmpty,P=h.keys,S=h.compact;a("postexpirator-sidebar",{render:function(a){function u(){n(this,u);var e=i(this,(u.__proto__||Object.getPrototypeOf(u)).apply(this,arguments));return e.state={categoriesList:[],catIdVsName:[]},e}return function(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function, not "+typeof t);e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),t&&(Object.setPrototypeOf?Object.setPrototypeOf(e,t):e.__proto__=t)}(u,a),r(u,[{key:"componentWillMount",value:function(){var a,o=this,r=(this.state.attributes,e.data.select("core/editor").getEditedPostAttribute("meta")),n=e.data.select("core/editor").getCurrentPostType(),i=1==t.defaults.autoEnable,s=new Date,u=this.getExpireType(r),l=[];if(u.includes("category")&&(l=this.getCategories(r)),r["_expiration-date-status"]&&"saved"===r["_expiration-date-status"]&&(i=!0),r["_expiration-date"])s.setTime(1e3*(r["_expiration-date"]+60*s.getTimezoneOffset()));else if(l=t.default_categories,t.default_date){s.setTime(1e3*(parseInt(t.default_date)+60*s.getTimezoneOffset()));a={"_expiration-date":this.getDate(s)},e.data.dispatch("core/editor").editPost({meta:a})}var p=t.defaults.taxonomy||"category";this.setState({enabled:i,date:s,expireAction:u,categories:l,taxonomy:p});var d=[],f=[];!p&&"post"===n||"category"===p?e.apiFetch({path:e.url.addQueryArgs("wp/v2/categories",{per_page:-1,hide_empty:!1})}).then((function(e){e.forEach((function(e){d[e.name]=e,f[e.id]=e.name})),o.setState({categoriesList:d,catIdVsName:f,taxonomy:c("Category")})})):"page"!==n&&e.apiFetch({path:e.url.addQueryArgs("wp/v2/taxonomies/"+p,{context:"edit"})}).then((function(t){e.apiFetch({path:e.url.addQueryArgs("wp/v2/"+t.rest_base,{context:"edit"})}).then((function(e){e.forEach((function(e){d[v(e.name)]=e,f[e.id]=v(e.name)})),o.setState({categoriesList:d,catIdVsName:f,taxonomy:v(t.name)})}))}))}},{key:"componentDidUpdate",value:function(){var t=this.state,a=t.enabled,o=t.date,r=t.expireAction,n=t.categories,i=function(t){return e.data.dispatch("core/editor").editPost({meta:t})};switch(t.attribute){case"enabled":i({"_expiration-date-status":a?"saved":""});break;case"date":"string"==typeof o&&i({"_expiration-date":this.getDate(o)});break;case"action":i({"_expiration-date-type":r}),r.includes("category")||i({"_expiration-date-categories":[]});break;case"category":i({"_expiration-date-categories":n})}}},{key:"render",value:function(){var t=this,a=this.state,o=a.categoriesList,r=a.catIdVsName,n=this.state,i=n.enabled,u=n.date,m=n.expireAction,x=n.categories,v=n.taxonomy,h=e.data.select("core/editor").getCurrentPostType(),k=[{label:c("Draft","post-expirator"),value:"draft"},{label:c("Delete","post-expirator"),value:"delete"},{label:c("Trash","post-expirator"),value:"trash"},{label:c("Private","post-expirator"),value:"private"},{label:c("Stick","post-expirator"),value:"stick"},{label:c("Unstick","post-expirator"),value:"unstick"}];"page"!==h&&(k=_.union(k,[{label:c("Category: Replace","post-expirator"),value:"category"},{label:c("Category: Add","post-expirator"),value:"category-add"},{label:c("Category: Remove","post-expirator"),value:"category-remove"}]));var w=x&&S(x.map((function(e){return r[e]||!1})));return"string"==typeof w&&(w=[]),React.createElement(s,{title:c("Post Expirator","post-expirator"),icon:"calendar",initialOpen:i},React.createElement(l,null,React.createElement(d,{label:c("Enable Post Expiration","post-expirator"),checked:i,onChange:function(e){t.setState({enabled:!i,attribute:"enabled"})}})),i&&React.createElement(b,null,React.createElement(l,null,React.createElement(p,{currentDate:u,onChange:function(e){return t.setState({date:e,attribute:"date"})},is12Hour:!0})),React.createElement(f,{label:c("How to expire","post-expirator"),value:m,options:k,onChange:function(e){t.setState({expireAction:e,attribute:"action"})}}),m.includes("category")&&(E(P(o))&&React.createElement(b,null,c("Loading","post-expirator")+" ("+v+")",React.createElement(y,null))||React.createElement(g,{label:c("Expiration Categories","post-expirator")+" ("+v+")",value:w,suggestions:Object.keys(o),onChange:function(e){t.setState({categories:t.selectCategories(e),attribute:"category"})},maxSuggestions:10}))))}},{key:"getExpireType",value:function(e){var t=e["_expiration-date-type"],a=e["_expiration-date-options"]&&e["_expiration-date-options"].expireType;return t||(a||"draft")}},{key:"getCategories",value:function(e){var t=e["_expiration-date-categories"]&&e["_expiration-date-categories"],a=e["_expiration-date-options"]&&e["_expiration-date-options"].category;return"object"===(void 0===t?"undefined":o(t))&&t.length>0?t:(a&&void 0!==a&&"object"!==(void 0===a?"undefined":o(a))&&(categories=[a]),a)}},{key:"selectCategories",value:function(e){var t=this.state,a=t.categoriesList;t.catIdVsName;if(!e.some((function(e){return"string"==typeof e&&!a[e]})))return e.map((function(e){return"string"==typeof e?a[e]:e})).map((function(e){return e.id}))}},{key:"getDate",value:function(e){var t=new Date;return t.setTime(Date.parse(e)),t.setTime(t.getTime()-60*(new Date).getTimezoneOffset()*1e3),t.getTime()/1e3}}]),u}(x)})}(window.wp,config)}]);
2
+ //# sourceMappingURL=block.js.map
assets/js/block.js.map ADDED
@@ -0,0 +1 @@
 
1
+ {"version":3,"sources":["webpack:///webpack/bootstrap","webpack:///./assets/jsx/block.jsx"],"names":["installedModules","__webpack_require__","moduleId","exports","module","i","l","modules","call","m","c","d","name","getter","o","Object","defineProperty","enumerable","get","r","Symbol","toStringTag","value","t","mode","__esModule","ns","create","key","bind","n","object","property","prototype","hasOwnProperty","p","s","wp","config","registerPlugin","plugins","__","i18n","PluginDocumentSettingPanel","editPost","components","PanelRow","DateTimePicker","CheckboxControl","SelectControl","FormTokenField","Spinner","element","Fragment","Component","decodeEntities","htmlEntities","lodash","isEmpty","keys","compact","render","arguments","state","categoriesList","catIdVsName","newMeta","postMeta","this","attributes","data","select","getEditedPostAttribute","postType","getCurrentPostType","enabled","defaults","autoEnable","date","Date","expireAction","getExpireType","categories","includes","getCategories","setTime","getTimezoneOffset","default_categories","default_date","parseInt","getDate","dispatch","meta","taxonomy","setState","apiFetch","path","url","addQueryArgs","per_page","hide_empty","then","list","forEach","cat","id","context","taxAttributes","rest_base","terms","term","setPostMeta","attribute","actionsList","label","_","union","selectedCats","map","title","icon","initialOpen","checked","onChange","currentDate","is12Hour","options","suggestions","selectCategories","maxSuggestions","typeNew","typeOld","categoriesNew","categoriesOld","length","tokens","some","token","newDate","parse","getTime","window"],"mappings":"aACE,IAAIA,EAAmB,GAGvB,SAASC,EAAoBC,GAG5B,GAAGF,EAAiBE,GACnB,OAAOF,EAAiBE,GAAUC,QAGnC,IAAIC,EAASJ,EAAiBE,GAAY,CACzCG,EAAGH,EACHI,GAAG,EACHH,QAAS,IAUV,OANAI,EAAQL,GAAUM,KAAKJ,EAAOD,QAASC,EAAQA,EAAOD,QAASF,GAG/DG,EAAOE,GAAI,EAGJF,EAAOD,QAKfF,EAAoBQ,EAAIF,EAGxBN,EAAoBS,EAAIV,EAGxBC,EAAoBU,EAAI,SAASR,EAASS,EAAMC,GAC3CZ,EAAoBa,EAAEX,EAASS,IAClCG,OAAOC,eAAeb,EAASS,EAAM,CAAEK,YAAY,EAAMC,IAAKL,KAKhEZ,EAAoBkB,EAAI,SAAShB,GACX,oBAAXiB,QAA0BA,OAAOC,aAC1CN,OAAOC,eAAeb,EAASiB,OAAOC,YAAa,CAAEC,MAAO,WAE7DP,OAAOC,eAAeb,EAAS,aAAc,CAAEmB,OAAO,KAQvDrB,EAAoBsB,EAAI,SAASD,EAAOE,GAEvC,GADU,EAAPA,IAAUF,EAAQrB,EAAoBqB,IAC/B,EAAPE,EAAU,OAAOF,EACpB,GAAW,EAAPE,GAA8B,iBAAVF,GAAsBA,GAASA,EAAMG,WAAY,OAAOH,EAChF,IAAII,EAAKX,OAAOY,OAAO,MAGvB,GAFA1B,EAAoBkB,EAAEO,GACtBX,OAAOC,eAAeU,EAAI,UAAW,CAAET,YAAY,EAAMK,MAAOA,IACtD,EAAPE,GAA4B,iBAATF,EAAmB,IAAI,IAAIM,KAAON,EAAOrB,EAAoBU,EAAEe,EAAIE,EAAK,SAASA,GAAO,OAAON,EAAMM,IAAQC,KAAK,KAAMD,IAC9I,OAAOF,GAIRzB,EAAoB6B,EAAI,SAAS1B,GAChC,IAAIS,EAAST,GAAUA,EAAOqB,WAC7B,WAAwB,OAAOrB,EAAgB,SAC/C,WAA8B,OAAOA,GAEtC,OADAH,EAAoBU,EAAEE,EAAQ,IAAKA,GAC5BA,GAIRZ,EAAoBa,EAAI,SAASiB,EAAQC,GAAY,OAAOjB,OAAOkB,UAAUC,eAAe1B,KAAKuB,EAAQC,IAGzG/B,EAAoBkC,EAAI,GAIjBlC,EAAoBA,EAAoBmC,EAAI,G,swBClFrD,SAAYC,EAAIC,GAAS,IAEbC,EAAmBF,EAAGG,QAAtBD,eACAE,EAAOJ,EAAGK,KAAVD,GACAE,EAA+BN,EAAGO,SAAlCD,2BAJa,EAKyEN,EAAGQ,WAAzFC,EALa,EAKbA,SAAUC,EALG,EAKHA,eAAgBC,EALb,EAKaA,gBAAiBC,EAL9B,EAK8BA,cAAeC,EAL7C,EAK6CA,eAAgBC,EAL7D,EAK6DA,QAL7D,EAMWd,EAAGe,QAA3BC,EANa,EAMbA,SAAUC,EANG,EAMHA,UACVC,EAAmBlB,EAAGmB,aAAtBD,eAPa,EAQcE,OAA3BC,EARa,EAQbA,QAASC,EARI,EAQJA,KAAMC,EARF,EAQEA,QA0PvBrB,EAAgB,wBAAyB,CACrCsB,OAnQiB,YAWjB,aAAc,0EACAC,YADA,OAGV,EAAKC,MAAQ,CACTC,eAAgB,GAChBC,YAAa,IALP,EAXG,O,yTAAA,sDAoBI,IA2BYC,EA3BZ,OAGXC,GAFiBC,KAAKL,MAApBM,WAEShC,EAAGiC,KAAKC,OAAQ,eAAgBC,uBAAwB,SACnEC,EAAWpC,EAAGiC,KAAKC,OAAO,eAAeG,qBAE3CC,EAAwC,GAA9BrC,EAAOsC,SAASC,WAC1BC,EAAO,IAAIC,KAEXC,EAAeZ,KAAKa,cAAcd,GAElCe,EAAa,GASjB,GARGF,EAAaG,SAAS,cACrBD,EAAad,KAAKgB,cAAcjB,IAGjCA,EAAS,4BAAsE,UAAxCA,EAAS,6BAC/CQ,GAAU,GAGXR,EAAS,oBACRW,EAAKO,QAAyE,KAAhElB,EAAS,oBAAiD,GAA3BW,EAAKQ,2BAGlD,GADAJ,EAAa5C,EAAOiD,mBACjBjD,EAAOkD,aAAa,CACnBV,EAAKO,QAA0E,KAAjEI,SAASnD,EAAOkD,cAA2C,GAA3BV,EAAKQ,sBAE9BpB,EACR,CAAC,mBAAoBE,KAAKsB,QAAQZ,IADdzC,EAAGiC,KAAKqB,SAAU,eAAgB/C,SAAU,CAAEgD,KAAM1B,IAK7F,IAAI2B,EAAWvD,EAAOsC,SAASiB,UAAY,WAE3CzB,KAAK0B,SAAU,CACXnB,QAASA,EACTG,KAAMA,EACNE,aAAcA,EACdE,WAAYA,EACZW,SAAUA,IAGd,IAAI7B,EAAiB,GACjBC,EAAc,IAEZ4B,GAAyB,SAAbpB,GAAqC,aAAboB,EACtCxD,EAAG0D,SAAU,CACTC,KAAM3D,EAAG4D,IAAIC,aAAc,mBAAoB,CAAEC,UAAW,EAAGC,YAAY,MAC3EC,MAAM,SAAEC,GACRA,EAAKC,SAAQ,SAAAC,GACTxC,EAAgBwC,EAAI5F,MAAS4F,EAC7BvC,EAAauC,EAAIC,IAAOD,EAAI5F,QAEhC,EAAKkF,SAAU,CAAE9B,eAAgBA,EAAgBC,YAAaA,EAAa4B,SAAUpD,EAAI,iBAE3E,SAAbgC,GACLpC,EAAG0D,SAAU,CACTC,KAAM3D,EAAG4D,IAAIC,aAAP,oBAAyCL,EAAY,CAAEa,QAAS,WACtEL,MAAM,SAAEM,GAERtE,EAAG0D,SAAU,CACTC,KAAM3D,EAAG4D,IAAIC,aAAP,SAA8BS,EAAcC,UAAa,CAAEF,QAAS,WAC1EL,MAAM,SAAEQ,GACRA,EAAMN,SAAQ,SAAAO,GACV9C,EAAgBT,EAAeuD,EAAKlG,OAAUkG,EAC9C7C,EAAa6C,EAAKL,IAAOlD,EAAeuD,EAAKlG,SAEjD,EAAKkF,SAAU,CAAE9B,eAAgBA,EAAgBC,YAAaA,EAAa4B,SAAUtC,EAAeoD,EAAc/F,gBAvFjH,2CA8FI,MAC8CwD,KAAKL,MAA5DY,EADS,EACTA,QAASG,EADA,EACAA,KAAME,EADN,EACMA,aAAcE,EADpB,EACoBA,WAC/B6B,EAAc,SAAC7C,GAAD,OAAa7B,EAAGiC,KAAKqB,SAAU,eAAgB/C,SAAU,CAAEgD,KAAM1B,KAErF,OAJiB,EACgC8C,WAI7C,IAAK,UACDD,EAAa,CAAE,0BAA6BpC,EAAU,QAAU,KAChE,MACJ,IAAK,OACkB,iBAATG,GACNiC,EAAa,CAAC,mBAAoB3C,KAAKsB,QAAQZ,KAEnD,MACJ,IAAK,SACDiC,EAAa,CAAE,wBAAyB/B,IACpCA,EAAaG,SAAS,aACtB4B,EAAa,CAAE,8BAA+B,KAElD,MACJ,IAAK,WACDA,EAAa,CAAE,8BAA+B7B,OAlHzC,+BAwHR,aACmCd,KAAKL,MAArCC,EADH,EACGA,eAAgBC,EADnB,EACmBA,YADnB,EAEyDG,KAAKL,MAA3DY,EAFH,EAEGA,QAASG,EAFZ,EAEYA,KAAME,EAFlB,EAEkBA,aAAcE,EAFhC,EAEgCA,WAAYW,EAF5C,EAE4CA,SAE3CpB,EAAWpC,EAAGiC,KAAKC,OAAO,eAAeG,qBAE3CuC,EAAc,CACd,CAAEC,MAAOzE,EAAI,QAAS,kBAAoBnB,MAAO,SACjD,CAAE4F,MAAOzE,EAAI,SAAU,kBAAoBnB,MAAO,UAClD,CAAE4F,MAAOzE,EAAI,QAAS,kBAAoBnB,MAAO,SACjD,CAAE4F,MAAOzE,EAAI,UAAW,kBAAoBnB,MAAO,WACnD,CAAE4F,MAAOzE,EAAI,QAAS,kBAAoBnB,MAAO,SACjD,CAAE4F,MAAOzE,EAAI,UAAW,kBAAoBnB,MAAO,YAGvC,SAAbmD,IACCwC,EAAcE,EAAEC,MAAMH,EAAa,CAC/B,CAAEC,MAAOzE,EAAG,oBAAqB,kBAAmBnB,MAAO,YAC3D,CAAE4F,MAAOzE,EAAG,gBAAiB,kBAAmBnB,MAAO,gBACvD,CAAE4F,MAAOzE,EAAG,mBAAoB,kBAAmBnB,MAAO,sBAIlE,IAAI+F,EAAenC,GAActB,EAAQsB,EAAWoC,KAAI,SAACb,GAAD,OAAQxC,EAAYwC,KAAO,MAKnF,MAJ2B,iBAAjBY,IACNA,EAAe,IAIf,oBAAC1E,EAAD,CAA4B4E,MAAQ9E,EAAI,iBAAkB,kBAAqB+E,KAAK,WAAWC,YAAc9C,GACzG,oBAAC7B,EAAD,KACI,oBAACE,EAAD,CACIkE,MAAQzE,EAAI,yBAA0B,kBACtCiF,QAAU/C,EACVgD,SAAW,SAACrG,GAAY,EAAKwE,SAAU,CAAEnB,SAAUA,EAASqC,UAAW,gBAG7ErC,GACE,oBAACtB,EAAD,KACI,oBAACP,EAAD,KACI,oBAACC,EAAD,CACI6E,YAAc9C,EACd6C,SAAW,SAAErG,GAAF,OAAa,EAAKwE,SAAU,CAAEhB,KAAMxD,EAAO0F,UAAW,UACjEa,UAAW,KAGnB,oBAAC5E,EAAD,CACIiE,MAAQzE,EAAI,gBAAiB,kBAC7BnB,MAAQ0D,EACR8C,QAAUb,EACVU,SAAW,SAACrG,GAAY,EAAKwE,SAAU,CAAEd,aAAc1D,EAAO0F,UAAW,cAE3EhC,EAAaG,SAAS,cAEdzB,EAAQC,EAAKK,KACX,oBAACX,EAAD,KACMZ,EAAI,UAAW,kBAAf,KAAyCoD,EAAzC,IACF,oBAAC1C,EAAD,QAKZ,oBAACD,EAAD,CACIgE,MAAQzE,EAAG,wBAAyB,kBAA5B,KAAqDoD,EAArD,IACRvE,MAAQ+F,EACRU,YAAchH,OAAO4C,KAAKK,GAC1B2D,SAAW,SAAErG,GAAa,EAAKwE,SAAU,CAAEZ,WAAY,EAAK8C,iBAAiB1G,GAAQ0F,UAAW,cAChGiB,eAAiB,UA3L5B,oCAsMH9D,GACV,IAAI+D,EAAU/D,EAAS,yBACnBgE,EAAUhE,EAAS,6BAA+BA,EAAS,4BAAT,WAEtD,OAAG+D,IAIAC,GAII,WAlNM,oCAsNHhE,GACV,IAAIiE,EAAgBjE,EAAS,gCAAkCA,EAAS,+BACpEkE,EAAgBlE,EAAS,6BAA+BA,EAAS,4BAAT,SAE5D,MAA4B,iBAAzB,IAAOiE,EAAP,cAAOA,KAA8BA,EAAcE,OAAS,EACpDF,GAGRC,QAA0C,IAAlBA,GAA0D,iBAAzB,IAAOA,EAAP,cAAOA,MAC/DnD,WAAa,CAAEmD,IAGZA,KAlOM,uCAuOAE,GAAQ,MACmBnE,KAAKL,MAArCC,EADa,EACbA,eADa,EACGC,YAMxB,IAJsBsE,EAAOC,MAAK,SAAUC,GACxC,MAAwB,iBAAVA,IAAuBzE,EAAeyE,MAWxD,OAJiBF,EAAOjB,KAAI,SAAUmB,GAClC,MAAwB,iBAAVA,EAAqBzE,EAAeyE,GAASA,KAG7CnB,KAAK,SAACd,GAAD,OAASA,EAAIC,QAtPvB,8BAyPT3B,GACJ,IAAI4D,EAAU,IAAI3D,KAGlB,OAFA2D,EAAQrD,QAAQN,KAAK4D,MAAM7D,IAC3B4D,EAAQrD,QAAQqD,EAAQE,UAA6C,IAAjC,IAAI7D,MAAOO,oBAA2B,KACjEoD,EAAQE,UAAa,QA7PjB,GAUctF,KAVvC,CAuQIuF,OAAOxG,GAAIC","file":"block.js","sourcesContent":[" \t// The module cache\n \tvar installedModules = {};\n\n \t// The require function\n \tfunction __webpack_require__(moduleId) {\n\n \t\t// Check if module is in cache\n \t\tif(installedModules[moduleId]) {\n \t\t\treturn installedModules[moduleId].exports;\n \t\t}\n \t\t// Create a new module (and put it into the cache)\n \t\tvar module = installedModules[moduleId] = {\n \t\t\ti: moduleId,\n \t\t\tl: false,\n \t\t\texports: {}\n \t\t};\n\n \t\t// Execute the module function\n \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n \t\t// Flag the module as loaded\n \t\tmodule.l = true;\n\n \t\t// Return the exports of the module\n \t\treturn module.exports;\n \t}\n\n\n \t// expose the modules object (__webpack_modules__)\n \t__webpack_require__.m = modules;\n\n \t// expose the module cache\n \t__webpack_require__.c = installedModules;\n\n \t// define getter function for harmony exports\n \t__webpack_require__.d = function(exports, name, getter) {\n \t\tif(!__webpack_require__.o(exports, name)) {\n \t\t\tObject.defineProperty(exports, name, { enumerable: true, get: getter });\n \t\t}\n \t};\n\n \t// define __esModule on exports\n \t__webpack_require__.r = function(exports) {\n \t\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n \t\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n \t\t}\n \t\tObject.defineProperty(exports, '__esModule', { value: true });\n \t};\n\n \t// create a fake namespace object\n \t// mode & 1: value is a module id, require it\n \t// mode & 2: merge all properties of value into the ns\n \t// mode & 4: return value when already ns object\n \t// mode & 8|1: behave like require\n \t__webpack_require__.t = function(value, mode) {\n \t\tif(mode & 1) value = __webpack_require__(value);\n \t\tif(mode & 8) return value;\n \t\tif((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;\n \t\tvar ns = Object.create(null);\n \t\t__webpack_require__.r(ns);\n \t\tObject.defineProperty(ns, 'default', { enumerable: true, value: value });\n \t\tif(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));\n \t\treturn ns;\n \t};\n\n \t// getDefaultExport function for compatibility with non-harmony modules\n \t__webpack_require__.n = function(module) {\n \t\tvar getter = module && module.__esModule ?\n \t\t\tfunction getDefault() { return module['default']; } :\n \t\t\tfunction getModuleExports() { return module; };\n \t\t__webpack_require__.d(getter, 'a', getter);\n \t\treturn getter;\n \t};\n\n \t// Object.prototype.hasOwnProperty.call\n \t__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };\n\n \t// __webpack_public_path__\n \t__webpack_require__.p = \"\";\n\n\n \t// Load entry module and return exports\n \treturn __webpack_require__(__webpack_require__.s = 0);\n","(function ( wp, config ) {\r\n\r\n const { registerPlugin } = wp.plugins;\r\n const { __ } = wp.i18n;\r\n const { PluginDocumentSettingPanel } = wp.editPost;\r\n const { PanelRow, DateTimePicker, CheckboxControl, SelectControl, FormTokenField, Spinner } = wp.components;\r\n const { Fragment, Component } = wp.element;\r\n const { decodeEntities } = wp.htmlEntities;\r\n const { isEmpty, keys, compact } = lodash;\r\n\r\n class PostExpiratorSidebar extends Component {\r\n constructor() {\r\n super( ...arguments );\r\n\r\n this.state = {\r\n categoriesList: [],\r\n catIdVsName: [],\r\n }\r\n }\r\n\r\n componentWillMount() {\r\n const { attributes } = this.state;\r\n\r\n const postMeta = wp.data.select( 'core/editor' ).getEditedPostAttribute( 'meta' );\r\n const postType = wp.data.select('core/editor').getCurrentPostType();\r\n\r\n let enabled = config.defaults.autoEnable == 1;\r\n let date = new Date();\r\n\r\n let expireAction = this.getExpireType(postMeta);\r\n\r\n let categories = [];\r\n if(expireAction.includes('category')){\r\n categories = this.getCategories(postMeta);\r\n }\r\n\r\n if(postMeta['_expiration-date-status'] && postMeta['_expiration-date-status'] === 'saved'){\r\n enabled = true;\r\n }\r\n\r\n if(postMeta['_expiration-date']){\r\n date.setTime((postMeta['_expiration-date'] + date.getTimezoneOffset() * 60) * 1000);\r\n }else{\r\n categories = config.default_categories;\r\n if(config.default_date){\r\n date.setTime((parseInt(config.default_date) + date.getTimezoneOffset() * 60) * 1000);\r\n // update the post meta for date so that the user does not have to click the date to set it\r\n const setPostMeta = (newMeta) => wp.data.dispatch( 'core/editor' ).editPost( { meta: newMeta } );\r\n setPostMeta( {'_expiration-date': this.getDate(date) } );\r\n }\r\n }\r\n\r\n let taxonomy = config.defaults.taxonomy || 'category';\r\n\r\n this.setState( {\r\n enabled: enabled,\r\n date: date,\r\n expireAction: expireAction,\r\n categories: categories,\r\n taxonomy: taxonomy,\r\n } );\r\n\r\n let categoriesList = [];\r\n let catIdVsName = [];\r\n\r\n if( (!taxonomy && postType === 'post') || taxonomy === 'category' ){\r\n wp.apiFetch( {\r\n path: wp.url.addQueryArgs( 'wp/v2/categories', { per_page: -1, hide_empty: false } ),\r\n } ).then( ( list ) => {\r\n list.forEach(cat => {\r\n categoriesList[ cat.name ] = cat;\r\n catIdVsName[ cat.id ] = cat.name;\r\n });\r\n this.setState( { categoriesList: categoriesList, catIdVsName: catIdVsName, taxonomy: __( 'Category' ) } );\r\n } );\r\n }else if(postType !== 'page') {\r\n wp.apiFetch( {\r\n path: wp.url.addQueryArgs( `wp/v2/taxonomies/${taxonomy}`, { context: 'edit' } ),\r\n } ).then( ( taxAttributes ) => {\r\n // fetch all terms\r\n wp.apiFetch( {\r\n path: wp.url.addQueryArgs( `wp/v2/${taxAttributes.rest_base}`, { context: 'edit' } ),\r\n } ).then( ( terms ) => {\r\n terms.forEach(term => {\r\n categoriesList[ decodeEntities(term.name) ] = term;\r\n catIdVsName[ term.id ] = decodeEntities(term.name);\r\n });\r\n this.setState( { categoriesList: categoriesList, catIdVsName: catIdVsName, taxonomy: decodeEntities(taxAttributes.name) } );\r\n });\r\n });\r\n }\r\n\r\n }\r\n\r\n componentDidUpdate() {\r\n const { enabled, date, expireAction, categories, attribute } = this.state;\r\n const setPostMeta = (newMeta) => wp.data.dispatch( 'core/editor' ).editPost( { meta: newMeta } );\r\n\r\n switch(attribute){\r\n case 'enabled':\r\n setPostMeta( { '_expiration-date-status' : (enabled ? 'saved' : '' ) } );\r\n break;\r\n case 'date':\r\n if(typeof date === 'string'){\r\n setPostMeta( {'_expiration-date': this.getDate(date) } );\r\n }\r\n break;\r\n case 'action':\r\n setPostMeta( { '_expiration-date-type': expireAction } );\r\n if(!expireAction.includes('category')){\r\n setPostMeta( { '_expiration-date-categories': [] } );\r\n }\r\n break;\r\n case 'category':\r\n setPostMeta( { '_expiration-date-categories': categories } );\r\n break;\r\n }\r\n\r\n }\r\n\r\n render() {\r\n const { categoriesList, catIdVsName } = this.state;\r\n const { enabled, date, expireAction, categories, taxonomy } = this.state;\r\n\r\n const postType = wp.data.select('core/editor').getCurrentPostType();\r\n\r\n let actionsList = [\r\n { label: __( 'Draft', 'post-expirator' ), value: 'draft' },\r\n { label: __( 'Delete', 'post-expirator' ), value: 'delete' },\r\n { label: __( 'Trash', 'post-expirator' ), value: 'trash' },\r\n { label: __( 'Private', 'post-expirator' ), value: 'private' },\r\n { label: __( 'Stick', 'post-expirator' ), value: 'stick' },\r\n { label: __( 'Unstick', 'post-expirator' ), value: 'unstick' },\r\n ];\r\n\r\n if(postType !== 'page'){\r\n actionsList = _.union(actionsList, [\r\n { label: __('Category: Replace', 'post-expirator'), value: 'category' },\r\n { label: __('Category: Add', 'post-expirator'), value: 'category-add' },\r\n { label: __('Category: Remove', 'post-expirator'), value: 'category-remove' },\r\n ]);\r\n }\r\n\r\n let selectedCats = categories && compact(categories.map((id) => catIdVsName[id] || false ));\r\n if(typeof selectedCats === 'string'){\r\n selectedCats = [];\r\n }\r\n \r\n return (\r\n <PluginDocumentSettingPanel title={ __( 'Post Expirator', 'post-expirator' ) } icon=\"calendar\" initialOpen={ enabled }>\r\n <PanelRow>\r\n <CheckboxControl\r\n label={ __( 'Enable Post Expiration', 'post-expirator' ) }\r\n checked={ enabled }\r\n onChange={ (value) => { this.setState( { enabled: !enabled, attribute: 'enabled' } ) } }\r\n />\r\n </PanelRow>\r\n { enabled && (\r\n <Fragment>\r\n <PanelRow>\r\n <DateTimePicker\r\n currentDate={ date }\r\n onChange={ ( value ) => this.setState( { date: value, attribute: 'date' } ) }\r\n is12Hour={ true }\r\n />\r\n </PanelRow>\r\n <SelectControl\r\n label={ __( 'How to expire', 'post-expirator' ) }\r\n value={ expireAction }\r\n options={ actionsList }\r\n onChange={ (value) => { this.setState( { expireAction: value, attribute: 'action' } ) } }\r\n />\r\n { expireAction.includes('category') && \r\n (\r\n ( isEmpty(keys(categoriesList)) && (\r\n <Fragment>\r\n { __( 'Loading', 'post-expirator' ) + ` (${taxonomy})` }\r\n <Spinner/>\r\n </Fragment>\r\n ) )\r\n ||\r\n (\r\n <FormTokenField\r\n label={ __('Expiration Categories', 'post-expirator') + ` (${taxonomy})` }\r\n value={ selectedCats }\r\n suggestions={ Object.keys(categoriesList) }\r\n onChange={ ( value ) => { this.setState( { categories: this.selectCategories(value), attribute: 'category' } ) } }\r\n maxSuggestions={ 10 }\r\n />\r\n )\r\n ) }\r\n </Fragment>\r\n ) }\r\n </PluginDocumentSettingPanel>\r\n );\r\n }\r\n\r\n // what action to take on expiration\r\n getExpireType(postMeta) {\r\n let typeNew = postMeta['_expiration-date-type'];\r\n let typeOld = postMeta['_expiration-date-options'] && postMeta['_expiration-date-options']['expireType'];\r\n\r\n if(typeNew){\r\n return typeNew;\r\n }\r\n\r\n if(typeOld){\r\n return typeOld;\r\n }\r\n\r\n return 'draft';\r\n }\r\n\r\n // what categories to add/remove/replace\r\n getCategories(postMeta) {\r\n let categoriesNew = postMeta['_expiration-date-categories'] && postMeta['_expiration-date-categories'];\r\n let categoriesOld = postMeta['_expiration-date-options'] && postMeta['_expiration-date-options']['category'];\r\n\r\n if(typeof categoriesNew === 'object' && categoriesNew.length > 0){\r\n return categoriesNew;\r\n }\r\n\r\n if(categoriesOld && typeof categoriesOld !== 'undefined' && typeof categoriesOld !== 'object'){\r\n categories = [ categoriesOld ];\r\n }\r\n\r\n return categoriesOld;\r\n\r\n }\r\n\r\n // fired for the autocomplete\r\n selectCategories(tokens) {\r\n const { categoriesList, catIdVsName } = this.state;\r\n\r\n var hasNoSuggestion = tokens.some(function (token) {\r\n return typeof token === 'string' && !categoriesList[token];\r\n });\r\n\r\n if (hasNoSuggestion) {\r\n return;\r\n }\r\n\r\n var categories = tokens.map(function (token) {\r\n return typeof token === 'string' ? categoriesList[token] : token;\r\n })\r\n\r\n return categories.map( (cat) => cat.id );\r\n }\r\n\r\n getDate(date){\r\n let newDate = new Date();\r\n newDate.setTime(Date.parse(date));\r\n newDate.setTime(newDate.getTime() - new Date().getTimezoneOffset() * 60 * 1000);\r\n return ((newDate.getTime()) / 1000);\r\n }\r\n\r\n }\r\n\r\n registerPlugin( 'postexpirator-sidebar', {\r\n render: PostExpiratorSidebar\r\n } );\r\n\r\n\r\n})( window.wp, config );"],"sourceRoot":""}
assets/js/settings.js ADDED
@@ -0,0 +1,15 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ (function($) {
2
+ $(document).ready(function(){
3
+ init();
4
+ });
5
+
6
+ function init() {
7
+ $('.pe-custom-date-toggle').on('change', function(e){
8
+ if($(this).val() === 'custom') {
9
+ $(this).siblings('.pe-custom-date-container').show();
10
+ }else{
11
+ $(this).siblings('.pe-custom-date-container').hide();
12
+ }
13
+ });
14
+ }
15
+ })(jQuery, config);
assets/jsx/block.jsx ADDED
@@ -0,0 +1,264 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ (function ( wp, config ) {
2
+
3
+ const { registerPlugin } = wp.plugins;
4
+ const { __ } = wp.i18n;
5
+ const { PluginDocumentSettingPanel } = wp.editPost;
6
+ const { PanelRow, DateTimePicker, CheckboxControl, SelectControl, FormTokenField, Spinner } = wp.components;
7
+ const { Fragment, Component } = wp.element;
8
+ const { decodeEntities } = wp.htmlEntities;
9
+ const { isEmpty, keys, compact } = lodash;
10
+
11
+ class PostExpiratorSidebar extends Component {
12
+ constructor() {
13
+ super( ...arguments );
14
+
15
+ this.state = {
16
+ categoriesList: [],
17
+ catIdVsName: [],
18
+ }
19
+ }
20
+
21
+ componentWillMount() {
22
+ const { attributes } = this.state;
23
+
24
+ const postMeta = wp.data.select( 'core/editor' ).getEditedPostAttribute( 'meta' );
25
+ const postType = wp.data.select('core/editor').getCurrentPostType();
26
+
27
+ let enabled = config.defaults.autoEnable == 1;
28
+ let date = new Date();
29
+
30
+ let expireAction = this.getExpireType(postMeta);
31
+
32
+ let categories = [];
33
+ if(expireAction.includes('category')){
34
+ categories = this.getCategories(postMeta);
35
+ }
36
+
37
+ if(postMeta['_expiration-date-status'] && postMeta['_expiration-date-status'] === 'saved'){
38
+ enabled = true;
39
+ }
40
+
41
+ if(postMeta['_expiration-date']){
42
+ date.setTime((postMeta['_expiration-date'] + date.getTimezoneOffset() * 60) * 1000);
43
+ }else{
44
+ categories = config.default_categories;
45
+ if(config.default_date){
46
+ date.setTime((parseInt(config.default_date) + date.getTimezoneOffset() * 60) * 1000);
47
+ // update the post meta for date so that the user does not have to click the date to set it
48
+ const setPostMeta = (newMeta) => wp.data.dispatch( 'core/editor' ).editPost( { meta: newMeta } );
49
+ setPostMeta( {'_expiration-date': this.getDate(date) } );
50
+ }
51
+ }
52
+
53
+ let taxonomy = config.defaults.taxonomy || 'category';
54
+
55
+ this.setState( {
56
+ enabled: enabled,
57
+ date: date,
58
+ expireAction: expireAction,
59
+ categories: categories,
60
+ taxonomy: taxonomy,
61
+ } );
62
+
63
+ let categoriesList = [];
64
+ let catIdVsName = [];
65
+
66
+ if( (!taxonomy && postType === 'post') || taxonomy === 'category' ){
67
+ wp.apiFetch( {
68
+ path: wp.url.addQueryArgs( 'wp/v2/categories', { per_page: -1, hide_empty: false } ),
69
+ } ).then( ( list ) => {
70
+ list.forEach(cat => {
71
+ categoriesList[ cat.name ] = cat;
72
+ catIdVsName[ cat.id ] = cat.name;
73
+ });
74
+ this.setState( { categoriesList: categoriesList, catIdVsName: catIdVsName, taxonomy: __( 'Category' ) } );
75
+ } );
76
+ }else if(postType !== 'page') {
77
+ wp.apiFetch( {
78
+ path: wp.url.addQueryArgs( `wp/v2/taxonomies/${taxonomy}`, { context: 'edit' } ),
79
+ } ).then( ( taxAttributes ) => {
80
+ // fetch all terms
81
+ wp.apiFetch( {
82
+ path: wp.url.addQueryArgs( `wp/v2/${taxAttributes.rest_base}`, { context: 'edit' } ),
83
+ } ).then( ( terms ) => {
84
+ terms.forEach(term => {
85
+ categoriesList[ decodeEntities(term.name) ] = term;
86
+ catIdVsName[ term.id ] = decodeEntities(term.name);
87
+ });
88
+ this.setState( { categoriesList: categoriesList, catIdVsName: catIdVsName, taxonomy: decodeEntities(taxAttributes.name) } );
89
+ });
90
+ });
91
+ }
92
+
93
+ }
94
+
95
+ componentDidUpdate() {
96
+ const { enabled, date, expireAction, categories, attribute } = this.state;
97
+ const setPostMeta = (newMeta) => wp.data.dispatch( 'core/editor' ).editPost( { meta: newMeta } );
98
+
99
+ switch(attribute){
100
+ case 'enabled':
101
+ setPostMeta( { '_expiration-date-status' : (enabled ? 'saved' : '' ) } );
102
+ break;
103
+ case 'date':
104
+ if(typeof date === 'string'){
105
+ setPostMeta( {'_expiration-date': this.getDate(date) } );
106
+ }
107
+ break;
108
+ case 'action':
109
+ setPostMeta( { '_expiration-date-type': expireAction } );
110
+ if(!expireAction.includes('category')){
111
+ setPostMeta( { '_expiration-date-categories': [] } );
112
+ }
113
+ break;
114
+ case 'category':
115
+ setPostMeta( { '_expiration-date-categories': categories } );
116
+ break;
117
+ }
118
+
119
+ }
120
+
121
+ render() {
122
+ const { categoriesList, catIdVsName } = this.state;
123
+ const { enabled, date, expireAction, categories, taxonomy } = this.state;
124
+
125
+ const postType = wp.data.select('core/editor').getCurrentPostType();
126
+
127
+ let actionsList = [
128
+ { label: __( 'Draft', 'post-expirator' ), value: 'draft' },
129
+ { label: __( 'Delete', 'post-expirator' ), value: 'delete' },
130
+ { label: __( 'Trash', 'post-expirator' ), value: 'trash' },
131
+ { label: __( 'Private', 'post-expirator' ), value: 'private' },
132
+ { label: __( 'Stick', 'post-expirator' ), value: 'stick' },
133
+ { label: __( 'Unstick', 'post-expirator' ), value: 'unstick' },
134
+ ];
135
+
136
+ if(postType !== 'page'){
137
+ actionsList = _.union(actionsList, [
138
+ { label: __('Category: Replace', 'post-expirator'), value: 'category' },
139
+ { label: __('Category: Add', 'post-expirator'), value: 'category-add' },
140
+ { label: __('Category: Remove', 'post-expirator'), value: 'category-remove' },
141
+ ]);
142
+ }
143
+
144
+ let selectedCats = categories && compact(categories.map((id) => catIdVsName[id] || false ));
145
+ if(typeof selectedCats === 'string'){
146
+ selectedCats = [];
147
+ }
148
+
149
+ return (
150
+ <PluginDocumentSettingPanel title={ __( 'Post Expirator', 'post-expirator' ) } icon="calendar" initialOpen={ enabled }>
151
+ <PanelRow>
152
+ <CheckboxControl
153
+ label={ __( 'Enable Post Expiration', 'post-expirator' ) }
154
+ checked={ enabled }
155
+ onChange={ (value) => { this.setState( { enabled: !enabled, attribute: 'enabled' } ) } }
156
+ />
157
+ </PanelRow>
158
+ { enabled && (
159
+ <Fragment>
160
+ <PanelRow>
161
+ <DateTimePicker
162
+ currentDate={ date }
163
+ onChange={ ( value ) => this.setState( { date: value, attribute: 'date' } ) }
164
+ is12Hour={ true }
165
+ />
166
+ </PanelRow>
167
+ <SelectControl
168
+ label={ __( 'How to expire', 'post-expirator' ) }
169
+ value={ expireAction }
170
+ options={ actionsList }
171
+ onChange={ (value) => { this.setState( { expireAction: value, attribute: 'action' } ) } }
172
+ />
173
+ { expireAction.includes('category') &&
174
+ (
175
+ ( isEmpty(keys(categoriesList)) && (
176
+ <Fragment>
177
+ { __( 'Loading', 'post-expirator' ) + ` (${taxonomy})` }
178
+ <Spinner/>
179
+ </Fragment>
180
+ ) )
181
+ ||
182
+ (
183
+ <FormTokenField
184
+ label={ __('Expiration Categories', 'post-expirator') + ` (${taxonomy})` }
185
+ value={ selectedCats }
186
+ suggestions={ Object.keys(categoriesList) }
187
+ onChange={ ( value ) => { this.setState( { categories: this.selectCategories(value), attribute: 'category' } ) } }
188
+ maxSuggestions={ 10 }
189
+ />
190
+ )
191
+ ) }
192
+ </Fragment>
193
+ ) }
194
+ </PluginDocumentSettingPanel>
195
+ );
196
+ }
197
+
198
+ // what action to take on expiration
199
+ getExpireType(postMeta) {
200
+ let typeNew = postMeta['_expiration-date-type'];
201
+ let typeOld = postMeta['_expiration-date-options'] && postMeta['_expiration-date-options']['expireType'];
202
+
203
+ if(typeNew){
204
+ return typeNew;
205
+ }
206
+
207
+ if(typeOld){
208
+ return typeOld;
209
+ }
210
+
211
+ return 'draft';
212
+ }
213
+
214
+ // what categories to add/remove/replace
215
+ getCategories(postMeta) {
216
+ let categoriesNew = postMeta['_expiration-date-categories'] && postMeta['_expiration-date-categories'];
217
+ let categoriesOld = postMeta['_expiration-date-options'] && postMeta['_expiration-date-options']['category'];
218
+
219
+ if(typeof categoriesNew === 'object' && categoriesNew.length > 0){
220
+ return categoriesNew;
221
+ }
222
+
223
+ if(categoriesOld && typeof categoriesOld !== 'undefined' && typeof categoriesOld !== 'object'){
224
+ categories = [ categoriesOld ];
225
+ }
226
+
227
+ return categoriesOld;
228
+
229
+ }
230
+
231
+ // fired for the autocomplete
232
+ selectCategories(tokens) {
233
+ const { categoriesList, catIdVsName } = this.state;
234
+
235
+ var hasNoSuggestion = tokens.some(function (token) {
236
+ return typeof token === 'string' && !categoriesList[token];
237
+ });
238
+
239
+ if (hasNoSuggestion) {
240
+ return;
241
+ }
242
+
243
+ var categories = tokens.map(function (token) {
244
+ return typeof token === 'string' ? categoriesList[token] : token;
245
+ })
246
+
247
+ return categories.map( (cat) => cat.id );
248
+ }
249
+
250
+ getDate(date){
251
+ let newDate = new Date();
252
+ newDate.setTime(Date.parse(date));
253
+ newDate.setTime(newDate.getTime() - new Date().getTimezoneOffset() * 60 * 1000);
254
+ return ((newDate.getTime()) / 1000);
255
+ }
256
+
257
+ }
258
+
259
+ registerPlugin( 'postexpirator-sidebar', {
260
+ render: PostExpiratorSidebar
261
+ } );
262
+
263
+
264
+ })( window.wp, config );
classes/Display.class.php ADDED
@@ -0,0 +1,258 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * The class that is responsible for all the displays.
5
+ */
6
+ class PostExpirator_Display {
7
+
8
+ /**
9
+ * The singleton instance.
10
+ */
11
+ private static $_instance = null;
12
+
13
+ /**
14
+ * Constructor.
15
+ */
16
+ private function __construct() {
17
+ $this->hooks();
18
+ }
19
+
20
+ /**
21
+ * Returns instance of the singleton.
22
+ */
23
+ public static function getInstance() {
24
+ if ( is_null( self::$_instance ) ) {
25
+ self::$_instance = new self();
26
+ }
27
+ return self::$_instance;
28
+ }
29
+
30
+ /**
31
+ * Initialize the hooks.
32
+ */
33
+ private function hooks() {
34
+ add_action( 'admin_menu', array( $this, 'add_menu' ) );
35
+ }
36
+
37
+ /**
38
+ * Add plugin page menu.
39
+ */
40
+ function add_menu() {
41
+ add_submenu_page( 'options-general.php', __( 'Post Expirator Options', 'post-expirator' ), __( 'Post Expirator', 'post-expirator' ), 'manage_options', POSTEXPIRATOR_BASENAME, array( self::$_instance, 'settings_tabs' ) );
42
+ }
43
+
44
+ /**
45
+ * Loads the specified tab.
46
+ */
47
+ public function load_tab( $tab ) {
48
+ switch ( $tab ) {
49
+ case 'general':
50
+ $this->menu_general();
51
+ break;
52
+ case 'defaults':
53
+ $this->menu_defaults();
54
+ break;
55
+ case 'diagnostics':
56
+ $this->menu_diagnostics();
57
+ break;
58
+ case 'viewdebug':
59
+ $this->menu_viewdebug();
60
+ break;
61
+ }
62
+ }
63
+
64
+ /**
65
+ * Creates the settings page.
66
+ */
67
+ public function settings_tabs() {
68
+ PostExpirator_Facade::load_assets( 'settings' );
69
+
70
+ $tab = isset( $_GET['tab'] ) ? $_GET['tab'] : '';
71
+ if ( empty( $tab ) ) {
72
+ $tab = 'general';
73
+ }
74
+
75
+ $tab_index = 0;
76
+
77
+ ob_start();
78
+
79
+ switch ( $tab ) {
80
+ case 'general':
81
+ $tab_index = 0;
82
+ $this->load_tab( 'general' );
83
+ break;
84
+ case 'defaults':
85
+ $this->load_tab( 'defaults' );
86
+ $tab_index = 1;
87
+ break;
88
+ case 'diagnostics':
89
+ $this->load_tab( 'diagnostics' );
90
+ $tab_index = 2;
91
+ break;
92
+ case 'viewdebug':
93
+ $this->load_tab( 'viewdebug' );
94
+ $tab_index = 3;
95
+ break;
96
+ }
97
+
98
+ $html = ob_get_clean();
99
+
100
+ $debug = postexpirator_debug(); // check for/load debug
101
+
102
+ $tabs = array( 'general', 'defaults', 'diagnostics' );
103
+ if ( POSTEXPIRATOR_DEBUG ) {
104
+ $tabs[] = 'viewdebug';
105
+ }
106
+
107
+ $this->render_template( 'tabs', array( 'tabs' => $tabs, 'tab_index' => $tab_index, 'html' => $html, 'tab' => $tab ) );
108
+
109
+ }
110
+
111
+ /**
112
+ * Diagnostics menu.
113
+ */
114
+ private function menu_diagnostics() {
115
+ if ( $_SERVER['REQUEST_METHOD'] === 'POST' ) {
116
+ if ( ! isset( $_POST['_postExpiratorMenuDiagnostics_nonce'] ) || ! wp_verify_nonce( $_POST['_postExpiratorMenuDiagnostics_nonce'], 'postexpirator_menu_diagnostics' ) ) {
117
+ print 'Form Validation Failure: Sorry, your nonce did not verify.';
118
+ exit;
119
+ }
120
+ if ( isset( $_POST['debugging-disable'] ) ) {
121
+ update_option( 'expirationdateDebug', 0 );
122
+ echo "<div id='message' class='updated fade'><p>";
123
+ _e( 'Debugging Disabled', 'post-expirator' );
124
+ echo '</p></div>';
125
+ } elseif ( isset( $_POST['debugging-enable'] ) ) {
126
+ update_option( 'expirationdateDebug', 1 );
127
+ echo "<div id='message' class='updated fade'><p>";
128
+ _e( 'Debugging Enabled', 'post-expirator' );
129
+ echo '</p></div>';
130
+ } elseif ( isset( $_POST['purge-debug'] ) ) {
131
+ require_once( plugin_dir_path( __FILE__ ) . 'post-expirator-debug.php' );
132
+ $debug = new PostExpiratorDebug();
133
+ $debug->purge();
134
+ echo "<div id='message' class='updated fade'><p>";
135
+ _e( 'Debugging Table Emptied', 'post-expirator' );
136
+ echo '</p></div>';
137
+ }
138
+ }
139
+
140
+ $debug = postexpirator_debug();
141
+
142
+ $this->render_template( 'menu-diagnostics' );
143
+ }
144
+
145
+ /**
146
+ * Debug menu.
147
+ */
148
+ private function menu_viewdebug() {
149
+ require_once POSTEXPIRATOR_BASEDIR . '/post-expirator-debug.php';
150
+ print '<p>' . __( 'Below is a dump of the debugging table, this should be useful for troubleshooting.', 'post-expirator' ) . '</p>';
151
+ $debug = new PostExpiratorDebug();
152
+ $debug->getTable();
153
+ }
154
+
155
+ /**
156
+ * The default menu.
157
+ */
158
+ private function menu_defaults() {
159
+ $debug = postexpirator_debug();
160
+ $types = postexpirator_get_post_types();
161
+ $defaults = array();
162
+
163
+ if ( isset( $_POST['expirationdateSaveDefaults'] ) ) {
164
+ if ( ! isset( $_POST['_postExpiratorMenuDefaults_nonce'] ) || ! wp_verify_nonce( $_POST['_postExpiratorMenuDefaults_nonce'], 'postexpirator_menu_defaults' ) ) {
165
+ print 'Form Validation Failure: Sorry, your nonce did not verify.';
166
+ exit;
167
+ } else {
168
+ // Filter Content
169
+ $_POST = filter_input_array( INPUT_POST, FILTER_SANITIZE_STRING );
170
+
171
+ foreach ( $types as $type ) {
172
+ if ( isset( $_POST[ 'expirationdate_expiretype-' . $type ] ) ) {
173
+ $defaults[ $type ]['expireType'] = $_POST[ 'expirationdate_expiretype-' . $type ];
174
+ }
175
+ if ( isset( $_POST[ 'expirationdate_autoenable-' . $type ] ) ) {
176
+ $defaults[ $type ]['autoEnable'] = intval( $_POST[ 'expirationdate_autoenable-' . $type ] );
177
+ }
178
+ if ( isset( $_POST[ 'expirationdate_taxonomy-' . $type ] ) ) {
179
+ $defaults[ $type ]['taxonomy'] = $_POST[ 'expirationdate_taxonomy-' . $type ];
180
+ }
181
+ if ( isset( $_POST[ 'expirationdate_activemeta-' . $type ] ) ) {
182
+ $defaults[ $type ]['activeMetaBox'] = $_POST[ 'expirationdate_activemeta-' . $type ];
183
+ }
184
+ $defaults[ $type ]['emailnotification'] = trim( $_POST[ 'expirationdate_emailnotification-' . $type ] );
185
+
186
+ if ( isset( $_POST[ 'expired-default-date-' . $type ] ) ) {
187
+ $defaults[ $type ]['default-expire-type'] = $_POST[ 'expired-default-date-' . $type ];
188
+ }
189
+ if ( isset( $_POST[ 'expired-custom-date-' . $type ] ) ) {
190
+ $defaults[ $type ]['default-custom-date'] = $_POST[ 'expired-custom-date-' . $type ];
191
+ }
192
+
193
+ // Save Settings
194
+ update_option( 'expirationdateDefaults' . ucfirst( $type ), $defaults[ $type ] );
195
+ }
196
+ echo "<div id='message' class='updated fade'><p>";
197
+ _e( 'Saved Options!', 'post-expirator' );
198
+ echo '</p></div>';
199
+ }
200
+ }
201
+
202
+ $this->render_template( 'menu-defaults', array( 'types' => $types, 'defaults' => $defaults ) );
203
+ }
204
+
205
+ /**
206
+ * Show the Expiration Date options page
207
+ */
208
+ private function menu_general() {
209
+ if ( isset( $_POST['expirationdateSave'] ) && $_POST['expirationdateSave'] ) {
210
+ if ( ! isset( $_POST['_postExpiratorMenuGeneral_nonce'] ) || ! wp_verify_nonce( $_POST['_postExpiratorMenuGeneral_nonce'], 'postexpirator_menu_general' ) ) {
211
+ print 'Form Validation Failure: Sorry, your nonce did not verify.';
212
+ exit;
213
+ } else {
214
+ // Filter Content
215
+ $_POST = filter_input_array( INPUT_POST, FILTER_SANITIZE_STRING );
216
+
217
+ update_option( 'expirationdateDefaultDateFormat', $_POST['expired-default-date-format'] );
218
+ update_option( 'expirationdateDefaultTimeFormat', $_POST['expired-default-time-format'] );
219
+ update_option( 'expirationdateDisplayFooter', $_POST['expired-display-footer'] );
220
+ update_option( 'expirationdateEmailNotification', $_POST['expired-email-notification'] );
221
+ update_option( 'expirationdateEmailNotificationAdmins', $_POST['expired-email-notification-admins'] );
222
+ update_option( 'expirationdateEmailNotificationList', trim( $_POST['expired-email-notification-list'] ) );
223
+ update_option( 'expirationdateFooterContents', $_POST['expired-footer-contents'] );
224
+ update_option( 'expirationdateFooterStyle', $_POST['expired-footer-style'] );
225
+ update_option( 'expirationdateGutenbergSupport', $_POST['gutenberg-support'] );
226
+ if ( isset( $_POST['expirationdate_category'] ) ) {
227
+ update_option( 'expirationdateCategoryDefaults', $_POST['expirationdate_category'] );
228
+ }
229
+ update_option( 'expirationdateDefaultDate', $_POST['expired-default-expiration-date'] );
230
+ if ( $_POST['expired-custom-expiration-date'] ) {
231
+ update_option( 'expirationdateDefaultDateCustom', $_POST['expired-custom-expiration-date'] );
232
+ }
233
+ echo "<div id='message' class='updated fade'><p>";
234
+ _e( 'Saved Options!', 'post-expirator' );
235
+ echo '</p></div>';
236
+ }
237
+ }
238
+
239
+ $this->render_template( 'menu-general' );
240
+ }
241
+
242
+ /**
243
+ * Renders a named template, if it is found.
244
+ */
245
+ public function render_template( $name, $params = null ) {
246
+ $template = POSTEXPIRATOR_BASEDIR . "/views/{$name}.php";
247
+ if ( file_exists( $template ) ) {
248
+ // expand all parameters so that they can be directly accessed with their name.
249
+ if ( $params ) {
250
+ foreach ( $params as $param => $value ) {
251
+ $$param = $value;
252
+ }
253
+ }
254
+ include $template;
255
+ }
256
+ }
257
+
258
+ }
classes/Facade.class.php ADDED
@@ -0,0 +1,372 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * The class that acts as a facade for the plugin's core functions.
5
+ *
6
+ * Eventually, everything should move here.
7
+ */
8
+ class PostExpirator_Facade {
9
+
10
+ /**
11
+ * The singleton instance.
12
+ */
13
+ private static $_instance = null;
14
+
15
+ /**
16
+ * Constructor.
17
+ */
18
+ private function __construct() {
19
+ PostExpirator_Display::getInstance();
20
+ $this->hooks();
21
+ }
22
+
23
+ /**
24
+ * Returns instance of the singleton.
25
+ */
26
+ public static function getInstance() {
27
+ if ( is_null( self::$_instance ) ) {
28
+ self::$_instance = new self();
29
+ }
30
+ return self::$_instance;
31
+ }
32
+
33
+ /**
34
+ * Initialize the hooks.
35
+ */
36
+ private function hooks() {
37
+ add_action( 'init', array( $this, 'register_post_meta' ), 11 );
38
+ add_action( 'enqueue_block_editor_assets', array( $this, 'block_editor_assets') );
39
+ add_action( 'updated_postmeta', array( $this, 'updatedmeta' ), 10, 4 );
40
+ }
41
+
42
+ /**
43
+ * Loads the assets for the particular page.
44
+ */
45
+ public static function load_assets( $for ) {
46
+ switch ( $for ) {
47
+ case 'settings':
48
+ wp_enqueue_script( 'pe-settings', POSTEXPIRATOR_BASEURL . '/assets/js/settings.js', array( 'jquery', 'jquery-ui-tabs' ), POSTEXPIRATOR_VERSION, false );
49
+ wp_localize_script( 'pe-settings', 'config', array() );
50
+ wp_enqueue_style( 'pe-settings', POSTEXPIRATOR_BASEURL . '/assets/css/settings.css', array(), POSTEXPIRATOR_VERSION, false );
51
+ wp_enqueue_style( 'pe-jquery-ui', POSTEXPIRATOR_BASEURL . '/assets/css/lib/jquery-ui/jquery-ui.min.css', array( 'pe-settings' ), POSTEXPIRATOR_VERSION );
52
+ break;
53
+ }
54
+ }
55
+
56
+
57
+ /**
58
+ * Fires when the post meta is updated (in the gutenberg block).
59
+ */
60
+ function updatedmeta( $meta_id, $post_id, $meta_key, $meta_value ) {
61
+ // allow only through gutenberg
62
+ if ( ! PostExpirator_Util::is_gutenberg_active() ) {
63
+ return;
64
+ }
65
+
66
+ // not through bulk edit.
67
+ if ( isset( $_POST['post_ids'] ) ) {
68
+ return;
69
+ }
70
+
71
+ // not through quick edit.
72
+ if ( isset( $_POST['expirationdate_quickedit'] ) ) {
73
+ return;
74
+ }
75
+
76
+ $unschedule = $schedule = false;
77
+ switch ( $meta_key ) {
78
+ case '_expiration-date-status':
79
+ $unschedule = empty( $meta_value );
80
+ break;
81
+ case '_expiration-date':
82
+ $schedule = true;
83
+ break;
84
+ }
85
+
86
+ remove_action( 'updated_postmeta', array( $this, 'updatedmeta' ), 10, 4 );
87
+ if ( $unschedule ) {
88
+ // @TODO the below delete_post_meta do not seem to work
89
+ delete_post_meta( $post_id, '_expiration-date' );
90
+ delete_post_meta( $post_id, '_expiration-date-options' );
91
+ delete_post_meta( $post_id, '_expiration-date-type' );
92
+ delete_post_meta( $post_id, '_expiration-date-categories' );
93
+ delete_post_meta( $post_id, '_expiration-date-taxonomy' );
94
+
95
+ $this->unschedule_event( $post_id );
96
+ }
97
+
98
+ if ( $schedule ) {
99
+ $opts = self::get_expire_principles( $post_id );
100
+ $ts = $meta_value;
101
+ $this->schedule_event( $post_id, $ts, $opts );
102
+ }
103
+ }
104
+
105
+ /**
106
+ * Calculates the default expiry date as set in the options.
107
+ */
108
+ public static function get_default_expiry( $post_type ) {
109
+ $defaultmonth = date_i18n( 'm' );
110
+ $defaultday = date_i18n( 'd' );
111
+ $defaulthour = date_i18n( 'H' );
112
+ $defaultyear = date_i18n( 'Y' );
113
+ $defaultminute = date_i18n( 'i' );
114
+ $ts = time();
115
+
116
+ $default_date_expiry = $custom_date = '';
117
+ $general_date_expiry = $general_custom_date = '';
118
+
119
+ // get the values from the general settings
120
+ $general_date_expiry = get_option( 'expirationdateDefaultDate', POSTEXPIRATOR_EXPIREDEFAULT );
121
+ if ( 'custom' === $general_date_expiry ) {
122
+ $custom = get_option( 'expirationdateDefaultDateCustom' );
123
+ if ( $custom !== false ) {
124
+ $general_custom_date = $custom;
125
+ }
126
+ }
127
+
128
+ // get the values from the post_type
129
+ $defaults = get_option( 'expirationdateDefaults' . ucfirst( $post_type ) );
130
+
131
+ if ( isset( $defaults['default-expire-type'] ) ) {
132
+ $default_date_expiry = $defaults['default-expire-type'];
133
+ switch ( $default_date_expiry ) {
134
+ case 'custom':
135
+ $custom_date = $defaults['default-custom-date'];
136
+ break;
137
+ case 'inherit':
138
+ $custom_date = $general_custom_date;
139
+ $default_date_expiry = $general_date_expiry;
140
+ break;
141
+ }
142
+ } else {
143
+ $default_date_expiry = $general_date_expiry;
144
+ $custom_date = $general_custom_date;
145
+ }
146
+
147
+ if ( 'custom' === $default_date_expiry ) {
148
+ $custom = get_option( 'expirationdateDefaultDateCustom' );
149
+ if ( ! empty( $custom_date ) ) {
150
+ $tz = get_option( 'timezone_string' );
151
+ if ( $tz ) {
152
+ // @TODO Using date_default_timezone_set() and similar isn't allowed, instead use WP internal timezone support.
153
+ // phpcs:ignore WordPress.DateTime.RestrictedFunctions.timezone_change_date_default_timezone_set
154
+ date_default_timezone_set( $tz );
155
+ }
156
+
157
+ // strip the quotes in case the user provides them.
158
+ $custom_date = str_replace( '"', '', html_entity_decode( $custom_date, ENT_QUOTES ) );
159
+
160
+ $ts = time() + ( strtotime( $custom_date ) - time() );
161
+ if ( $tz ) {
162
+ // @TODO Using date_default_timezone_set() and similar isn't allowed, instead use WP internal timezone support.
163
+ // phpcs:ignore WordPress.DateTime.RestrictedFunctions.timezone_change_date_default_timezone_set
164
+ date_default_timezone_set( 'UTC' );
165
+ }
166
+ }
167
+ $defaultmonth = get_date_from_gmt( gmdate( 'Y-m-d H:i:s', $ts ), 'm' );
168
+ $defaultday = get_date_from_gmt( gmdate( 'Y-m-d H:i:s', $ts ), 'd' );
169
+ $defaultyear = get_date_from_gmt( gmdate( 'Y-m-d H:i:s', $ts ), 'Y' );
170
+ $defaulthour = get_date_from_gmt( gmdate( 'Y-m-d H:i:s', $ts ), 'H' );
171
+ $defaultminute = get_date_from_gmt( gmdate( 'Y-m-d H:i:s', $ts ), 'i' );
172
+ }
173
+
174
+ return array(
175
+ 'month' => $defaultmonth,
176
+ 'day' => $defaultday,
177
+ 'year' => $defaultyear,
178
+ 'hour' => $defaulthour,
179
+ 'minute' => $defaultminute,
180
+ 'ts' => $ts,
181
+ );
182
+ }
183
+
184
+ /**
185
+ * Set the expire type, categories etc. corresponding to the new (gutenberg) structure.
186
+ */
187
+ public static function set_expire_principles( $id, $opts ) {
188
+ update_post_meta( $id, '_expiration-date-options', $opts );
189
+ update_post_meta( $id, '_expiration-date-type', $opts['expireType'] );
190
+ update_post_meta( $id, '_expiration-date-categories', isset( $opts['category'] ) ? $opts['category'] : array() );
191
+ update_post_meta( $id, '_expiration-date-taxonomy', isset( $opts['categoryTaxonomy'] ) ? $opts['categoryTaxonomy'] : '' );
192
+ }
193
+
194
+ /**
195
+ * Get the expire type, categories etc.
196
+ *
197
+ * Keeps in mind the old (classic editor) and new (gutenberg) structure.
198
+ */
199
+ public static function get_expire_principles( $id ) {
200
+ $expireType = $categories = $taxonomyName = '';
201
+
202
+ $expireTypeNew = get_post_meta( $id, '_expiration-date-type', true );
203
+ if ( ! empty( $expireTypeNew ) ) {
204
+ $expireType = $expireTypeNew;
205
+ }
206
+
207
+ $categoriesNew = get_post_meta( $id, '_expiration-date-categories', true );
208
+ if ( ! empty( $categoriesNew ) ) {
209
+ $categories = $categoriesNew;
210
+ }
211
+
212
+ $taxonomyNameNew = get_post_meta( $id, '_expiration-date-taxonomy', true );
213
+ if ( ! empty( $taxonomyNameNew ) ) {
214
+ $taxonomyName = $taxonomyNameNew;
215
+ }
216
+
217
+ // _expiration-date-options is deprecated when using block editor
218
+ $opts = get_post_meta( $id, '_expiration-date-options', true );
219
+ if ( empty( $expireType ) && isset( $opts['expireType'] ) ) {
220
+ $expireType = $opts['expireType'];
221
+ }
222
+ if ( empty( $categories ) ) {
223
+ $categories = isset( $opts['category'] ) ? $opts['category'] : false;
224
+ }
225
+
226
+ if ( empty( $taxonomyName ) ) {
227
+ $taxonomyName = isset( $opts['categoryTaxonomy'] ) ? $opts['categoryTaxonomy'] : '';
228
+ }
229
+
230
+ return array(
231
+ 'expireType' => $expireType,
232
+ 'category' => $categories,
233
+ 'categoryTaxonomy' => $taxonomyName,
234
+ );
235
+ }
236
+
237
+
238
+ /**
239
+ * Register the post meta to use in the block.
240
+ */
241
+ function register_post_meta() {
242
+ $post_types = get_post_types( array('public' => true) );
243
+ foreach ( $post_types as $post_type ) {
244
+
245
+ // this is important for CPTs to show the postMeta.
246
+ add_post_type_support( $post_type, array( 'custom-fields' ) );
247
+
248
+ register_post_meta(
249
+ $post_type, '_expiration-date-status', array(
250
+ 'single' => true,
251
+ 'type' => 'string',
252
+ 'auth_callback' => function() {
253
+ return current_user_can( 'edit_posts' );
254
+ },
255
+ 'show_in_rest' => true,
256
+ )
257
+ );
258
+ register_post_meta(
259
+ $post_type, '_expiration-date', array(
260
+ 'single' => true,
261
+ 'type' => 'number',
262
+ 'auth_callback' => function() {
263
+ return current_user_can( 'edit_posts' );
264
+ },
265
+ 'show_in_rest' => true,
266
+ )
267
+ );
268
+ register_post_meta(
269
+ $post_type, '_expiration-date-type', array(
270
+ 'single' => true,
271
+ 'type' => 'string',
272
+ 'auth_callback' => function() {
273
+ return current_user_can( 'edit_posts' );
274
+ },
275
+ 'show_in_rest' => true,
276
+ )
277
+ );
278
+ register_post_meta(
279
+ $post_type, '_expiration-date-categories', array(
280
+ 'single' => true,
281
+ 'type' => 'array',
282
+ 'auth_callback' => function() {
283
+ return current_user_can( 'edit_posts' );
284
+ },
285
+ 'show_in_rest' => array(
286
+ 'schema' => array(
287
+ 'type' => 'array',
288
+ 'items' => array(
289
+ 'type' => 'number',
290
+ ),
291
+ ),
292
+ ),
293
+ )
294
+ );
295
+
296
+ // this is the old complex field that we are now deprecating
297
+ // as it cannot be used easily in the block editor
298
+ register_post_meta(
299
+ $post_type, '_expiration-date-options', array(
300
+ 'single' => true,
301
+ 'type' => 'object',
302
+ 'auth_callback' => function() {
303
+ return current_user_can( 'edit_posts' );
304
+ },
305
+ 'show_in_rest' => array(
306
+ 'schema' => array(
307
+ 'type' => 'object',
308
+ 'additionalProperties' => true,
309
+ ),
310
+ ),
311
+ )
312
+ );
313
+
314
+ }
315
+ }
316
+
317
+ /**
318
+ * Load the block's backend assets only if the meta box is active for this post type.
319
+ */
320
+ function block_editor_assets() {
321
+ global $post;
322
+
323
+ if ( ! $post || ! self::show_gutenberg_metabox() ) {
324
+ return;
325
+ }
326
+
327
+ $defaults = get_option( 'expirationdateDefaults' . ucfirst( $post->post_type ) );
328
+ // if settings are not configured, show the metabox by default only for posts and pages
329
+ if ( ( ! isset( $defaults['activeMetaBox'] ) && in_array( $post->post_type, array( 'post', 'page' ), true ) ) || $defaults['activeMetaBox'] === 'active' ) {
330
+ wp_enqueue_script(
331
+ 'postexpirator-block',
332
+ POSTEXPIRATOR_BASEURL . 'assets/js/block.js',
333
+ array( 'wp-edit-post' ),
334
+ POSTEXPIRATOR_VERSION,
335
+ true
336
+ );
337
+
338
+ $default_expiry = PostExpirator_Facade::get_default_expiry( $post->post_type );
339
+ wp_localize_script(
340
+ 'postexpirator-block', 'config', array(
341
+ 'defaults' => $defaults,
342
+ 'default_date' => $default_expiry['ts'],
343
+ 'default_categories' => get_option( 'expirationdateCategoryDefaults' ),
344
+ )
345
+ );
346
+
347
+ }
348
+ }
349
+
350
+ /**
351
+ * Is the (default) Gutenberg-style box enabled in options?
352
+ */
353
+ public static function show_gutenberg_metabox() {
354
+ $gutenberg = get_option( 'expirationdateGutenbergSupport', 1 );
355
+ return intval( $gutenberg ) === 1;
356
+ }
357
+
358
+ /**
359
+ * Wrapper for unscheduling event.
360
+ */
361
+ private function unschedule_event( $post_id ) {
362
+ postexpirator_unschedule_event( $post_id );
363
+ }
364
+
365
+ /**
366
+ * Wrapper for scheduling event.
367
+ */
368
+ private function schedule_event( $post_id, $ts, $opts ) {
369
+ postexpirator_schedule_event( $post_id, $ts, $opts );
370
+ }
371
+
372
+ }
classes/Util.class.php ADDED
@@ -0,0 +1,51 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Utility functions.
5
+ */
6
+ class PostExpirator_Util {
7
+
8
+ /**
9
+ * Check if Block Editor is active.
10
+ * Must only be used after plugins_loaded action is fired.
11
+ *
12
+ * @return bool
13
+ */
14
+ public static function is_gutenberg_active() {
15
+ // Gutenberg plugin is installed and activated.
16
+ $gutenberg = ! ( false === has_filter( 'replace_editor', 'gutenberg_init' ) );
17
+
18
+ // Block editor since 5.0.
19
+ $block_editor = version_compare( $GLOBALS['wp_version'], '5.0-beta', '>' );
20
+
21
+ if ( ! $gutenberg && ! $block_editor ) {
22
+ return false;
23
+ }
24
+
25
+ if ( self::is_classic_editor_plugin_active() ) {
26
+ $editor_option = get_option( 'classic-editor-replace' );
27
+ $block_editor_active = array( 'no-replace', 'block' );
28
+
29
+ return in_array( $editor_option, $block_editor_active, true );
30
+ }
31
+
32
+ return true;
33
+ }
34
+
35
+ /**
36
+ * Check if Classic Editor plugin is active.
37
+ *
38
+ * @return bool
39
+ */
40
+ private static function is_classic_editor_plugin_active() {
41
+ if ( ! function_exists( 'is_plugin_active' ) ) {
42
+ include_once ABSPATH . 'wp-admin/includes/plugin.php';
43
+ }
44
+
45
+ if ( is_plugin_active( 'classic-editor/classic-editor.php' ) ) {
46
+ return true;
47
+ }
48
+
49
+ return false;
50
+ }
51
+ }
composer.json ADDED
@@ -0,0 +1,39 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "name": "publishpress/post-expirator",
3
+ "type": "wordpress-plugin",
4
+ "license": "GPL-2.0-or-later",
5
+ "description": "",
6
+ "authors": [
7
+ {
8
+ "name": "PublishPress",
9
+ "email": "help@publishpress.com",
10
+ "homepage": "https://publishpress.com",
11
+ "role": "Developer"
12
+ },
13
+ {
14
+ "name": "Aaron Axelsen",
15
+ "homepage": "http://postexpirator.tuxdocs.net/"
16
+ }
17
+ ],
18
+ "config": {
19
+ "preferred-install": "dist"
20
+ },
21
+ "minimum-stability": "stable",
22
+ "repositories": [
23
+ {
24
+ "type": "git",
25
+ "url": "https://github.com/publishpress/PublishPress-Plugin-Builder"
26
+ }
27
+ ],
28
+ "dist": {
29
+ "url": "https://github.com/publishpress/PublishPress-Future/releases/download/v2.5.0/publishpress-authors-2.5.0.zip",
30
+ "type": "zip"
31
+ },
32
+ "require-dev": {
33
+ "dealerdirect/phpcodesniffer-composer-installer": "*",
34
+ "squizlabs/php_codesniffer": "3.*",
35
+ "phpcompatibility/php-compatibility": "*",
36
+ "wp-coding-standards/wpcs": "*",
37
+ "publishpress/publishpress-plugin-builder": "^1.3"
38
+ }
39
+ }
composer.lock ADDED
@@ -0,0 +1,2454 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "_readme": [
3
+ "This file locks the dependencies of your project to a known state",
4
+ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
5
+ "This file is @generated automatically"
6
+ ],
7
+ "content-hash": "0795226c327436b714b82f47a10656a1",
8
+ "packages": [],
9
+ "packages-dev": [
10
+ {
11
+ "name": "consolidation/annotated-command",
12
+ "version": "4.3.1",
13
+ "source": {
14
+ "type": "git",
15
+ "url": "https://github.com/consolidation/annotated-command.git",
16
+ "reference": "386d2c9253675bbb4b7f04c6bc52f8e74c0d4cc6"
17
+ },
18
+ "dist": {
19
+ "type": "zip",
20
+ "url": "https://api.github.com/repos/consolidation/annotated-command/zipball/386d2c9253675bbb4b7f04c6bc52f8e74c0d4cc6",
21
+ "reference": "386d2c9253675bbb4b7f04c6bc52f8e74c0d4cc6",
22
+ "shasum": ""
23
+ },
24
+ "require": {
25
+ "consolidation/output-formatters": "^4.1.1",
26
+ "php": ">=7.1.3",
27
+ "psr/log": "^1|^2",
28
+ "symfony/console": "^4.4.8|~5.1.0",
29
+ "symfony/event-dispatcher": "^4.4.8|^5",
30
+ "symfony/finder": "^4.4.8|^5"
31
+ },
32
+ "require-dev": {
33
+ "phpunit/phpunit": "^7.5.20 || ^8 || ^9",
34
+ "squizlabs/php_codesniffer": "^3",
35
+ "yoast/phpunit-polyfills": "^0.2.0"
36
+ },
37
+ "type": "library",
38
+ "extra": {
39
+ "branch-alias": {
40
+ "dev-main": "4.x-dev"
41
+ }
42
+ },
43
+ "autoload": {
44
+ "psr-4": {
45
+ "Consolidation\\AnnotatedCommand\\": "src"
46
+ }
47
+ },
48
+ "notification-url": "https://packagist.org/downloads/",
49
+ "license": [
50
+ "MIT"
51
+ ],
52
+ "authors": [
53
+ {
54
+ "name": "Greg Anderson",
55
+ "email": "greg.1.anderson@greenknowe.org"
56
+ }
57
+ ],
58
+ "description": "Initialize Symfony Console commands from annotated command class methods.",
59
+ "support": {
60
+ "issues": "https://github.com/consolidation/annotated-command/issues",
61
+ "source": "https://github.com/consolidation/annotated-command/tree/4.3.1"
62
+ },
63
+ "time": "2021-08-30T03:50:47+00:00"
64
+ },
65
+ {
66
+ "name": "consolidation/config",
67
+ "version": "2.0.1",
68
+ "source": {
69
+ "type": "git",
70
+ "url": "https://github.com/consolidation/config.git",
71
+ "reference": "9a2c2a7b2aea1b3525984a4378743a8b74c14e1c"
72
+ },
73
+ "dist": {
74
+ "type": "zip",
75
+ "url": "https://api.github.com/repos/consolidation/config/zipball/9a2c2a7b2aea1b3525984a4378743a8b74c14e1c",
76
+ "reference": "9a2c2a7b2aea1b3525984a4378743a8b74c14e1c",
77
+ "shasum": ""
78
+ },
79
+ "require": {
80
+ "dflydev/dot-access-data": "^1.1.0",
81
+ "grasmash/expander": "^1",
82
+ "php": ">=7.1.3",
83
+ "psr/log": "^1.1",
84
+ "symfony/event-dispatcher": "^4||^5"
85
+ },
86
+ "require-dev": {
87
+ "phpunit/phpunit": ">=7.5.20",
88
+ "squizlabs/php_codesniffer": "^3",
89
+ "symfony/console": "^4||^5",
90
+ "symfony/yaml": "^4||^5",
91
+ "yoast/phpunit-polyfills": "^0.2.0"
92
+ },
93
+ "suggest": {
94
+ "symfony/event-dispatcher": "Required to inject configuration into Command options",
95
+ "symfony/yaml": "Required to use Consolidation\\Config\\Loader\\YamlConfigLoader"
96
+ },
97
+ "type": "library",
98
+ "extra": {
99
+ "branch-alias": {
100
+ "dev-main": "2.x-dev"
101
+ }
102
+ },
103
+ "autoload": {
104
+ "psr-4": {
105
+ "Consolidation\\Config\\": "src"
106
+ }
107
+ },
108
+ "notification-url": "https://packagist.org/downloads/",
109
+ "license": [
110
+ "MIT"
111
+ ],
112
+ "authors": [
113
+ {
114
+ "name": "Greg Anderson",
115
+ "email": "greg.1.anderson@greenknowe.org"
116
+ }
117
+ ],
118
+ "description": "Provide configuration services for a commandline tool.",
119
+ "support": {
120
+ "issues": "https://github.com/consolidation/config/issues",
121
+ "source": "https://github.com/consolidation/config/tree/2.0.1"
122
+ },
123
+ "time": "2020-12-06T00:03:30+00:00"
124
+ },
125
+ {
126
+ "name": "consolidation/log",
127
+ "version": "2.0.2",
128
+ "source": {
129
+ "type": "git",
130
+ "url": "https://github.com/consolidation/log.git",
131
+ "reference": "82a2aaaa621a7b976e50a745a8d249d5085ee2b1"
132
+ },
133
+ "dist": {
134
+ "type": "zip",
135
+ "url": "https://api.github.com/repos/consolidation/log/zipball/82a2aaaa621a7b976e50a745a8d249d5085ee2b1",
136
+ "reference": "82a2aaaa621a7b976e50a745a8d249d5085ee2b1",
137
+ "shasum": ""
138
+ },
139
+ "require": {
140
+ "php": ">=7.1.3",
141
+ "psr/log": "^1.0",
142
+ "symfony/console": "^4|^5"
143
+ },
144
+ "require-dev": {
145
+ "phpunit/phpunit": ">=7.5.20",
146
+ "squizlabs/php_codesniffer": "^3",
147
+ "yoast/phpunit-polyfills": "^0.2.0"
148
+ },
149
+ "type": "library",
150
+ "extra": {
151
+ "branch-alias": {
152
+ "dev-main": "2.x-dev"
153
+ }
154
+ },
155
+ "autoload": {
156
+ "psr-4": {
157
+ "Consolidation\\Log\\": "src"
158
+ }
159
+ },
160
+ "notification-url": "https://packagist.org/downloads/",
161
+ "license": [
162
+ "MIT"
163
+ ],
164
+ "authors": [
165
+ {
166
+ "name": "Greg Anderson",
167
+ "email": "greg.1.anderson@greenknowe.org"
168
+ }
169
+ ],
170
+ "description": "Improved Psr-3 / Psr\\Log logger based on Symfony Console components.",
171
+ "support": {
172
+ "issues": "https://github.com/consolidation/log/issues",
173
+ "source": "https://github.com/consolidation/log/tree/2.0.2"
174
+ },
175
+ "time": "2020-12-10T16:26:23+00:00"
176
+ },
177
+ {
178
+ "name": "consolidation/output-formatters",
179
+ "version": "4.1.2",
180
+ "source": {
181
+ "type": "git",
182
+ "url": "https://github.com/consolidation/output-formatters.git",
183
+ "reference": "5821e6ae076bf690058a4de6c94dce97398a69c9"
184
+ },
185
+ "dist": {
186
+ "type": "zip",
187
+ "url": "https://api.github.com/repos/consolidation/output-formatters/zipball/5821e6ae076bf690058a4de6c94dce97398a69c9",
188
+ "reference": "5821e6ae076bf690058a4de6c94dce97398a69c9",
189
+ "shasum": ""
190
+ },
191
+ "require": {
192
+ "dflydev/dot-access-data": "^1.1.0",
193
+ "php": ">=7.1.3",
194
+ "symfony/console": "^4|^5",
195
+ "symfony/finder": "^4|^5"
196
+ },
197
+ "require-dev": {
198
+ "php-coveralls/php-coveralls": "^2.4.2",
199
+ "phpunit/phpunit": ">=7",
200
+ "squizlabs/php_codesniffer": "^3",
201
+ "symfony/var-dumper": "^4",
202
+ "symfony/yaml": "^4",
203
+ "yoast/phpunit-polyfills": "^0.2.0"
204
+ },
205
+ "suggest": {
206
+ "symfony/var-dumper": "For using the var_dump formatter"
207
+ },
208
+ "type": "library",
209
+ "extra": {
210
+ "branch-alias": {
211
+ "dev-main": "4.x-dev"
212
+ }
213
+ },
214
+ "autoload": {
215
+ "psr-4": {
216
+ "Consolidation\\OutputFormatters\\": "src"
217
+ }
218
+ },
219
+ "notification-url": "https://packagist.org/downloads/",
220
+ "license": [
221
+ "MIT"
222
+ ],
223
+ "authors": [
224
+ {
225
+ "name": "Greg Anderson",
226
+ "email": "greg.1.anderson@greenknowe.org"
227
+ }
228
+ ],
229
+ "description": "Format text by applying transformations provided by plug-in formatters.",
230
+ "support": {
231
+ "issues": "https://github.com/consolidation/output-formatters/issues",
232
+ "source": "https://github.com/consolidation/output-formatters/tree/4.1.2"
233
+ },
234
+ "time": "2020-12-12T19:04:59+00:00"
235
+ },
236
+ {
237
+ "name": "consolidation/robo",
238
+ "version": "2.2.2",
239
+ "source": {
240
+ "type": "git",
241
+ "url": "https://github.com/consolidation/Robo.git",
242
+ "reference": "b365df174d9cfb0f5814e4f3275a1c558b17bc4c"
243
+ },
244
+ "dist": {
245
+ "type": "zip",
246
+ "url": "https://api.github.com/repos/consolidation/Robo/zipball/b365df174d9cfb0f5814e4f3275a1c558b17bc4c",
247
+ "reference": "b365df174d9cfb0f5814e4f3275a1c558b17bc4c",
248
+ "shasum": ""
249
+ },
250
+ "require": {
251
+ "consolidation/annotated-command": "^4.2.1",
252
+ "consolidation/config": "^1.2.1|^2",
253
+ "consolidation/log": "^1.1.1|^2.0.1",
254
+ "consolidation/output-formatters": "^4.1.1",
255
+ "consolidation/self-update": "^1.2",
256
+ "league/container": "^2.4.1",
257
+ "php": ">=7.1.3",
258
+ "symfony/console": "^4.4.11|^5",
259
+ "symfony/event-dispatcher": "^4.4.11|^5",
260
+ "symfony/filesystem": "^4.4.11|^5",
261
+ "symfony/finder": "^4.4.11|^5",
262
+ "symfony/process": "^4.4.11|^5",
263
+ "symfony/yaml": "^4.0 || ^5.0"
264
+ },
265
+ "conflict": {
266
+ "codegyre/robo": "*"
267
+ },
268
+ "require-dev": {
269
+ "g1a/composer-test-scenarios": "^3",
270
+ "natxet/cssmin": "3.0.4",
271
+ "patchwork/jsqueeze": "^2",
272
+ "pear/archive_tar": "^1.4.4",
273
+ "php-coveralls/php-coveralls": "^2.2",
274
+ "phpdocumentor/reflection-docblock": "^4.3.2",
275
+ "phpunit/phpunit": "^6.5.14",
276
+ "squizlabs/php_codesniffer": "^3"
277
+ },
278
+ "suggest": {
279
+ "henrikbjorn/lurker": "For monitoring filesystem changes in taskWatch",
280
+ "natxet/cssmin": "For minifying CSS files in taskMinify",
281
+ "patchwork/jsqueeze": "For minifying JS files in taskMinify",
282
+ "pear/archive_tar": "Allows tar archives to be created and extracted in taskPack and taskExtract, respectively."
283
+ },
284
+ "bin": [
285
+ "robo"
286
+ ],
287
+ "type": "library",
288
+ "extra": {
289
+ "scenarios": {
290
+ "symfony4": {
291
+ "require": {
292
+ "symfony/console": "^4.4.11",
293
+ "symfony/event-dispatcher": "^4.4.11",
294
+ "symfony/filesystem": "^4.4.11",
295
+ "symfony/finder": "^4.4.11",
296
+ "symfony/process": "^4.4.11",
297
+ "phpunit/phpunit": "^6",
298
+ "nikic/php-parser": "^2"
299
+ },
300
+ "remove": [
301
+ "codeception/phpunit-wrapper"
302
+ ],
303
+ "config": {
304
+ "platform": {
305
+ "php": "7.1.3"
306
+ }
307
+ }
308
+ }
309
+ },
310
+ "branch-alias": {
311
+ "dev-master": "2.x-dev",
312
+ "dev-main": "2.x-dev"
313
+ }
314
+ },
315
+ "autoload": {
316
+ "psr-4": {
317
+ "Robo\\": "src"
318
+ }
319
+ },
320
+ "notification-url": "https://packagist.org/downloads/",
321
+ "license": [
322
+ "MIT"
323
+ ],
324
+ "authors": [
325
+ {
326
+ "name": "Davert",
327
+ "email": "davert.php@resend.cc"
328
+ }
329
+ ],
330
+ "description": "Modern task runner",
331
+ "support": {
332
+ "issues": "https://github.com/consolidation/Robo/issues",
333
+ "source": "https://github.com/consolidation/Robo/tree/2.2.2"
334
+ },
335
+ "time": "2020-12-18T22:09:18+00:00"
336
+ },
337
+ {
338
+ "name": "consolidation/self-update",
339
+ "version": "1.2.0",
340
+ "source": {
341
+ "type": "git",
342
+ "url": "https://github.com/consolidation/self-update.git",
343
+ "reference": "dba6b2c0708f20fa3ba8008a2353b637578849b4"
344
+ },
345
+ "dist": {
346
+ "type": "zip",
347
+ "url": "https://api.github.com/repos/consolidation/self-update/zipball/dba6b2c0708f20fa3ba8008a2353b637578849b4",
348
+ "reference": "dba6b2c0708f20fa3ba8008a2353b637578849b4",
349
+ "shasum": ""
350
+ },
351
+ "require": {
352
+ "php": ">=5.5.0",
353
+ "symfony/console": "^2.8|^3|^4|^5",
354
+ "symfony/filesystem": "^2.5|^3|^4|^5"
355
+ },
356
+ "bin": [
357
+ "scripts/release"
358
+ ],
359
+ "type": "library",
360
+ "extra": {
361
+ "branch-alias": {
362
+ "dev-master": "1.x-dev"
363
+ }
364
+ },
365
+ "autoload": {
366
+ "psr-4": {
367
+ "SelfUpdate\\": "src"
368
+ }
369
+ },
370
+ "notification-url": "https://packagist.org/downloads/",
371
+ "license": [
372
+ "MIT"
373
+ ],
374
+ "authors": [
375
+ {
376
+ "name": "Alexander Menk",
377
+ "email": "menk@mestrona.net"
378
+ },
379
+ {
380
+ "name": "Greg Anderson",
381
+ "email": "greg.1.anderson@greenknowe.org"
382
+ }
383
+ ],
384
+ "description": "Provides a self:update command for Symfony Console applications.",
385
+ "support": {
386
+ "issues": "https://github.com/consolidation/self-update/issues",
387
+ "source": "https://github.com/consolidation/self-update/tree/1.2.0"
388
+ },
389
+ "time": "2020-04-13T02:49:20+00:00"
390
+ },
391
+ {
392
+ "name": "container-interop/container-interop",
393
+ "version": "1.2.0",
394
+ "source": {
395
+ "type": "git",
396
+ "url": "https://github.com/container-interop/container-interop.git",
397
+ "reference": "79cbf1341c22ec75643d841642dd5d6acd83bdb8"
398
+ },
399
+ "dist": {
400
+ "type": "zip",
401
+ "url": "https://api.github.com/repos/container-interop/container-interop/zipball/79cbf1341c22ec75643d841642dd5d6acd83bdb8",
402
+ "reference": "79cbf1341c22ec75643d841642dd5d6acd83bdb8",
403
+ "shasum": ""
404
+ },
405
+ "require": {
406
+ "psr/container": "^1.0"
407
+ },
408
+ "type": "library",
409
+ "autoload": {
410
+ "psr-4": {
411
+ "Interop\\Container\\": "src/Interop/Container/"
412
+ }
413
+ },
414
+ "notification-url": "https://packagist.org/downloads/",
415
+ "license": [
416
+ "MIT"
417
+ ],
418
+ "description": "Promoting the interoperability of container objects (DIC, SL, etc.)",
419
+ "homepage": "https://github.com/container-interop/container-interop",
420
+ "support": {
421
+ "issues": "https://github.com/container-interop/container-interop/issues",
422
+ "source": "https://github.com/container-interop/container-interop/tree/master"
423
+ },
424
+ "abandoned": "psr/container",
425
+ "time": "2017-02-14T19:40:03+00:00"
426
+ },
427
+ {
428
+ "name": "dealerdirect/phpcodesniffer-composer-installer",
429
+ "version": "v0.7.1",
430
+ "source": {
431
+ "type": "git",
432
+ "url": "https://github.com/Dealerdirect/phpcodesniffer-composer-installer.git",
433
+ "reference": "fe390591e0241955f22eb9ba327d137e501c771c"
434
+ },
435
+ "dist": {
436
+ "type": "zip",
437
+ "url": "https://api.github.com/repos/Dealerdirect/phpcodesniffer-composer-installer/zipball/fe390591e0241955f22eb9ba327d137e501c771c",
438
+ "reference": "fe390591e0241955f22eb9ba327d137e501c771c",
439
+ "shasum": ""
440
+ },
441
+ "require": {
442
+ "composer-plugin-api": "^1.0 || ^2.0",
443
+ "php": ">=5.3",
444
+ "squizlabs/php_codesniffer": "^2.0 || ^3.0 || ^4.0"
445
+ },
446
+ "require-dev": {
447
+ "composer/composer": "*",
448
+ "phpcompatibility/php-compatibility": "^9.0",
449
+ "sensiolabs/security-checker": "^4.1.0"
450
+ },
451
+ "type": "composer-plugin",
452
+ "extra": {
453
+ "class": "Dealerdirect\\Composer\\Plugin\\Installers\\PHPCodeSniffer\\Plugin"
454
+ },
455
+ "autoload": {
456
+ "psr-4": {
457
+ "Dealerdirect\\Composer\\Plugin\\Installers\\PHPCodeSniffer\\": "src/"
458
+ }
459
+ },
460
+ "notification-url": "https://packagist.org/downloads/",
461
+ "license": [
462
+ "MIT"
463
+ ],
464
+ "authors": [
465
+ {
466
+ "name": "Franck Nijhof",
467
+ "email": "franck.nijhof@dealerdirect.com",
468
+ "homepage": "http://www.frenck.nl",
469
+ "role": "Developer / IT Manager"
470
+ }
471
+ ],
472
+ "description": "PHP_CodeSniffer Standards Composer Installer Plugin",
473
+ "homepage": "http://www.dealerdirect.com",
474
+ "keywords": [
475
+ "PHPCodeSniffer",
476
+ "PHP_CodeSniffer",
477
+ "code quality",
478
+ "codesniffer",
479
+ "composer",
480
+ "installer",
481
+ "phpcs",
482
+ "plugin",
483
+ "qa",
484
+ "quality",
485
+ "standard",
486
+ "standards",
487
+ "style guide",
488
+ "stylecheck",
489
+ "tests"
490
+ ],
491
+ "support": {
492
+ "issues": "https://github.com/dealerdirect/phpcodesniffer-composer-installer/issues",
493
+ "source": "https://github.com/dealerdirect/phpcodesniffer-composer-installer"
494
+ },
495
+ "time": "2020-12-07T18:04:37+00:00"
496
+ },
497
+ {
498
+ "name": "dflydev/dot-access-data",
499
+ "version": "v1.1.0",
500
+ "source": {
501
+ "type": "git",
502
+ "url": "https://github.com/dflydev/dflydev-dot-access-data.git",
503
+ "reference": "3fbd874921ab2c041e899d044585a2ab9795df8a"
504
+ },
505
+ "dist": {
506
+ "type": "zip",
507
+ "url": "https://api.github.com/repos/dflydev/dflydev-dot-access-data/zipball/3fbd874921ab2c041e899d044585a2ab9795df8a",
508
+ "reference": "3fbd874921ab2c041e899d044585a2ab9795df8a",
509
+ "shasum": ""
510
+ },
511
+ "require": {
512
+ "php": ">=5.3.2"
513
+ },
514
+ "type": "library",
515
+ "extra": {
516
+ "branch-alias": {
517
+ "dev-master": "1.0-dev"
518
+ }
519
+ },
520
+ "autoload": {
521
+ "psr-0": {
522
+ "Dflydev\\DotAccessData": "src"
523
+ }
524
+ },
525
+ "notification-url": "https://packagist.org/downloads/",
526
+ "license": [
527
+ "MIT"
528
+ ],
529
+ "authors": [
530
+ {
531
+ "name": "Dragonfly Development Inc.",
532
+ "email": "info@dflydev.com",
533
+ "homepage": "http://dflydev.com"
534
+ },
535
+ {
536
+ "name": "Beau Simensen",
537
+ "email": "beau@dflydev.com",
538
+ "homepage": "http://beausimensen.com"
539
+ },
540
+ {
541
+ "name": "Carlos Frutos",
542
+ "email": "carlos@kiwing.it",
543
+ "homepage": "https://github.com/cfrutos"
544
+ }
545
+ ],
546
+ "description": "Given a deep data structure, access data by dot notation.",
547
+ "homepage": "https://github.com/dflydev/dflydev-dot-access-data",
548
+ "keywords": [
549
+ "access",
550
+ "data",
551
+ "dot",
552
+ "notation"
553
+ ],
554
+ "support": {
555
+ "issues": "https://github.com/dflydev/dflydev-dot-access-data/issues",
556
+ "source": "https://github.com/dflydev/dflydev-dot-access-data/tree/master"
557
+ },
558
+ "time": "2017-01-20T21:14:22+00:00"
559
+ },
560
+ {
561
+ "name": "grasmash/expander",
562
+ "version": "1.0.0",
563
+ "source": {
564
+ "type": "git",
565
+ "url": "https://github.com/grasmash/expander.git",
566
+ "reference": "95d6037344a4be1dd5f8e0b0b2571a28c397578f"
567
+ },
568
+ "dist": {
569
+ "type": "zip",
570
+ "url": "https://api.github.com/repos/grasmash/expander/zipball/95d6037344a4be1dd5f8e0b0b2571a28c397578f",
571
+ "reference": "95d6037344a4be1dd5f8e0b0b2571a28c397578f",
572
+ "shasum": ""
573
+ },
574
+ "require": {
575
+ "dflydev/dot-access-data": "^1.1.0",
576
+ "php": ">=5.4"
577
+ },
578
+ "require-dev": {
579
+ "greg-1-anderson/composer-test-scenarios": "^1",
580
+ "phpunit/phpunit": "^4|^5.5.4",
581
+ "satooshi/php-coveralls": "^1.0.2|dev-master",
582
+ "squizlabs/php_codesniffer": "^2.7"
583
+ },
584
+ "type": "library",
585
+ "extra": {
586
+ "branch-alias": {
587
+ "dev-master": "1.x-dev"
588
+ }
589
+ },
590
+ "autoload": {
591
+ "psr-4": {
592
+ "Grasmash\\Expander\\": "src/"
593
+ }
594
+ },
595
+ "notification-url": "https://packagist.org/downloads/",
596
+ "license": [
597
+ "MIT"
598
+ ],
599
+ "authors": [
600
+ {
601
+ "name": "Matthew Grasmick"
602
+ }
603
+ ],
604
+ "description": "Expands internal property references in PHP arrays file.",
605
+ "support": {
606
+ "issues": "https://github.com/grasmash/expander/issues",
607
+ "source": "https://github.com/grasmash/expander/tree/master"
608
+ },
609
+ "time": "2017-12-21T22:14:55+00:00"
610
+ },
611
+ {
612
+ "name": "league/container",
613
+ "version": "2.5.0",
614
+ "source": {
615
+ "type": "git",
616
+ "url": "https://github.com/thephpleague/container.git",
617
+ "reference": "8438dc47a0674e3378bcce893a0a04d79a2c22b3"
618
+ },
619
+ "dist": {
620
+ "type": "zip",
621
+ "url": "https://api.github.com/repos/thephpleague/container/zipball/8438dc47a0674e3378bcce893a0a04d79a2c22b3",
622
+ "reference": "8438dc47a0674e3378bcce893a0a04d79a2c22b3",
623
+ "shasum": ""
624
+ },
625
+ "require": {
626
+ "container-interop/container-interop": "^1.2",
627
+ "php": "^5.4 || ^7.0 || ^8.0"
628
+ },
629
+ "provide": {
630
+ "container-interop/container-interop-implementation": "^1.2",
631
+ "psr/container-implementation": "^1.0"
632
+ },
633
+ "replace": {
634
+ "orno/di": "~2.0"
635
+ },
636
+ "require-dev": {
637
+ "phpunit/phpunit": "^4.8.36",
638
+ "scrutinizer/ocular": "^1.3",
639
+ "squizlabs/php_codesniffer": "^3.5"
640
+ },
641
+ "type": "library",
642
+ "extra": {
643
+ "branch-alias": {
644
+ "dev-2.x": "2.x-dev",
645
+ "dev-1.x": "1.x-dev"
646
+ }
647
+ },
648
+ "autoload": {
649
+ "psr-4": {
650
+ "League\\Container\\": "src"
651
+ }
652
+ },
653
+ "notification-url": "https://packagist.org/downloads/",
654
+ "license": [
655
+ "MIT"
656
+ ],
657
+ "authors": [
658
+ {
659
+ "name": "Phil Bennett",
660
+ "email": "philipobenito@gmail.com",
661
+ "homepage": "http://www.philipobenito.com",
662
+ "role": "Developer"
663
+ }
664
+ ],
665
+ "description": "A fast and intuitive dependency injection container.",
666
+ "homepage": "https://github.com/thephpleague/container",
667
+ "keywords": [
668
+ "container",
669
+ "dependency",
670
+ "di",
671
+ "injection",
672
+ "league",
673
+ "provider",
674
+ "service"
675
+ ],
676
+ "support": {
677
+ "issues": "https://github.com/thephpleague/container/issues",
678
+ "source": "https://github.com/thephpleague/container/tree/2.5.0"
679
+ },
680
+ "funding": [
681
+ {
682
+ "url": "https://github.com/philipobenito",
683
+ "type": "github"
684
+ }
685
+ ],
686
+ "time": "2021-02-22T09:20:06+00:00"
687
+ },
688
+ {
689
+ "name": "nelexa/zip",
690
+ "version": "3.3.3",
691
+ "source": {
692
+ "type": "git",
693
+ "url": "https://github.com/Ne-Lexa/php-zip.git",
694
+ "reference": "501b52f6fc393a599b44ff348a42740e1eaac7c6"
695
+ },
696
+ "dist": {
697
+ "type": "zip",
698
+ "url": "https://api.github.com/repos/Ne-Lexa/php-zip/zipball/501b52f6fc393a599b44ff348a42740e1eaac7c6",
699
+ "reference": "501b52f6fc393a599b44ff348a42740e1eaac7c6",
700
+ "shasum": ""
701
+ },
702
+ "require": {
703
+ "ext-zlib": "*",
704
+ "paragonie/random_compat": "*",
705
+ "php": "^5.5.9 || ^7.0",
706
+ "psr/http-message": "^1.0",
707
+ "symfony/finder": "^3.0|^4.0|^5.0"
708
+ },
709
+ "require-dev": {
710
+ "ext-bz2": "*",
711
+ "ext-fileinfo": "*",
712
+ "ext-openssl": "*",
713
+ "ext-xml": "*",
714
+ "guzzlehttp/psr7": "^1.6",
715
+ "phpunit/phpunit": "^4.8|^5.7",
716
+ "symfony/var-dumper": "^3.0|^4.0|^5.0"
717
+ },
718
+ "suggest": {
719
+ "ext-bz2": "Needed to support BZIP2 compression",
720
+ "ext-fileinfo": "Needed to get mime-type file",
721
+ "ext-mcrypt": "Needed to support encrypt zip entries or use ext-openssl",
722
+ "ext-openssl": "Needed to support encrypt zip entries or use ext-mcrypt"
723
+ },
724
+ "type": "library",
725
+ "autoload": {
726
+ "psr-4": {
727
+ "PhpZip\\": "src/"
728
+ }
729
+ },
730
+ "notification-url": "https://packagist.org/downloads/",
731
+ "license": [
732
+ "MIT"
733
+ ],
734
+ "authors": [
735
+ {
736
+ "name": "Ne-Lexa",
737
+ "email": "alexey@nelexa.ru",
738
+ "role": "Developer"
739
+ }
740
+ ],
741
+ "description": "PhpZip is a php-library for extended work with ZIP-archives. Open, create, update, delete, extract and get info tool. Supports appending to existing ZIP files, WinZip AES encryption, Traditional PKWARE Encryption, ZipAlign tool, BZIP2 compression, external file attributes and ZIP64 extensions. Alternative ZipArchive. It does not require php-zip extension.",
742
+ "homepage": "https://github.com/Ne-Lexa/php-zip",
743
+ "keywords": [
744
+ "archive",
745
+ "extract",
746
+ "unzip",
747
+ "winzip",
748
+ "zip",
749
+ "zipalign",
750
+ "ziparchive"
751
+ ],
752
+ "support": {
753
+ "issues": "https://github.com/Ne-Lexa/php-zip/issues",
754
+ "source": "https://github.com/Ne-Lexa/php-zip/tree/3.3.3"
755
+ },
756
+ "time": "2020-07-11T21:01:42+00:00"
757
+ },
758
+ {
759
+ "name": "paragonie/random_compat",
760
+ "version": "v9.99.100",
761
+ "source": {
762
+ "type": "git",
763
+ "url": "https://github.com/paragonie/random_compat.git",
764
+ "reference": "996434e5492cb4c3edcb9168db6fbb1359ef965a"
765
+ },
766
+ "dist": {
767
+ "type": "zip",
768
+ "url": "https://api.github.com/repos/paragonie/random_compat/zipball/996434e5492cb4c3edcb9168db6fbb1359ef965a",
769
+ "reference": "996434e5492cb4c3edcb9168db6fbb1359ef965a",
770
+ "shasum": ""
771
+ },
772
+ "require": {
773
+ "php": ">= 7"
774
+ },
775
+ "require-dev": {
776
+ "phpunit/phpunit": "4.*|5.*",
777
+ "vimeo/psalm": "^1"
778
+ },
779
+ "suggest": {
780
+ "ext-libsodium": "Provides a modern crypto API that can be used to generate random bytes."
781
+ },
782
+ "type": "library",
783
+ "notification-url": "https://packagist.org/downloads/",
784
+ "license": [
785
+ "MIT"
786
+ ],
787
+ "authors": [
788
+ {
789
+ "name": "Paragon Initiative Enterprises",
790
+ "email": "security@paragonie.com",
791
+ "homepage": "https://paragonie.com"
792
+ }
793
+ ],
794
+ "description": "PHP 5.x polyfill for random_bytes() and random_int() from PHP 7",
795
+ "keywords": [
796
+ "csprng",
797
+ "polyfill",
798
+ "pseudorandom",
799
+ "random"
800
+ ],
801
+ "support": {
802
+ "email": "info@paragonie.com",
803
+ "issues": "https://github.com/paragonie/random_compat/issues",
804
+ "source": "https://github.com/paragonie/random_compat"
805
+ },
806
+ "time": "2020-10-15T08:29:30+00:00"
807
+ },
808
+ {
809
+ "name": "phpcompatibility/php-compatibility",
810
+ "version": "9.3.5",
811
+ "source": {
812
+ "type": "git",
813
+ "url": "https://github.com/PHPCompatibility/PHPCompatibility.git",
814
+ "reference": "9fb324479acf6f39452e0655d2429cc0d3914243"
815
+ },
816
+ "dist": {
817
+ "type": "zip",
818
+ "url": "https://api.github.com/repos/PHPCompatibility/PHPCompatibility/zipball/9fb324479acf6f39452e0655d2429cc0d3914243",
819
+ "reference": "9fb324479acf6f39452e0655d2429cc0d3914243",
820
+ "shasum": ""
821
+ },
822
+ "require": {
823
+ "php": ">=5.3",
824
+ "squizlabs/php_codesniffer": "^2.3 || ^3.0.2"
825
+ },
826
+ "conflict": {
827
+ "squizlabs/php_codesniffer": "2.6.2"
828
+ },
829
+ "require-dev": {
830
+ "phpunit/phpunit": "~4.5 || ^5.0 || ^6.0 || ^7.0"
831
+ },
832
+ "suggest": {
833
+ "dealerdirect/phpcodesniffer-composer-installer": "^0.5 || This Composer plugin will sort out the PHPCS 'installed_paths' automatically.",
834
+ "roave/security-advisories": "dev-master || Helps prevent installing dependencies with known security issues."
835
+ },
836
+ "type": "phpcodesniffer-standard",
837
+ "notification-url": "https://packagist.org/downloads/",
838
+ "license": [
839
+ "LGPL-3.0-or-later"
840
+ ],
841
+ "authors": [
842
+ {
843
+ "name": "Wim Godden",
844
+ "homepage": "https://github.com/wimg",
845
+ "role": "lead"
846
+ },
847
+ {
848
+ "name": "Juliette Reinders Folmer",
849
+ "homepage": "https://github.com/jrfnl",
850
+ "role": "lead"
851
+ },
852
+ {
853
+ "name": "Contributors",
854
+ "homepage": "https://github.com/PHPCompatibility/PHPCompatibility/graphs/contributors"
855
+ }
856
+ ],
857
+ "description": "A set of sniffs for PHP_CodeSniffer that checks for PHP cross-version compatibility.",
858
+ "homepage": "http://techblog.wimgodden.be/tag/codesniffer/",
859
+ "keywords": [
860
+ "compatibility",
861
+ "phpcs",
862
+ "standards"
863
+ ],
864
+ "support": {
865
+ "issues": "https://github.com/PHPCompatibility/PHPCompatibility/issues",
866
+ "source": "https://github.com/PHPCompatibility/PHPCompatibility"
867
+ },
868
+ "time": "2019-12-27T09:44:58+00:00"
869
+ },
870
+ {
871
+ "name": "psr/container",
872
+ "version": "1.1.1",
873
+ "source": {
874
+ "type": "git",
875
+ "url": "https://github.com/php-fig/container.git",
876
+ "reference": "8622567409010282b7aeebe4bb841fe98b58dcaf"
877
+ },
878
+ "dist": {
879
+ "type": "zip",
880
+ "url": "https://api.github.com/repos/php-fig/container/zipball/8622567409010282b7aeebe4bb841fe98b58dcaf",
881
+ "reference": "8622567409010282b7aeebe4bb841fe98b58dcaf",
882
+ "shasum": ""
883
+ },
884
+ "require": {
885
+ "php": ">=7.2.0"
886
+ },
887
+ "type": "library",
888
+ "autoload": {
889
+ "psr-4": {
890
+ "Psr\\Container\\": "src/"
891
+ }
892
+ },
893
+ "notification-url": "https://packagist.org/downloads/",
894
+ "license": [
895
+ "MIT"
896
+ ],
897
+ "authors": [
898
+ {
899
+ "name": "PHP-FIG",
900
+ "homepage": "https://www.php-fig.org/"
901
+ }
902
+ ],
903
+ "description": "Common Container Interface (PHP FIG PSR-11)",
904
+ "homepage": "https://github.com/php-fig/container",
905
+ "keywords": [
906
+ "PSR-11",
907
+ "container",
908
+ "container-interface",
909
+ "container-interop",
910
+ "psr"
911
+ ],
912
+ "support": {
913
+ "issues": "https://github.com/php-fig/container/issues",
914
+ "source": "https://github.com/php-fig/container/tree/1.1.1"
915
+ },
916
+ "time": "2021-03-05T17:36:06+00:00"
917
+ },
918
+ {
919
+ "name": "psr/event-dispatcher",
920
+ "version": "1.0.0",
921
+ "source": {
922
+ "type": "git",
923
+ "url": "https://github.com/php-fig/event-dispatcher.git",
924
+ "reference": "dbefd12671e8a14ec7f180cab83036ed26714bb0"
925
+ },
926
+ "dist": {
927
+ "type": "zip",
928
+ "url": "https://api.github.com/repos/php-fig/event-dispatcher/zipball/dbefd12671e8a14ec7f180cab83036ed26714bb0",
929
+ "reference": "dbefd12671e8a14ec7f180cab83036ed26714bb0",
930
+ "shasum": ""
931
+ },
932
+ "require": {
933
+ "php": ">=7.2.0"
934
+ },
935
+ "type": "library",
936
+ "extra": {
937
+ "branch-alias": {
938
+ "dev-master": "1.0.x-dev"
939
+ }
940
+ },
941
+ "autoload": {
942
+ "psr-4": {
943
+ "Psr\\EventDispatcher\\": "src/"
944
+ }
945
+ },
946
+ "notification-url": "https://packagist.org/downloads/",
947
+ "license": [
948
+ "MIT"
949
+ ],
950
+ "authors": [
951
+ {
952
+ "name": "PHP-FIG",
953
+ "homepage": "http://www.php-fig.org/"
954
+ }
955
+ ],
956
+ "description": "Standard interfaces for event handling.",
957
+ "keywords": [
958
+ "events",
959
+ "psr",
960
+ "psr-14"
961
+ ],
962
+ "support": {
963
+ "issues": "https://github.com/php-fig/event-dispatcher/issues",
964
+ "source": "https://github.com/php-fig/event-dispatcher/tree/1.0.0"
965
+ },
966
+ "time": "2019-01-08T18:20:26+00:00"
967
+ },
968
+ {
969
+ "name": "psr/http-message",
970
+ "version": "1.0.1",
971
+ "source": {
972
+ "type": "git",
973
+ "url": "https://github.com/php-fig/http-message.git",
974
+ "reference": "f6561bf28d520154e4b0ec72be95418abe6d9363"
975
+ },
976
+ "dist": {
977
+ "type": "zip",
978
+ "url": "https://api.github.com/repos/php-fig/http-message/zipball/f6561bf28d520154e4b0ec72be95418abe6d9363",
979
+ "reference": "f6561bf28d520154e4b0ec72be95418abe6d9363",
980
+ "shasum": ""
981
+ },
982
+ "require": {
983
+ "php": ">=5.3.0"
984
+ },
985
+ "type": "library",
986
+ "extra": {
987
+ "branch-alias": {
988
+ "dev-master": "1.0.x-dev"
989
+ }
990
+ },
991
+ "autoload": {
992
+ "psr-4": {
993
+ "Psr\\Http\\Message\\": "src/"
994
+ }
995
+ },
996
+ "notification-url": "https://packagist.org/downloads/",
997
+ "license": [
998
+ "MIT"
999
+ ],
1000
+ "authors": [
1001
+ {
1002
+ "name": "PHP-FIG",
1003
+ "homepage": "http://www.php-fig.org/"
1004
+ }
1005
+ ],
1006
+ "description": "Common interface for HTTP messages",
1007
+ "homepage": "https://github.com/php-fig/http-message",
1008
+ "keywords": [
1009
+ "http",
1010
+ "http-message",
1011
+ "psr",
1012
+ "psr-7",
1013
+ "request",
1014
+ "response"
1015
+ ],
1016
+ "support": {
1017
+ "source": "https://github.com/php-fig/http-message/tree/master"
1018
+ },
1019
+ "time": "2016-08-06T14:39:51+00:00"
1020
+ },
1021
+ {
1022
+ "name": "psr/log",
1023
+ "version": "1.1.4",
1024
+ "source": {
1025
+ "type": "git",
1026
+ "url": "https://github.com/php-fig/log.git",
1027
+ "reference": "d49695b909c3b7628b6289db5479a1c204601f11"
1028
+ },
1029
+ "dist": {
1030
+ "type": "zip",
1031
+ "url": "https://api.github.com/repos/php-fig/log/zipball/d49695b909c3b7628b6289db5479a1c204601f11",
1032
+ "reference": "d49695b909c3b7628b6289db5479a1c204601f11",
1033
+ "shasum": ""
1034
+ },
1035
+ "require": {
1036
+ "php": ">=5.3.0"
1037
+ },
1038
+ "type": "library",
1039
+ "extra": {
1040
+ "branch-alias": {
1041
+ "dev-master": "1.1.x-dev"
1042
+ }
1043
+ },
1044
+ "autoload": {
1045
+ "psr-4": {
1046
+ "Psr\\Log\\": "Psr/Log/"
1047
+ }
1048
+ },
1049
+ "notification-url": "https://packagist.org/downloads/",
1050
+ "license": [
1051
+ "MIT"
1052
+ ],
1053
+ "authors": [
1054
+ {
1055
+ "name": "PHP-FIG",
1056
+ "homepage": "https://www.php-fig.org/"
1057
+ }
1058
+ ],
1059
+ "description": "Common interface for logging libraries",
1060
+ "homepage": "https://github.com/php-fig/log",
1061
+ "keywords": [
1062
+ "log",
1063
+ "psr",
1064
+ "psr-3"
1065
+ ],
1066
+ "support": {
1067
+ "source": "https://github.com/php-fig/log/tree/1.1.4"
1068
+ },
1069
+ "time": "2021-05-03T11:20:27+00:00"
1070
+ },
1071
+ {
1072
+ "name": "publishpress/publishpress-plugin-builder",
1073
+ "version": "v1.3.3",
1074
+ "source": {
1075
+ "type": "git",
1076
+ "url": "https://github.com/publishpress/PublishPress-Plugin-Builder",
1077
+ "reference": "9496b6042d4461b884ea1d7d75a2b6246fb88665"
1078
+ },
1079
+ "require": {
1080
+ "consolidation/robo": "^2.0",
1081
+ "nelexa/zip": "^3.3",
1082
+ "php": "~7.3",
1083
+ "symfony/yaml": "^4"
1084
+ },
1085
+ "require-dev": {
1086
+ "codeception/codeception": "^4.0",
1087
+ "codeception/module-asserts": "^1.0.0",
1088
+ "phpmd/phpmd": "^2.8",
1089
+ "phpmetrics/phpmetrics": "^2.7",
1090
+ "squizlabs/php_codesniffer": "^3.5"
1091
+ },
1092
+ "type": "library",
1093
+ "autoload": {
1094
+ "psr-4": {
1095
+ "PublishPressBuilder\\": "src/"
1096
+ }
1097
+ },
1098
+ "license": [
1099
+ "GPL-2.0-or-later"
1100
+ ],
1101
+ "authors": [
1102
+ {
1103
+ "name": "PublishPress",
1104
+ "email": "help@publishpress.com"
1105
+ }
1106
+ ],
1107
+ "description": "Robo tasks for building WordPress plugins",
1108
+ "time": "2021-07-12T16:44:13+00:00"
1109
+ },
1110
+ {
1111
+ "name": "squizlabs/php_codesniffer",
1112
+ "version": "3.6.0",
1113
+ "source": {
1114
+ "type": "git",
1115
+ "url": "https://github.com/squizlabs/PHP_CodeSniffer.git",
1116
+ "reference": "ffced0d2c8fa8e6cdc4d695a743271fab6c38625"
1117
+ },
1118
+ "dist": {
1119
+ "type": "zip",
1120
+ "url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/ffced0d2c8fa8e6cdc4d695a743271fab6c38625",
1121
+ "reference": "ffced0d2c8fa8e6cdc4d695a743271fab6c38625",
1122
+ "shasum": ""
1123
+ },
1124
+ "require": {
1125
+ "ext-simplexml": "*",
1126
+ "ext-tokenizer": "*",
1127
+ "ext-xmlwriter": "*",
1128
+ "php": ">=5.4.0"
1129
+ },
1130
+ "require-dev": {
1131
+ "phpunit/phpunit": "^4.0 || ^5.0 || ^6.0 || ^7.0"
1132
+ },
1133
+ "bin": [
1134
+ "bin/phpcs",
1135
+ "bin/phpcbf"
1136
+ ],
1137
+ "type": "library",
1138
+ "extra": {
1139
+ "branch-alias": {
1140
+ "dev-master": "3.x-dev"
1141
+ }
1142
+ },
1143
+ "notification-url": "https://packagist.org/downloads/",
1144
+ "license": [
1145
+ "BSD-3-Clause"
1146
+ ],
1147
+ "authors": [
1148
+ {
1149
+ "name": "Greg Sherwood",
1150
+ "role": "lead"
1151
+ }
1152
+ ],
1153
+ "description": "PHP_CodeSniffer tokenizes PHP, JavaScript and CSS files and detects violations of a defined set of coding standards.",
1154
+ "homepage": "https://github.com/squizlabs/PHP_CodeSniffer",
1155
+ "keywords": [
1156
+ "phpcs",
1157
+ "standards"
1158
+ ],
1159
+ "support": {
1160
+ "issues": "https://github.com/squizlabs/PHP_CodeSniffer/issues",
1161
+ "source": "https://github.com/squizlabs/PHP_CodeSniffer",
1162
+ "wiki": "https://github.com/squizlabs/PHP_CodeSniffer/wiki"
1163
+ },
1164
+ "time": "2021-04-09T00:54:41+00:00"
1165
+ },
1166
+ {
1167
+ "name": "symfony/console",
1168
+ "version": "v5.1.11",
1169
+ "source": {
1170
+ "type": "git",
1171
+ "url": "https://github.com/symfony/console.git",
1172
+ "reference": "d9a267b621c5082e0a6c659d73633b6fd28a8a08"
1173
+ },
1174
+ "dist": {
1175
+ "type": "zip",
1176
+ "url": "https://api.github.com/repos/symfony/console/zipball/d9a267b621c5082e0a6c659d73633b6fd28a8a08",
1177
+ "reference": "d9a267b621c5082e0a6c659d73633b6fd28a8a08",
1178
+ "shasum": ""
1179
+ },
1180
+ "require": {
1181
+ "php": ">=7.2.5",
1182
+ "symfony/polyfill-mbstring": "~1.0",
1183
+ "symfony/polyfill-php73": "^1.8",
1184
+ "symfony/polyfill-php80": "^1.15",
1185
+ "symfony/service-contracts": "^1.1|^2",
1186
+ "symfony/string": "^5.1"
1187
+ },
1188
+ "conflict": {
1189
+ "symfony/dependency-injection": "<4.4",
1190
+ "symfony/dotenv": "<5.1",
1191
+ "symfony/event-dispatcher": "<4.4",
1192
+ "symfony/lock": "<4.4",
1193
+ "symfony/process": "<4.4"
1194
+ },
1195
+ "provide": {
1196
+ "psr/log-implementation": "1.0"
1197
+ },
1198
+ "require-dev": {
1199
+ "psr/log": "~1.0",
1200
+ "symfony/config": "^4.4|^5.0",
1201
+ "symfony/dependency-injection": "^4.4|^5.0",
1202
+ "symfony/event-dispatcher": "^4.4|^5.0",
1203
+ "symfony/lock": "^4.4|^5.0",
1204
+ "symfony/process": "^4.4|^5.0",
1205
+ "symfony/var-dumper": "^4.4|^5.0"
1206
+ },
1207
+ "suggest": {
1208
+ "psr/log": "For using the console logger",
1209
+ "symfony/event-dispatcher": "",
1210
+ "symfony/lock": "",
1211
+ "symfony/process": ""
1212
+ },
1213
+ "type": "library",
1214
+ "autoload": {
1215
+ "psr-4": {
1216
+ "Symfony\\Component\\Console\\": ""
1217
+ },
1218
+ "exclude-from-classmap": [
1219
+ "/Tests/"
1220
+ ]
1221
+ },
1222
+ "notification-url": "https://packagist.org/downloads/",
1223
+ "license": [
1224
+ "MIT"
1225
+ ],
1226
+ "authors": [
1227
+ {
1228
+ "name": "Fabien Potencier",
1229
+ "email": "fabien@symfony.com"
1230
+ },
1231
+ {
1232
+ "name": "Symfony Community",
1233
+ "homepage": "https://symfony.com/contributors"
1234
+ }
1235
+ ],
1236
+ "description": "Eases the creation of beautiful and testable command line interfaces",
1237
+ "homepage": "https://symfony.com",
1238
+ "support": {
1239
+ "source": "https://github.com/symfony/console/tree/v5.1.11"
1240
+ },
1241
+ "funding": [
1242
+ {
1243
+ "url": "https://symfony.com/sponsor",
1244
+ "type": "custom"
1245
+ },
1246
+ {
1247
+ "url": "https://github.com/fabpot",
1248
+ "type": "github"
1249
+ },
1250
+ {
1251
+ "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
1252
+ "type": "tidelift"
1253
+ }
1254
+ ],
1255
+ "time": "2021-01-27T10:01:46+00:00"
1256
+ },
1257
+ {
1258
+ "name": "symfony/deprecation-contracts",
1259
+ "version": "v2.4.0",
1260
+ "source": {
1261
+ "type": "git",
1262
+ "url": "https://github.com/symfony/deprecation-contracts.git",
1263
+ "reference": "5f38c8804a9e97d23e0c8d63341088cd8a22d627"
1264
+ },
1265
+ "dist": {
1266
+ "type": "zip",
1267
+ "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/5f38c8804a9e97d23e0c8d63341088cd8a22d627",
1268
+ "reference": "5f38c8804a9e97d23e0c8d63341088cd8a22d627",
1269
+ "shasum": ""
1270
+ },
1271
+ "require": {
1272
+ "php": ">=7.1"
1273
+ },
1274
+ "type": "library",
1275
+ "extra": {
1276
+ "branch-alias": {
1277
+ "dev-main": "2.4-dev"
1278
+ },
1279
+ "thanks": {
1280
+ "name": "symfony/contracts",
1281
+ "url": "https://github.com/symfony/contracts"
1282
+ }
1283
+ },
1284
+ "autoload": {
1285
+ "files": [
1286
+ "function.php"
1287
+ ]
1288
+ },
1289
+ "notification-url": "https://packagist.org/downloads/",
1290
+ "license": [
1291
+ "MIT"
1292
+ ],
1293
+ "authors": [
1294
+ {
1295
+ "name": "Nicolas Grekas",
1296
+ "email": "p@tchwork.com"
1297
+ },
1298
+ {
1299
+ "name": "Symfony Community",
1300
+ "homepage": "https://symfony.com/contributors"
1301
+ }
1302
+ ],
1303
+ "description": "A generic function and convention to trigger deprecation notices",
1304
+ "homepage": "https://symfony.com",
1305
+ "support": {
1306
+ "source": "https://github.com/symfony/deprecation-contracts/tree/v2.4.0"
1307
+ },
1308
+ "funding": [
1309
+ {
1310
+ "url": "https://symfony.com/sponsor",
1311
+ "type": "custom"
1312
+ },
1313
+ {
1314
+ "url": "https://github.com/fabpot",
1315
+ "type": "github"
1316
+ },
1317
+ {
1318
+ "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
1319
+ "type": "tidelift"
1320
+ }
1321
+ ],
1322
+ "time": "2021-03-23T23:28:01+00:00"
1323
+ },
1324
+ {
1325
+ "name": "symfony/event-dispatcher",
1326
+ "version": "v5.3.7",
1327
+ "source": {
1328
+ "type": "git",
1329
+ "url": "https://github.com/symfony/event-dispatcher.git",
1330
+ "reference": "ce7b20d69c66a20939d8952b617506a44d102130"
1331
+ },
1332
+ "dist": {
1333
+ "type": "zip",
1334
+ "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/ce7b20d69c66a20939d8952b617506a44d102130",
1335
+ "reference": "ce7b20d69c66a20939d8952b617506a44d102130",
1336
+ "shasum": ""
1337
+ },
1338
+ "require": {
1339
+ "php": ">=7.2.5",
1340
+ "symfony/deprecation-contracts": "^2.1",
1341
+ "symfony/event-dispatcher-contracts": "^2",
1342
+ "symfony/polyfill-php80": "^1.16"
1343
+ },
1344
+ "conflict": {
1345
+ "symfony/dependency-injection": "<4.4"
1346
+ },
1347
+ "provide": {
1348
+ "psr/event-dispatcher-implementation": "1.0",
1349
+ "symfony/event-dispatcher-implementation": "2.0"
1350
+ },
1351
+ "require-dev": {
1352
+ "psr/log": "^1|^2|^3",
1353
+ "symfony/config": "^4.4|^5.0",
1354
+ "symfony/dependency-injection": "^4.4|^5.0",
1355
+ "symfony/error-handler": "^4.4|^5.0",
1356
+ "symfony/expression-language": "^4.4|^5.0",
1357
+ "symfony/http-foundation": "^4.4|^5.0",
1358
+ "symfony/service-contracts": "^1.1|^2",
1359
+ "symfony/stopwatch": "^4.4|^5.0"
1360
+ },
1361
+ "suggest": {
1362
+ "symfony/dependency-injection": "",
1363
+ "symfony/http-kernel": ""
1364
+ },
1365
+ "type": "library",
1366
+ "autoload": {
1367
+ "psr-4": {
1368
+ "Symfony\\Component\\EventDispatcher\\": ""
1369
+ },
1370
+ "exclude-from-classmap": [
1371
+ "/Tests/"
1372
+ ]
1373
+ },
1374
+ "notification-url": "https://packagist.org/downloads/",
1375
+ "license": [
1376
+ "MIT"
1377
+ ],
1378
+ "authors": [
1379
+ {
1380
+ "name": "Fabien Potencier",
1381
+ "email": "fabien@symfony.com"
1382
+ },
1383
+ {
1384
+ "name": "Symfony Community",
1385
+ "homepage": "https://symfony.com/contributors"
1386
+ }
1387
+ ],
1388
+ "description": "Provides tools that allow your application components to communicate with each other by dispatching events and listening to them",
1389
+ "homepage": "https://symfony.com",
1390
+ "support": {
1391
+ "source": "https://github.com/symfony/event-dispatcher/tree/v5.3.7"
1392
+ },
1393
+ "funding": [
1394
+ {
1395
+ "url": "https://symfony.com/sponsor",
1396
+ "type": "custom"
1397
+ },
1398
+ {
1399
+ "url": "https://github.com/fabpot",
1400
+ "type": "github"
1401
+ },
1402
+ {
1403
+ "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
1404
+ "type": "tidelift"
1405
+ }
1406
+ ],
1407
+ "time": "2021-08-04T21:20:46+00:00"
1408
+ },
1409
+ {
1410
+ "name": "symfony/event-dispatcher-contracts",
1411
+ "version": "v2.4.0",
1412
+ "source": {
1413
+ "type": "git",
1414
+ "url": "https://github.com/symfony/event-dispatcher-contracts.git",
1415
+ "reference": "69fee1ad2332a7cbab3aca13591953da9cdb7a11"
1416
+ },
1417
+ "dist": {
1418
+ "type": "zip",
1419
+ "url": "https://api.github.com/repos/symfony/event-dispatcher-contracts/zipball/69fee1ad2332a7cbab3aca13591953da9cdb7a11",
1420
+ "reference": "69fee1ad2332a7cbab3aca13591953da9cdb7a11",
1421
+ "shasum": ""
1422
+ },
1423
+ "require": {
1424
+ "php": ">=7.2.5",
1425
+ "psr/event-dispatcher": "^1"
1426
+ },
1427
+ "suggest": {
1428
+ "symfony/event-dispatcher-implementation": ""
1429
+ },
1430
+ "type": "library",
1431
+ "extra": {
1432
+ "branch-alias": {
1433
+ "dev-main": "2.4-dev"
1434
+ },
1435
+ "thanks": {
1436
+ "name": "symfony/contracts",
1437
+ "url": "https://github.com/symfony/contracts"
1438
+ }
1439
+ },
1440
+ "autoload": {
1441
+ "psr-4": {
1442
+ "Symfony\\Contracts\\EventDispatcher\\": ""
1443
+ }
1444
+ },
1445
+ "notification-url": "https://packagist.org/downloads/",
1446
+ "license": [
1447
+ "MIT"
1448
+ ],
1449
+ "authors": [
1450
+ {
1451
+ "name": "Nicolas Grekas",
1452
+ "email": "p@tchwork.com"
1453
+ },
1454
+ {
1455
+ "name": "Symfony Community",
1456
+ "homepage": "https://symfony.com/contributors"
1457
+ }
1458
+ ],
1459
+ "description": "Generic abstractions related to dispatching event",
1460
+ "homepage": "https://symfony.com",
1461
+ "keywords": [
1462
+ "abstractions",
1463
+ "contracts",
1464
+ "decoupling",
1465
+ "interfaces",
1466
+ "interoperability",
1467
+ "standards"
1468
+ ],
1469
+ "support": {
1470
+ "source": "https://github.com/symfony/event-dispatcher-contracts/tree/v2.4.0"
1471
+ },
1472
+ "funding": [
1473
+ {
1474
+ "url": "https://symfony.com/sponsor",
1475
+ "type": "custom"
1476
+ },
1477
+ {
1478
+ "url": "https://github.com/fabpot",
1479
+ "type": "github"
1480
+ },
1481
+ {
1482
+ "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
1483
+ "type": "tidelift"
1484
+ }
1485
+ ],
1486
+ "time": "2021-03-23T23:28:01+00:00"
1487
+ },
1488
+ {
1489
+ "name": "symfony/filesystem",
1490
+ "version": "v5.3.4",
1491
+ "source": {
1492
+ "type": "git",
1493
+ "url": "https://github.com/symfony/filesystem.git",
1494
+ "reference": "343f4fe324383ca46792cae728a3b6e2f708fb32"
1495
+ },
1496
+ "dist": {
1497
+ "type": "zip",
1498
+ "url": "https://api.github.com/repos/symfony/filesystem/zipball/343f4fe324383ca46792cae728a3b6e2f708fb32",
1499
+ "reference": "343f4fe324383ca46792cae728a3b6e2f708fb32",
1500
+ "shasum": ""
1501
+ },
1502
+ "require": {
1503
+ "php": ">=7.2.5",
1504
+ "symfony/polyfill-ctype": "~1.8",
1505
+ "symfony/polyfill-php80": "^1.16"
1506
+ },
1507
+ "type": "library",
1508
+ "autoload": {
1509
+ "psr-4": {
1510
+ "Symfony\\Component\\Filesystem\\": ""
1511
+ },
1512
+ "exclude-from-classmap": [
1513
+ "/Tests/"
1514
+ ]
1515
+ },
1516
+ "notification-url": "https://packagist.org/downloads/",
1517
+ "license": [
1518
+ "MIT"
1519
+ ],
1520
+ "authors": [
1521
+ {
1522
+ "name": "Fabien Potencier",
1523
+ "email": "fabien@symfony.com"
1524
+ },
1525
+ {
1526
+ "name": "Symfony Community",
1527
+ "homepage": "https://symfony.com/contributors"
1528
+ }
1529
+ ],
1530
+ "description": "Provides basic utilities for the filesystem",
1531
+ "homepage": "https://symfony.com",
1532
+ "support": {
1533
+ "source": "https://github.com/symfony/filesystem/tree/v5.3.4"
1534
+ },
1535
+ "funding": [
1536
+ {
1537
+ "url": "https://symfony.com/sponsor",
1538
+ "type": "custom"
1539
+ },
1540
+ {
1541
+ "url": "https://github.com/fabpot",
1542
+ "type": "github"
1543
+ },
1544
+ {
1545
+ "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
1546
+ "type": "tidelift"
1547
+ }
1548
+ ],
1549
+ "time": "2021-07-21T12:40:44+00:00"
1550
+ },
1551
+ {
1552
+ "name": "symfony/finder",
1553
+ "version": "v5.3.7",
1554
+ "source": {
1555
+ "type": "git",
1556
+ "url": "https://github.com/symfony/finder.git",
1557
+ "reference": "a10000ada1e600d109a6c7632e9ac42e8bf2fb93"
1558
+ },
1559
+ "dist": {
1560
+ "type": "zip",
1561
+ "url": "https://api.github.com/repos/symfony/finder/zipball/a10000ada1e600d109a6c7632e9ac42e8bf2fb93",
1562
+ "reference": "a10000ada1e600d109a6c7632e9ac42e8bf2fb93",
1563
+ "shasum": ""
1564
+ },
1565
+ "require": {
1566
+ "php": ">=7.2.5",
1567
+ "symfony/polyfill-php80": "^1.16"
1568
+ },
1569
+ "type": "library",
1570
+ "autoload": {
1571
+ "psr-4": {
1572
+ "Symfony\\Component\\Finder\\": ""
1573
+ },
1574
+ "exclude-from-classmap": [
1575
+ "/Tests/"
1576
+ ]
1577
+ },
1578
+ "notification-url": "https://packagist.org/downloads/",
1579
+ "license": [
1580
+ "MIT"
1581
+ ],
1582
+ "authors": [
1583
+ {
1584
+ "name": "Fabien Potencier",
1585
+ "email": "fabien@symfony.com"
1586
+ },
1587
+ {
1588
+ "name": "Symfony Community",
1589
+ "homepage": "https://symfony.com/contributors"
1590
+ }
1591
+ ],
1592
+ "description": "Finds files and directories via an intuitive fluent interface",
1593
+ "homepage": "https://symfony.com",
1594
+ "support": {
1595
+ "source": "https://github.com/symfony/finder/tree/v5.3.7"
1596
+ },
1597
+ "funding": [
1598
+ {
1599
+ "url": "https://symfony.com/sponsor",
1600
+ "type": "custom"
1601
+ },
1602
+ {
1603
+ "url": "https://github.com/fabpot",
1604
+ "type": "github"
1605
+ },
1606
+ {
1607
+ "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
1608
+ "type": "tidelift"
1609
+ }
1610
+ ],
1611
+ "time": "2021-08-04T21:20:46+00:00"
1612
+ },
1613
+ {
1614
+ "name": "symfony/polyfill-ctype",
1615
+ "version": "v1.23.0",
1616
+ "source": {
1617
+ "type": "git",
1618
+ "url": "https://github.com/symfony/polyfill-ctype.git",
1619
+ "reference": "46cd95797e9df938fdd2b03693b5fca5e64b01ce"
1620
+ },
1621
+ "dist": {
1622
+ "type": "zip",
1623
+ "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/46cd95797e9df938fdd2b03693b5fca5e64b01ce",
1624
+ "reference": "46cd95797e9df938fdd2b03693b5fca5e64b01ce",
1625
+ "shasum": ""
1626
+ },
1627
+ "require": {
1628
+ "php": ">=7.1"
1629
+ },
1630
+ "suggest": {
1631
+ "ext-ctype": "For best performance"
1632
+ },
1633
+ "type": "library",
1634
+ "extra": {
1635
+ "branch-alias": {
1636
+ "dev-main": "1.23-dev"
1637
+ },
1638
+ "thanks": {
1639
+ "name": "symfony/polyfill",
1640
+ "url": "https://github.com/symfony/polyfill"
1641
+ }
1642
+ },
1643
+ "autoload": {
1644
+ "psr-4": {
1645
+ "Symfony\\Polyfill\\Ctype\\": ""
1646
+ },
1647
+ "files": [
1648
+ "bootstrap.php"
1649
+ ]
1650
+ },
1651
+ "notification-url": "https://packagist.org/downloads/",
1652
+ "license": [
1653
+ "MIT"
1654
+ ],
1655
+ "authors": [
1656
+ {
1657
+ "name": "Gert de Pagter",
1658
+ "email": "BackEndTea@gmail.com"
1659
+ },
1660
+ {
1661
+ "name": "Symfony Community",
1662
+ "homepage": "https://symfony.com/contributors"
1663
+ }
1664
+ ],
1665
+ "description": "Symfony polyfill for ctype functions",
1666
+ "homepage": "https://symfony.com",
1667
+ "keywords": [
1668
+ "compatibility",
1669
+ "ctype",
1670
+ "polyfill",
1671
+ "portable"
1672
+ ],
1673
+ "support": {
1674
+ "source": "https://github.com/symfony/polyfill-ctype/tree/v1.23.0"
1675
+ },
1676
+ "funding": [
1677
+ {
1678
+ "url": "https://symfony.com/sponsor",
1679
+ "type": "custom"
1680
+ },
1681
+ {
1682
+ "url": "https://github.com/fabpot",
1683
+ "type": "github"
1684
+ },
1685
+ {
1686
+ "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
1687
+ "type": "tidelift"
1688
+ }
1689
+ ],
1690
+ "time": "2021-02-19T12:13:01+00:00"
1691
+ },
1692
+ {
1693
+ "name": "symfony/polyfill-intl-grapheme",
1694
+ "version": "v1.23.1",
1695
+ "source": {
1696
+ "type": "git",
1697
+ "url": "https://github.com/symfony/polyfill-intl-grapheme.git",
1698
+ "reference": "16880ba9c5ebe3642d1995ab866db29270b36535"
1699
+ },
1700
+ "dist": {
1701
+ "type": "zip",
1702
+ "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/16880ba9c5ebe3642d1995ab866db29270b36535",
1703
+ "reference": "16880ba9c5ebe3642d1995ab866db29270b36535",
1704
+ "shasum": ""
1705
+ },
1706
+ "require": {
1707
+ "php": ">=7.1"
1708
+ },
1709
+ "suggest": {
1710
+ "ext-intl": "For best performance"
1711
+ },
1712
+ "type": "library",
1713
+ "extra": {
1714
+ "branch-alias": {
1715
+ "dev-main": "1.23-dev"
1716
+ },
1717
+ "thanks": {
1718
+ "name": "symfony/polyfill",
1719
+ "url": "https://github.com/symfony/polyfill"
1720
+ }
1721
+ },
1722
+ "autoload": {
1723
+ "psr-4": {
1724
+ "Symfony\\Polyfill\\Intl\\Grapheme\\": ""
1725
+ },
1726
+ "files": [
1727
+ "bootstrap.php"
1728
+ ]
1729
+ },
1730
+ "notification-url": "https://packagist.org/downloads/",
1731
+ "license": [
1732
+ "MIT"
1733
+ ],
1734
+ "authors": [
1735
+ {
1736
+ "name": "Nicolas Grekas",
1737
+ "email": "p@tchwork.com"
1738
+ },
1739
+ {
1740
+ "name": "Symfony Community",
1741
+ "homepage": "https://symfony.com/contributors"
1742
+ }
1743
+ ],
1744
+ "description": "Symfony polyfill for intl's grapheme_* functions",
1745
+ "homepage": "https://symfony.com",
1746
+ "keywords": [
1747
+ "compatibility",
1748
+ "grapheme",
1749
+ "intl",
1750
+ "polyfill",
1751
+ "portable",
1752
+ "shim"
1753
+ ],
1754
+ "support": {
1755
+ "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.23.1"
1756
+ },
1757
+ "funding": [
1758
+ {
1759
+ "url": "https://symfony.com/sponsor",
1760
+ "type": "custom"
1761
+ },
1762
+ {
1763
+ "url": "https://github.com/fabpot",
1764
+ "type": "github"
1765
+ },
1766
+ {
1767
+ "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
1768
+ "type": "tidelift"
1769
+ }
1770
+ ],
1771
+ "time": "2021-05-27T12:26:48+00:00"
1772
+ },
1773
+ {
1774
+ "name": "symfony/polyfill-intl-normalizer",
1775
+ "version": "v1.23.0",
1776
+ "source": {
1777
+ "type": "git",
1778
+ "url": "https://github.com/symfony/polyfill-intl-normalizer.git",
1779
+ "reference": "8590a5f561694770bdcd3f9b5c69dde6945028e8"
1780
+ },
1781
+ "dist": {
1782
+ "type": "zip",
1783
+ "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/8590a5f561694770bdcd3f9b5c69dde6945028e8",
1784
+ "reference": "8590a5f561694770bdcd3f9b5c69dde6945028e8",
1785
+ "shasum": ""
1786
+ },
1787
+ "require": {
1788
+ "php": ">=7.1"
1789
+ },
1790
+ "suggest": {
1791
+ "ext-intl": "For best performance"
1792
+ },
1793
+ "type": "library",
1794
+ "extra": {
1795
+ "branch-alias": {
1796
+ "dev-main": "1.23-dev"
1797
+ },
1798
+ "thanks": {
1799
+ "name": "symfony/polyfill",
1800
+ "url": "https://github.com/symfony/polyfill"
1801
+ }
1802
+ },
1803
+ "autoload": {
1804
+ "psr-4": {
1805
+ "Symfony\\Polyfill\\Intl\\Normalizer\\": ""
1806
+ },
1807
+ "files": [
1808
+ "bootstrap.php"
1809
+ ],
1810
+ "classmap": [
1811
+ "Resources/stubs"
1812
+ ]
1813
+ },
1814
+ "notification-url": "https://packagist.org/downloads/",
1815
+ "license": [
1816
+ "MIT"
1817
+ ],
1818
+ "authors": [
1819
+ {
1820
+ "name": "Nicolas Grekas",
1821
+ "email": "p@tchwork.com"
1822
+ },
1823
+ {
1824
+ "name": "Symfony Community",
1825
+ "homepage": "https://symfony.com/contributors"
1826
+ }
1827
+ ],
1828
+ "description": "Symfony polyfill for intl's Normalizer class and related functions",
1829
+ "homepage": "https://symfony.com",
1830
+ "keywords": [
1831
+ "compatibility",
1832
+ "intl",
1833
+ "normalizer",
1834
+ "polyfill",
1835
+ "portable",
1836
+ "shim"
1837
+ ],
1838
+ "support": {
1839
+ "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.23.0"
1840
+ },
1841
+ "funding": [
1842
+ {
1843
+ "url": "https://symfony.com/sponsor",
1844
+ "type": "custom"
1845
+ },
1846
+ {
1847
+ "url": "https://github.com/fabpot",
1848
+ "type": "github"
1849
+ },
1850
+ {
1851
+ "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
1852
+ "type": "tidelift"
1853
+ }
1854
+ ],
1855
+ "time": "2021-02-19T12:13:01+00:00"
1856
+ },
1857
+ {
1858
+ "name": "symfony/polyfill-mbstring",
1859
+ "version": "v1.23.1",
1860
+ "source": {
1861
+ "type": "git",
1862
+ "url": "https://github.com/symfony/polyfill-mbstring.git",
1863
+ "reference": "9174a3d80210dca8daa7f31fec659150bbeabfc6"
1864
+ },
1865
+ "dist": {
1866
+ "type": "zip",
1867
+ "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/9174a3d80210dca8daa7f31fec659150bbeabfc6",
1868
+ "reference": "9174a3d80210dca8daa7f31fec659150bbeabfc6",
1869
+ "shasum": ""
1870
+ },
1871
+ "require": {
1872
+ "php": ">=7.1"
1873
+ },
1874
+ "suggest": {
1875
+ "ext-mbstring": "For best performance"
1876
+ },
1877
+ "type": "library",
1878
+ "extra": {
1879
+ "branch-alias": {
1880
+ "dev-main": "1.23-dev"
1881
+ },
1882
+ "thanks": {
1883
+ "name": "symfony/polyfill",
1884
+ "url": "https://github.com/symfony/polyfill"
1885
+ }
1886
+ },
1887
+ "autoload": {
1888
+ "psr-4": {
1889
+ "Symfony\\Polyfill\\Mbstring\\": ""
1890
+ },
1891
+ "files": [
1892
+ "bootstrap.php"
1893
+ ]
1894
+ },
1895
+ "notification-url": "https://packagist.org/downloads/",
1896
+ "license": [
1897
+ "MIT"
1898
+ ],
1899
+ "authors": [
1900
+ {
1901
+ "name": "Nicolas Grekas",
1902
+ "email": "p@tchwork.com"
1903
+ },
1904
+ {
1905
+ "name": "Symfony Community",
1906
+ "homepage": "https://symfony.com/contributors"
1907
+ }
1908
+ ],
1909
+ "description": "Symfony polyfill for the Mbstring extension",
1910
+ "homepage": "https://symfony.com",
1911
+ "keywords": [
1912
+ "compatibility",
1913
+ "mbstring",
1914
+ "polyfill",
1915
+ "portable",
1916
+ "shim"
1917
+ ],
1918
+ "support": {
1919
+ "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.23.1"
1920
+ },
1921
+ "funding": [
1922
+ {
1923
+ "url": "https://symfony.com/sponsor",
1924
+ "type": "custom"
1925
+ },
1926
+ {
1927
+ "url": "https://github.com/fabpot",
1928
+ "type": "github"
1929
+ },
1930
+ {
1931
+ "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
1932
+ "type": "tidelift"
1933
+ }
1934
+ ],
1935
+ "time": "2021-05-27T12:26:48+00:00"
1936
+ },
1937
+ {
1938
+ "name": "symfony/polyfill-php73",
1939
+ "version": "v1.23.0",
1940
+ "source": {
1941
+ "type": "git",
1942
+ "url": "https://github.com/symfony/polyfill-php73.git",
1943
+ "reference": "fba8933c384d6476ab14fb7b8526e5287ca7e010"
1944
+ },
1945
+ "dist": {
1946
+ "type": "zip",
1947
+ "url": "https://api.github.com/repos/symfony/polyfill-php73/zipball/fba8933c384d6476ab14fb7b8526e5287ca7e010",
1948
+ "reference": "fba8933c384d6476ab14fb7b8526e5287ca7e010",
1949
+ "shasum": ""
1950
+ },
1951
+ "require": {
1952
+ "php": ">=7.1"
1953
+ },
1954
+ "type": "library",
1955
+ "extra": {
1956
+ "branch-alias": {
1957
+ "dev-main": "1.23-dev"
1958
+ },
1959
+ "thanks": {
1960
+ "name": "symfony/polyfill",
1961
+ "url": "https://github.com/symfony/polyfill"
1962
+ }
1963
+ },
1964
+ "autoload": {
1965
+ "psr-4": {
1966
+ "Symfony\\Polyfill\\Php73\\": ""
1967
+ },
1968
+ "files": [
1969
+ "bootstrap.php"
1970
+ ],
1971
+ "classmap": [
1972
+ "Resources/stubs"
1973
+ ]
1974
+ },
1975
+ "notification-url": "https://packagist.org/downloads/",
1976
+ "license": [
1977
+ "MIT"
1978
+ ],
1979
+ "authors": [
1980
+ {
1981
+ "name": "Nicolas Grekas",
1982
+ "email": "p@tchwork.com"
1983
+ },
1984
+ {
1985
+ "name": "Symfony Community",
1986
+ "homepage": "https://symfony.com/contributors"
1987
+ }
1988
+ ],
1989
+ "description": "Symfony polyfill backporting some PHP 7.3+ features to lower PHP versions",
1990
+ "homepage": "https://symfony.com",
1991
+ "keywords": [
1992
+ "compatibility",
1993
+ "polyfill",
1994
+ "portable",
1995
+ "shim"
1996
+ ],
1997
+ "support": {
1998
+ "source": "https://github.com/symfony/polyfill-php73/tree/v1.23.0"
1999
+ },
2000
+ "funding": [
2001
+ {
2002
+ "url": "https://symfony.com/sponsor",
2003
+ "type": "custom"
2004
+ },
2005
+ {
2006
+ "url": "https://github.com/fabpot",
2007
+ "type": "github"
2008
+ },
2009
+ {
2010
+ "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
2011
+ "type": "tidelift"
2012
+ }
2013
+ ],
2014
+ "time": "2021-02-19T12:13:01+00:00"
2015
+ },
2016
+ {
2017
+ "name": "symfony/polyfill-php80",
2018
+ "version": "v1.23.1",
2019
+ "source": {
2020
+ "type": "git",
2021
+ "url": "https://github.com/symfony/polyfill-php80.git",
2022
+ "reference": "1100343ed1a92e3a38f9ae122fc0eb21602547be"
2023
+ },
2024
+ "dist": {
2025
+ "type": "zip",
2026
+ "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/1100343ed1a92e3a38f9ae122fc0eb21602547be",
2027
+ "reference": "1100343ed1a92e3a38f9ae122fc0eb21602547be",
2028
+ "shasum": ""
2029
+ },
2030
+ "require": {
2031
+ "php": ">=7.1"
2032
+ },
2033
+ "type": "library",
2034
+ "extra": {
2035
+ "branch-alias": {
2036
+ "dev-main": "1.23-dev"
2037
+ },
2038
+ "thanks": {
2039
+ "name": "symfony/polyfill",
2040
+ "url": "https://github.com/symfony/polyfill"
2041
+ }
2042
+ },
2043
+ "autoload": {
2044
+ "psr-4": {
2045
+ "Symfony\\Polyfill\\Php80\\": ""
2046
+ },
2047
+ "files": [
2048
+ "bootstrap.php"
2049
+ ],
2050
+ "classmap": [
2051
+ "Resources/stubs"
2052
+ ]
2053
+ },
2054
+ "notification-url": "https://packagist.org/downloads/",
2055
+ "license": [
2056
+ "MIT"
2057
+ ],
2058
+ "authors": [
2059
+ {
2060
+ "name": "Ion Bazan",
2061
+ "email": "ion.bazan@gmail.com"
2062
+ },
2063
+ {
2064
+ "name": "Nicolas Grekas",
2065
+ "email": "p@tchwork.com"
2066
+ },
2067
+ {
2068
+ "name": "Symfony Community",
2069
+ "homepage": "https://symfony.com/contributors"
2070
+ }
2071
+ ],
2072
+ "description": "Symfony polyfill backporting some PHP 8.0+ features to lower PHP versions",
2073
+ "homepage": "https://symfony.com",
2074
+ "keywords": [
2075
+ "compatibility",
2076
+ "polyfill",
2077
+ "portable",
2078
+ "shim"
2079
+ ],
2080
+ "support": {
2081
+ "source": "https://github.com/symfony/polyfill-php80/tree/v1.23.1"
2082
+ },
2083
+ "funding": [
2084
+ {
2085
+ "url": "https://symfony.com/sponsor",
2086
+ "type": "custom"
2087
+ },
2088
+ {
2089
+ "url": "https://github.com/fabpot",
2090
+ "type": "github"
2091
+ },
2092
+ {
2093
+ "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
2094
+ "type": "tidelift"
2095
+ }
2096
+ ],
2097
+ "time": "2021-07-28T13:41:28+00:00"
2098
+ },
2099
+ {
2100
+ "name": "symfony/process",
2101
+ "version": "v5.3.7",
2102
+ "source": {
2103
+ "type": "git",
2104
+ "url": "https://github.com/symfony/process.git",
2105
+ "reference": "38f26c7d6ed535217ea393e05634cb0b244a1967"
2106
+ },
2107
+ "dist": {
2108
+ "type": "zip",
2109
+ "url": "https://api.github.com/repos/symfony/process/zipball/38f26c7d6ed535217ea393e05634cb0b244a1967",
2110
+ "reference": "38f26c7d6ed535217ea393e05634cb0b244a1967",
2111
+ "shasum": ""
2112
+ },
2113
+ "require": {
2114
+ "php": ">=7.2.5",
2115
+ "symfony/polyfill-php80": "^1.16"
2116
+ },
2117
+ "type": "library",
2118
+ "autoload": {
2119
+ "psr-4": {
2120
+ "Symfony\\Component\\Process\\": ""
2121
+ },
2122
+ "exclude-from-classmap": [
2123
+ "/Tests/"
2124
+ ]
2125
+ },
2126
+ "notification-url": "https://packagist.org/downloads/",
2127
+ "license": [
2128
+ "MIT"
2129
+ ],
2130
+ "authors": [
2131
+ {
2132
+ "name": "Fabien Potencier",
2133
+ "email": "fabien@symfony.com"
2134
+ },
2135
+ {
2136
+ "name": "Symfony Community",
2137
+ "homepage": "https://symfony.com/contributors"
2138
+ }
2139
+ ],
2140
+ "description": "Executes commands in sub-processes",
2141
+ "homepage": "https://symfony.com",
2142
+ "support": {
2143
+ "source": "https://github.com/symfony/process/tree/v5.3.7"
2144
+ },
2145
+ "funding": [
2146
+ {
2147
+ "url": "https://symfony.com/sponsor",
2148
+ "type": "custom"
2149
+ },
2150
+ {
2151
+ "url": "https://github.com/fabpot",
2152
+ "type": "github"
2153
+ },
2154
+ {
2155
+ "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
2156
+ "type": "tidelift"
2157
+ }
2158
+ ],
2159
+ "time": "2021-08-04T21:20:46+00:00"
2160
+ },
2161
+ {
2162
+ "name": "symfony/service-contracts",
2163
+ "version": "v2.4.0",
2164
+ "source": {
2165
+ "type": "git",
2166
+ "url": "https://github.com/symfony/service-contracts.git",
2167
+ "reference": "f040a30e04b57fbcc9c6cbcf4dbaa96bd318b9bb"
2168
+ },
2169
+ "dist": {
2170
+ "type": "zip",
2171
+ "url": "https://api.github.com/repos/symfony/service-contracts/zipball/f040a30e04b57fbcc9c6cbcf4dbaa96bd318b9bb",
2172
+ "reference": "f040a30e04b57fbcc9c6cbcf4dbaa96bd318b9bb",
2173
+ "shasum": ""
2174
+ },
2175
+ "require": {
2176
+ "php": ">=7.2.5",
2177
+ "psr/container": "^1.1"
2178
+ },
2179
+ "suggest": {
2180
+ "symfony/service-implementation": ""
2181
+ },
2182
+ "type": "library",
2183
+ "extra": {
2184
+ "branch-alias": {
2185
+ "dev-main": "2.4-dev"
2186
+ },
2187
+ "thanks": {
2188
+ "name": "symfony/contracts",
2189
+ "url": "https://github.com/symfony/contracts"
2190
+ }
2191
+ },
2192
+ "autoload": {
2193
+ "psr-4": {
2194
+ "Symfony\\Contracts\\Service\\": ""
2195
+ }
2196
+ },
2197
+ "notification-url": "https://packagist.org/downloads/",
2198
+ "license": [
2199
+ "MIT"
2200
+ ],
2201
+ "authors": [
2202
+ {
2203
+ "name": "Nicolas Grekas",
2204
+ "email": "p@tchwork.com"
2205
+ },
2206
+ {
2207
+ "name": "Symfony Community",
2208
+ "homepage": "https://symfony.com/contributors"
2209
+ }
2210
+ ],
2211
+ "description": "Generic abstractions related to writing services",
2212
+ "homepage": "https://symfony.com",
2213
+ "keywords": [
2214
+ "abstractions",
2215
+ "contracts",
2216
+ "decoupling",
2217
+ "interfaces",
2218
+ "interoperability",
2219
+ "standards"
2220
+ ],
2221
+ "support": {
2222
+ "source": "https://github.com/symfony/service-contracts/tree/v2.4.0"
2223
+ },
2224
+ "funding": [
2225
+ {
2226
+ "url": "https://symfony.com/sponsor",
2227
+ "type": "custom"
2228
+ },
2229
+ {
2230
+ "url": "https://github.com/fabpot",
2231
+ "type": "github"
2232
+ },
2233
+ {
2234
+ "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
2235
+ "type": "tidelift"
2236
+ }
2237
+ ],
2238
+ "time": "2021-04-01T10:43:52+00:00"
2239
+ },
2240
+ {
2241
+ "name": "symfony/string",
2242
+ "version": "v5.3.7",
2243
+ "source": {
2244
+ "type": "git",
2245
+ "url": "https://github.com/symfony/string.git",
2246
+ "reference": "8d224396e28d30f81969f083a58763b8b9ceb0a5"
2247
+ },
2248
+ "dist": {
2249
+ "type": "zip",
2250
+ "url": "https://api.github.com/repos/symfony/string/zipball/8d224396e28d30f81969f083a58763b8b9ceb0a5",
2251
+ "reference": "8d224396e28d30f81969f083a58763b8b9ceb0a5",
2252
+ "shasum": ""
2253
+ },
2254
+ "require": {
2255
+ "php": ">=7.2.5",
2256
+ "symfony/polyfill-ctype": "~1.8",
2257
+ "symfony/polyfill-intl-grapheme": "~1.0",
2258
+ "symfony/polyfill-intl-normalizer": "~1.0",
2259
+ "symfony/polyfill-mbstring": "~1.0",
2260
+ "symfony/polyfill-php80": "~1.15"
2261
+ },
2262
+ "require-dev": {
2263
+ "symfony/error-handler": "^4.4|^5.0",
2264
+ "symfony/http-client": "^4.4|^5.0",
2265
+ "symfony/translation-contracts": "^1.1|^2",
2266
+ "symfony/var-exporter": "^4.4|^5.0"
2267
+ },
2268
+ "type": "library",
2269
+ "autoload": {
2270
+ "psr-4": {
2271
+ "Symfony\\Component\\String\\": ""
2272
+ },
2273
+ "files": [
2274
+ "Resources/functions.php"
2275
+ ],
2276
+ "exclude-from-classmap": [
2277
+ "/Tests/"
2278
+ ]
2279
+ },
2280
+ "notification-url": "https://packagist.org/downloads/",
2281
+ "license": [
2282
+ "MIT"
2283
+ ],
2284
+ "authors": [
2285
+ {
2286
+ "name": "Nicolas Grekas",
2287
+ "email": "p@tchwork.com"
2288
+ },
2289
+ {
2290
+ "name": "Symfony Community",
2291
+ "homepage": "https://symfony.com/contributors"
2292
+ }
2293
+ ],
2294
+ "description": "Provides an object-oriented API to strings and deals with bytes, UTF-8 code points and grapheme clusters in a unified way",
2295
+ "homepage": "https://symfony.com",
2296
+ "keywords": [
2297
+ "grapheme",
2298
+ "i18n",
2299
+ "string",
2300
+ "unicode",
2301
+ "utf-8",
2302
+ "utf8"
2303
+ ],
2304
+ "support": {
2305
+ "source": "https://github.com/symfony/string/tree/v5.3.7"
2306
+ },
2307
+ "funding": [
2308
+ {
2309
+ "url": "https://symfony.com/sponsor",
2310
+ "type": "custom"
2311
+ },
2312
+ {
2313
+ "url": "https://github.com/fabpot",
2314
+ "type": "github"
2315
+ },
2316
+ {
2317
+ "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
2318
+ "type": "tidelift"
2319
+ }
2320
+ ],
2321
+ "time": "2021-08-26T08:00:08+00:00"
2322
+ },
2323
+ {
2324
+ "name": "symfony/yaml",
2325
+ "version": "v4.4.29",
2326
+ "source": {
2327
+ "type": "git",
2328
+ "url": "https://github.com/symfony/yaml.git",
2329
+ "reference": "3abcc4db06d4e776825eaa3ed8ad924d5bc7432a"
2330
+ },
2331
+ "dist": {
2332
+ "type": "zip",
2333
+ "url": "https://api.github.com/repos/symfony/yaml/zipball/3abcc4db06d4e776825eaa3ed8ad924d5bc7432a",
2334
+ "reference": "3abcc4db06d4e776825eaa3ed8ad924d5bc7432a",
2335
+ "shasum": ""
2336
+ },
2337
+ "require": {
2338
+ "php": ">=7.1.3",
2339
+ "symfony/polyfill-ctype": "~1.8"
2340
+ },
2341
+ "conflict": {
2342
+ "symfony/console": "<3.4"
2343
+ },
2344
+ "require-dev": {
2345
+ "symfony/console": "^3.4|^4.0|^5.0"
2346
+ },
2347
+ "suggest": {
2348
+ "symfony/console": "For validating YAML files using the lint command"
2349
+ },
2350
+ "type": "library",
2351
+ "autoload": {
2352
+ "psr-4": {
2353
+ "Symfony\\Component\\Yaml\\": ""
2354
+ },
2355
+ "exclude-from-classmap": [
2356
+ "/Tests/"
2357
+ ]
2358
+ },
2359
+ "notification-url": "https://packagist.org/downloads/",
2360
+ "license": [
2361
+ "MIT"
2362
+ ],
2363
+ "authors": [
2364
+ {
2365
+ "name": "Fabien Potencier",
2366
+ "email": "fabien@symfony.com"
2367
+ },
2368
+ {
2369
+ "name": "Symfony Community",
2370
+ "homepage": "https://symfony.com/contributors"
2371
+ }
2372
+ ],
2373
+ "description": "Loads and dumps YAML files",
2374
+ "homepage": "https://symfony.com",
2375
+ "support": {
2376
+ "source": "https://github.com/symfony/yaml/tree/v4.4.29"
2377
+ },
2378
+ "funding": [
2379
+ {
2380
+ "url": "https://symfony.com/sponsor",
2381
+ "type": "custom"
2382
+ },
2383
+ {
2384
+ "url": "https://github.com/fabpot",
2385
+ "type": "github"
2386
+ },
2387
+ {
2388
+ "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
2389
+ "type": "tidelift"
2390
+ }
2391
+ ],
2392
+ "time": "2021-07-27T16:19:30+00:00"
2393
+ },
2394
+ {
2395
+ "name": "wp-coding-standards/wpcs",
2396
+ "version": "2.3.0",
2397
+ "source": {
2398
+ "type": "git",
2399
+ "url": "https://github.com/WordPress/WordPress-Coding-Standards.git",
2400
+ "reference": "7da1894633f168fe244afc6de00d141f27517b62"
2401
+ },
2402
+ "dist": {
2403
+ "type": "zip",
2404
+ "url": "https://api.github.com/repos/WordPress/WordPress-Coding-Standards/zipball/7da1894633f168fe244afc6de00d141f27517b62",
2405
+ "reference": "7da1894633f168fe244afc6de00d141f27517b62",
2406
+ "shasum": ""
2407
+ },
2408
+ "require": {
2409
+ "php": ">=5.4",
2410
+ "squizlabs/php_codesniffer": "^3.3.1"
2411
+ },
2412
+ "require-dev": {
2413
+ "dealerdirect/phpcodesniffer-composer-installer": "^0.5 || ^0.6",
2414
+ "phpcompatibility/php-compatibility": "^9.0",
2415
+ "phpcsstandards/phpcsdevtools": "^1.0",
2416
+ "phpunit/phpunit": "^4.0 || ^5.0 || ^6.0 || ^7.0"
2417
+ },
2418
+ "suggest": {
2419
+ "dealerdirect/phpcodesniffer-composer-installer": "^0.6 || This Composer plugin will sort out the PHPCS 'installed_paths' automatically."
2420
+ },
2421
+ "type": "phpcodesniffer-standard",
2422
+ "notification-url": "https://packagist.org/downloads/",
2423
+ "license": [
2424
+ "MIT"
2425
+ ],
2426
+ "authors": [
2427
+ {
2428
+ "name": "Contributors",
2429
+ "homepage": "https://github.com/WordPress/WordPress-Coding-Standards/graphs/contributors"
2430
+ }
2431
+ ],
2432
+ "description": "PHP_CodeSniffer rules (sniffs) to enforce WordPress coding conventions",
2433
+ "keywords": [
2434
+ "phpcs",
2435
+ "standards",
2436
+ "wordpress"
2437
+ ],
2438
+ "support": {
2439
+ "issues": "https://github.com/WordPress/WordPress-Coding-Standards/issues",
2440
+ "source": "https://github.com/WordPress/WordPress-Coding-Standards",
2441
+ "wiki": "https://github.com/WordPress/WordPress-Coding-Standards/wiki"
2442
+ },
2443
+ "time": "2020-05-13T23:57:56+00:00"
2444
+ }
2445
+ ],
2446
+ "aliases": [],
2447
+ "minimum-stability": "stable",
2448
+ "stability-flags": [],
2449
+ "prefer-stable": false,
2450
+ "prefer-lowest": false,
2451
+ "platform": [],
2452
+ "platform-dev": [],
2453
+ "plugin-api-version": "2.0.0"
2454
+ }
languages/post-expirator.pot CHANGED
@@ -2,16 +2,42 @@
2
  # This file is distributed under the same license as the Post Expirator package.
3
  msgid ""
4
  msgstr ""
5
- "Project-Id-Version: Post Expirator 2.4.2\n"
6
  "Report-Msgid-Bugs-To: "
7
  "https://wordpress.org/support/plugin/PublishPress-Future\n"
8
- "POT-Creation-Date: 2021-06-17 17:09:25+00:00\n"
9
  "MIME-Version: 1.0\n"
10
  "Content-Type: text/plain; charset=utf-8\n"
11
  "Content-Transfer-Encoding: 8bit\n"
12
  "Last-Translator: PostExpirator Translate Team\n"
13
  "Language-Team: PostExpirator Translate Team\n"
14
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
15
  #: post-expirator-debug.php:66
16
  msgid "Debugging table is currently empty."
17
  msgstr ""
@@ -36,542 +62,551 @@ msgstr ""
36
  msgid "Post expires at EXPIRATIONTIME on EXPIRATIONDATE"
37
  msgstr ""
38
 
39
- #: post-expirator.php:41
40
  msgid "Settings"
41
  msgstr ""
42
 
43
- #: post-expirator.php:70 post-expirator.php:147 post-expirator.php:218
44
- #: post-expirator.php:269
45
  msgid "Expires"
46
  msgstr ""
47
 
48
- #: post-expirator.php:164
49
- msgid "Never"
50
- msgstr ""
51
-
52
- #: post-expirator.php:216 post-expirator.php:272 post-expirator.php:429
53
  msgid "Enable Post Expiration"
54
  msgstr ""
55
 
56
- #: post-expirator.php:220 post-expirator.php:283 post-expirator.php:436
57
- msgid "Month"
58
- msgstr ""
59
-
60
- #: post-expirator.php:233 post-expirator.php:297 post-expirator.php:437
61
- msgid "Day"
62
  msgstr ""
63
 
64
- #: post-expirator.php:235 post-expirator.php:301 post-expirator.php:435
65
  msgid "Year"
66
  msgstr ""
67
 
68
- #: post-expirator.php:237 post-expirator.php:305 post-expirator.php:474
69
- msgid "Hour"
70
- msgstr ""
71
-
72
- #: post-expirator.php:239 post-expirator.php:309 post-expirator.php:475
73
- msgid "Minute"
74
- msgstr ""
75
-
76
- #: post-expirator.php:274
77
- msgid "No Change"
78
- msgstr ""
79
-
80
- #: post-expirator.php:275
81
- msgid "Change expiry date if enabled on posts"
82
- msgstr ""
83
-
84
- #: post-expirator.php:275
85
- msgid "Change on posts"
86
- msgstr ""
87
-
88
- #: post-expirator.php:276
89
- msgid "Add expiry date if not enabled on posts"
90
- msgstr ""
91
-
92
- #: post-expirator.php:276
93
- msgid "Add to posts"
94
  msgstr ""
95
 
96
- #: post-expirator.php:277
97
- msgid "Change & Add"
98
  msgstr ""
99
 
100
- #: post-expirator.php:278
101
- msgid "Remove from posts"
102
  msgstr ""
103
 
104
- #: post-expirator.php:432
105
- msgid "The published date/time will be used as the expiration value"
106
  msgstr ""
107
 
108
- #: post-expirator.php:496
 
109
  msgid "How to expire"
110
  msgstr ""
111
 
112
- #: post-expirator.php:507
113
  msgid "Expiration Categories"
114
  msgstr ""
115
 
116
- #: post-expirator.php:518
117
  msgid ""
118
  "You must assign a heirarchical taxonomy to this post type to use this "
119
  "feature."
120
  msgstr ""
121
 
122
- #: post-expirator.php:520
123
  msgid ""
124
  "More than 1 heirachical taxonomy detected. You must assign a default "
125
  "taxonomy on the settings screen."
126
  msgstr ""
127
 
128
- #: post-expirator.php:530
129
  msgid "Taxonomy Name"
130
  msgstr ""
131
 
132
- #: post-expirator.php:827 post-expirator.php:838 post-expirator.php:849
133
- #: post-expirator.php:860
134
  msgid ""
135
  "%1$s (%2$s) has expired at %3$s. Post status has been successfully changed "
136
  "to \"%4$s\"."
137
  msgstr ""
138
 
139
- #: post-expirator.php:871
140
  msgid ""
141
  "%1$s (%2$s) has expired at %3$s. Post \"%4$s\" status has been successfully "
142
  "set."
143
  msgstr ""
144
 
145
- #: post-expirator.php:882
146
  msgid ""
147
  "%1$s (%2$s) has expired at %3$s. Post \"%4$s\" status has been successfully "
148
  "removed."
149
  msgstr ""
150
 
151
- #: post-expirator.php:895 post-expirator.php:909
152
  msgid ""
153
  "%1$s (%2$s) has expired at %3$s. Post \"%4$s\" have now been set to "
154
  "\"%5$s\"."
155
  msgstr ""
156
 
157
- #: post-expirator.php:932 post-expirator.php:946
158
  msgid ""
159
  "%1$s (%2$s) has expired at %3$s. The following post \"%4$s\" have now been "
160
  "added: \"%5$s\". The full list of categories on the post are: \"%6$s\"."
161
  msgstr ""
162
 
163
- #: post-expirator.php:974 post-expirator.php:995
164
  msgid ""
165
  "%1$s (%2$s) has expired at %3$s. The following post \"%4$s\" have now been "
166
  "removed: \"%5$s\". The full list of categories on the post are: \"%6$s\"."
167
  msgstr ""
168
 
169
- #: post-expirator.php:1014
170
  msgid "Post Expiration Complete \"%s\""
171
  msgstr ""
172
 
173
- #: post-expirator.php:1050
174
  msgid "[%1$s] %2$s"
175
  msgstr ""
176
 
177
- #: post-expirator.php:1092
178
- msgid "General Settings"
 
 
179
  msgstr ""
180
 
181
- #: post-expirator.php:1093 post-expirator.php:1228
182
- msgid "Defaults"
183
  msgstr ""
184
 
185
- #: post-expirator.php:1094
186
- msgid "Diagnostics"
187
  msgstr ""
188
 
189
- #: post-expirator.php:1095
190
- msgid "View Debug Logs"
191
  msgstr ""
192
 
193
- #: post-expirator.php:1110 post-expirator.php:1133
194
- msgid "Post Expirator Options"
195
  msgstr ""
196
 
197
- #: post-expirator.php:1169 post-expirator.php:1401
198
- msgid "Saved Options!"
199
  msgstr ""
200
 
201
- #: post-expirator.php:1216
202
- msgid ""
203
- "The post expirator plugin sets a custom meta value, and then optionally "
204
- "allows you to select if you want the post changed to a draft status or "
205
- "deleted when it expires."
206
  msgstr ""
207
 
208
- #: post-expirator.php:1219
209
- msgid "Valid [postexpirator] attributes:"
210
  msgstr ""
211
 
212
- #: post-expirator.php:1221
213
- msgid "type - defaults to full - valid options are full,date,time"
214
  msgstr ""
215
 
216
- #: post-expirator.php:1222
217
- msgid ""
218
- "dateformat - format set here will override the value set on the settings "
219
- "page"
220
  msgstr ""
221
 
222
- #: post-expirator.php:1223
223
- msgid ""
224
- "timeformat - format set here will override the value set on the settings "
225
- "page"
226
  msgstr ""
227
 
228
- #: post-expirator.php:1231
229
- msgid "Date Format:"
230
  msgstr ""
231
 
232
- #: post-expirator.php:1235
233
- msgid ""
234
- "The default format to use when displaying the expiration date within a post "
235
- "using the [postexpirator] shortcode or within the footer. For information "
236
- "on valid formatting options, see: <a "
237
- "href=\"http://us2.php.net/manual/en/function.date.php\" "
238
- "target=\"_blank\">PHP Date Function</a>."
239
  msgstr ""
240
 
241
- #: post-expirator.php:1239
242
- msgid "Time Format:"
243
  msgstr ""
244
 
245
- #: post-expirator.php:1243
246
- msgid ""
247
- "The default format to use when displaying the expiration time within a post "
248
- "using the [postexpirator] shortcode or within the footer. For information "
249
- "on valid formatting options, see: <a "
250
- "href=\"http://us2.php.net/manual/en/function.date.php\" "
251
- "target=\"_blank\">PHP Date Function</a>."
252
  msgstr ""
253
 
254
- #: post-expirator.php:1247
255
- msgid "Default Date/Time Duration:"
256
  msgstr ""
257
 
258
- #: post-expirator.php:1250
259
- msgid "None"
260
  msgstr ""
261
 
262
- #: post-expirator.php:1251
263
- msgid "Custom"
264
  msgstr ""
265
 
266
- #: post-expirator.php:1252
267
- msgid "Post/Page Publish Time"
268
  msgstr ""
269
 
270
- #: post-expirator.php:1255
271
- msgid ""
272
- "Set the default expiration date to be used when creating new posts and "
273
- "pages. Defaults to none."
274
  msgstr ""
275
 
276
- #: post-expirator.php:1260
277
- msgid ""
278
- "Set the custom value to use for the default expiration date. For "
279
- "information on formatting, see %1$s. For example, you could enter %2$s+1 "
280
- "month%3$s or %4$s+1 week 2 days 4 hours 2 seconds%5$s or %6$snext "
281
- "Thursday%7$s."
282
  msgstr ""
283
 
284
- #: post-expirator.php:1265
285
- msgid "Category Expiration"
286
  msgstr ""
287
 
288
- #: post-expirator.php:1268
289
- msgid "Default Expiration Category"
 
 
 
290
  msgstr ""
291
 
292
- #: post-expirator.php:1279
293
- msgid "Set's the default expiration category for the post."
294
  msgstr ""
295
 
296
- #: post-expirator.php:1284
297
- msgid "Expiration Email Notification"
298
  msgstr ""
299
 
300
- #: post-expirator.php:1285
301
- msgid ""
302
- "Whenever a post expires, an email can be sent to alert users of the "
303
- "expiration."
304
  msgstr ""
305
 
306
- #: post-expirator.php:1288
307
- msgid "Enable Email Notification?"
 
 
 
 
308
  msgstr ""
309
 
310
- #: post-expirator.php:1290 post-expirator.php:1300 post-expirator.php:1323
311
- #: post-expirator.php:1464
312
  msgid "Enabled"
313
  msgstr ""
314
 
315
- #: post-expirator.php:1292 post-expirator.php:1302 post-expirator.php:1325
316
- #: post-expirator.php:1466
317
  msgid "Disabled"
318
  msgstr ""
319
 
320
- #: post-expirator.php:1294
321
- msgid ""
322
- "This will enable or disable the send of email notification on post "
323
- "expiration."
324
  msgstr ""
325
 
326
- #: post-expirator.php:1298
327
- msgid "Include Blog Administrators?"
328
  msgstr ""
329
 
330
- #: post-expirator.php:1304
 
 
 
 
331
  msgid ""
332
- "This will include all users with the role of \"Administrator\" in the post "
333
- "expiration email."
334
  msgstr ""
335
 
336
- #: post-expirator.php:1308 post-expirator.php:1478
337
- msgid "Who to notify:"
338
  msgstr ""
339
 
340
- #: post-expirator.php:1312
341
- msgid ""
342
- "Enter a comma seperate list of emails that you would like to be notified "
343
- "when the post expires. This will be applied to ALL post types. You can "
344
- "set post type specific emails on the Defaults tab."
345
  msgstr ""
346
 
347
- #: post-expirator.php:1317
348
- msgid "Post Footer Display"
 
349
  msgstr ""
350
 
351
- #: post-expirator.php:1318
352
- msgid ""
353
- "Enabling this below will display the expiration date automatically at the "
354
- "end of any post which is set to expire."
355
  msgstr ""
356
 
357
- #: post-expirator.php:1321
358
- msgid "Show in post footer?"
359
  msgstr ""
360
 
361
- #: post-expirator.php:1327
362
  msgid ""
363
- "This will enable or disable displaying the post expiration date in the post "
364
- "footer."
365
  msgstr ""
366
 
367
- #: post-expirator.php:1331
368
- msgid "Footer Contents:"
 
 
 
 
369
  msgstr ""
370
 
371
- #: post-expirator.php:1335
372
- msgid ""
373
- "Enter the text you would like to appear at the bottom of every post that "
374
- "will expire. The following placeholders will be replaced with the post "
375
- "expiration date in the following format:"
376
  msgstr ""
377
 
378
- #: post-expirator.php:1344
379
- msgid "Footer Style:"
380
  msgstr ""
381
 
382
- #: post-expirator.php:1347
383
- msgid "This post will expire on"
384
  msgstr ""
385
 
386
- #: post-expirator.php:1349
387
- msgid "The inline css which will be used to style the footer text."
388
  msgstr ""
389
 
390
- #: post-expirator.php:1354 post-expirator.php:1492
391
- msgid "Save Changes"
392
  msgstr ""
393
 
394
- #: post-expirator.php:1409
395
- msgid "Default Expiration Values"
396
  msgstr ""
397
 
398
- #: post-expirator.php:1411
399
- msgid ""
400
- "Use the values below to set the default actions/values to be used for each "
401
- "for the corresponding post types. These values can all be overwritten when "
402
- "creating/editing the post/page."
403
  msgstr ""
404
 
405
- #: post-expirator.php:1443
406
- msgid "Active:"
407
  msgstr ""
408
 
409
- #: post-expirator.php:1445
410
- msgid "Active"
411
  msgstr ""
412
 
413
- #: post-expirator.php:1447
414
- msgid "Inactive"
415
  msgstr ""
416
 
417
- #: post-expirator.php:1449
418
- msgid "Select whether the post expirator meta box is active for this post type."
419
  msgstr ""
420
 
421
- #: post-expirator.php:1453
422
- msgid "How to expire:"
423
  msgstr ""
424
 
425
- #: post-expirator.php:1458
426
- msgid "Select the default expire action for the post type."
427
  msgstr ""
428
 
429
- #: post-expirator.php:1462
430
- msgid "Auto-Enable?"
 
 
431
  msgstr ""
432
 
433
- #: post-expirator.php:1468
434
- msgid "Select whether the post expirator is enabled for all new posts."
435
  msgstr ""
436
 
437
- #: post-expirator.php:1472
438
- msgid "Taxonomy (hierarchical):"
439
  msgstr ""
440
 
441
- #: post-expirator.php:1482
 
 
 
 
 
 
 
 
442
  msgid ""
443
- "Enter a comma seperate list of emails that you would like to be notified "
444
- "when the post expires."
 
445
  msgstr ""
446
 
447
- #: post-expirator.php:1514
448
- msgid "Debugging Disabled"
449
  msgstr ""
450
 
451
- #: post-expirator.php:1519
452
- msgid "Debugging Enabled"
453
  msgstr ""
454
 
455
- #: post-expirator.php:1526
456
- msgid "Debugging Table Emptied"
457
  msgstr ""
458
 
459
- #: post-expirator.php:1535
460
- msgid "Advanced Diagnostics"
461
  msgstr ""
462
 
463
- #: post-expirator.php:1538
464
- msgid "Post Expirator Debug Logging:"
465
  msgstr ""
466
 
467
- #: post-expirator.php:1542
468
- msgid "Status: Enabled"
469
  msgstr ""
470
 
471
- #: post-expirator.php:1543
472
- msgid "Disable Debugging"
 
 
 
473
  msgstr ""
474
 
475
- #: post-expirator.php:1545
476
- msgid "Status: Disabled"
477
  msgstr ""
478
 
479
- #: post-expirator.php:1546
480
- msgid "Enable Debugging"
 
 
 
481
  msgstr ""
482
 
483
- #: post-expirator.php:1554
484
- msgid "Purge Debug Log:"
485
  msgstr ""
486
 
487
- #: post-expirator.php:1556
488
- msgid "Purge Debug Log"
 
 
489
  msgstr ""
490
 
491
- #: post-expirator.php:1560
492
- msgid "WP-Cron Status:"
493
  msgstr ""
494
 
495
- #: post-expirator.php:1564
496
- msgid "DISABLED"
497
  msgstr ""
498
 
499
- #: post-expirator.php:1566
500
- msgid "ENABLED - OK"
501
  msgstr ""
502
 
503
- #: post-expirator.php:1572
504
- msgid "Current Cron Schedule:"
 
 
505
  msgstr ""
506
 
507
- #: post-expirator.php:1574
 
 
 
 
508
  msgid ""
509
- "The below table will show all currently scheduled cron events with the next "
510
- "run time."
511
  msgstr ""
512
 
513
- #: post-expirator.php:1577
514
- msgid "Date"
515
  msgstr ""
516
 
517
- #: post-expirator.php:1578
518
- msgid "Event"
 
 
519
  msgstr ""
520
 
521
- #: post-expirator.php:1579
522
- msgid "Arguments / Schedule"
 
 
 
523
  msgstr ""
524
 
525
- #: post-expirator.php:1604
526
- msgid "Single Event"
527
  msgstr ""
528
 
529
- #: post-expirator.php:1632
530
  msgid ""
531
- "Below is a dump of the debugging table, this should be useful for "
532
- "troubleshooting."
533
  msgstr ""
534
 
535
- #: post-expirator.php:2075
536
- msgid "Draft"
537
  msgstr ""
538
 
539
- #: post-expirator.php:2076
540
- msgid "Delete"
 
 
541
  msgstr ""
542
 
543
- #: post-expirator.php:2077
544
- msgid "Trash"
545
  msgstr ""
546
 
547
- #: post-expirator.php:2078
548
- msgid "Private"
 
 
 
549
  msgstr ""
550
 
551
- #: post-expirator.php:2079
552
- msgid "Stick"
553
  msgstr ""
554
 
555
- #: post-expirator.php:2080
556
- msgid "Unstick"
557
  msgstr ""
558
 
559
- #: post-expirator.php:2082
560
- msgid "Category: Replace"
561
  msgstr ""
562
 
563
- #: post-expirator.php:2083
564
- msgid "Category: Add"
565
  msgstr ""
566
 
567
- #: post-expirator.php:2084
568
- msgid "Category: Remove"
 
 
 
 
 
 
 
 
 
 
569
  msgstr ""
570
 
571
- #: post-expirator.php:2137
 
 
 
 
572
  msgid ""
573
- "Select the hierarchical taxonomy to be used for \"category\" based "
574
- "expiration."
 
 
 
 
 
 
 
 
 
 
 
 
575
  msgstr ""
576
 
577
  #. Description of the plugin/theme
2
  # This file is distributed under the same license as the Post Expirator package.
3
  msgid ""
4
  msgstr ""
5
+ "Project-Id-Version: Post Expirator 2.4.4\n"
6
  "Report-Msgid-Bugs-To: "
7
  "https://wordpress.org/support/plugin/PublishPress-Future\n"
8
+ "POT-Creation-Date: 2021-08-30 07:18:09+00:00\n"
9
  "MIME-Version: 1.0\n"
10
  "Content-Type: text/plain; charset=utf-8\n"
11
  "Content-Transfer-Encoding: 8bit\n"
12
  "Last-Translator: PostExpirator Translate Team\n"
13
  "Language-Team: PostExpirator Translate Team\n"
14
 
15
+ #: classes/Display.class.php:41 views/tabs.php:6
16
+ msgid "Post Expirator Options"
17
+ msgstr ""
18
+
19
+ #: classes/Display.class.php:123
20
+ msgid "Debugging Disabled"
21
+ msgstr ""
22
+
23
+ #: classes/Display.class.php:128
24
+ msgid "Debugging Enabled"
25
+ msgstr ""
26
+
27
+ #: classes/Display.class.php:135
28
+ msgid "Debugging Table Emptied"
29
+ msgstr ""
30
+
31
+ #: classes/Display.class.php:150
32
+ msgid ""
33
+ "Below is a dump of the debugging table, this should be useful for "
34
+ "troubleshooting."
35
+ msgstr ""
36
+
37
+ #: classes/Display.class.php:197 classes/Display.class.php:234
38
+ msgid "Saved Options!"
39
+ msgstr ""
40
+
41
  #: post-expirator-debug.php:66
42
  msgid "Debugging table is currently empty."
43
  msgstr ""
62
  msgid "Post expires at EXPIRATIONTIME on EXPIRATIONDATE"
63
  msgstr ""
64
 
65
+ #: post-expirator.php:42
66
  msgid "Settings"
67
  msgstr ""
68
 
69
+ #: post-expirator.php:72 post-expirator.php:149
 
70
  msgid "Expires"
71
  msgstr ""
72
 
73
+ #: post-expirator.php:334 views/bulk-edit.php:20 views/quick-edit.php:7
 
 
 
 
74
  msgid "Enable Post Expiration"
75
  msgstr ""
76
 
77
+ #: post-expirator.php:337
78
+ msgid "The published date/time will be used as the expiration value"
 
 
 
 
79
  msgstr ""
80
 
81
+ #: post-expirator.php:340 views/bulk-edit.php:51 views/quick-edit.php:32
82
  msgid "Year"
83
  msgstr ""
84
 
85
+ #: post-expirator.php:341 views/bulk-edit.php:31 views/quick-edit.php:14
86
+ msgid "Month"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
87
  msgstr ""
88
 
89
+ #: post-expirator.php:342 views/bulk-edit.php:47 views/quick-edit.php:28
90
+ msgid "Day"
91
  msgstr ""
92
 
93
+ #: post-expirator.php:379 views/bulk-edit.php:55 views/quick-edit.php:36
94
+ msgid "Hour"
95
  msgstr ""
96
 
97
+ #: post-expirator.php:380 views/bulk-edit.php:59 views/quick-edit.php:40
98
+ msgid "Minute"
99
  msgstr ""
100
 
101
+ #: post-expirator.php:401 views/bulk-edit.php:67 views/menu-defaults.php:60
102
+ #: views/quick-edit.php:47
103
  msgid "How to expire"
104
  msgstr ""
105
 
106
+ #: post-expirator.php:412 views/bulk-edit.php:79 views/quick-edit.php:57
107
  msgid "Expiration Categories"
108
  msgstr ""
109
 
110
+ #: post-expirator.php:423
111
  msgid ""
112
  "You must assign a heirarchical taxonomy to this post type to use this "
113
  "feature."
114
  msgstr ""
115
 
116
+ #: post-expirator.php:425
117
  msgid ""
118
  "More than 1 heirachical taxonomy detected. You must assign a default "
119
  "taxonomy on the settings screen."
120
  msgstr ""
121
 
122
+ #: post-expirator.php:435
123
  msgid "Taxonomy Name"
124
  msgstr ""
125
 
126
+ #: post-expirator.php:744 post-expirator.php:755 post-expirator.php:766
127
+ #: post-expirator.php:777
128
  msgid ""
129
  "%1$s (%2$s) has expired at %3$s. Post status has been successfully changed "
130
  "to \"%4$s\"."
131
  msgstr ""
132
 
133
+ #: post-expirator.php:788
134
  msgid ""
135
  "%1$s (%2$s) has expired at %3$s. Post \"%4$s\" status has been successfully "
136
  "set."
137
  msgstr ""
138
 
139
+ #: post-expirator.php:799
140
  msgid ""
141
  "%1$s (%2$s) has expired at %3$s. Post \"%4$s\" status has been successfully "
142
  "removed."
143
  msgstr ""
144
 
145
+ #: post-expirator.php:812 post-expirator.php:826
146
  msgid ""
147
  "%1$s (%2$s) has expired at %3$s. Post \"%4$s\" have now been set to "
148
  "\"%5$s\"."
149
  msgstr ""
150
 
151
+ #: post-expirator.php:849 post-expirator.php:863
152
  msgid ""
153
  "%1$s (%2$s) has expired at %3$s. The following post \"%4$s\" have now been "
154
  "added: \"%5$s\". The full list of categories on the post are: \"%6$s\"."
155
  msgstr ""
156
 
157
+ #: post-expirator.php:892 post-expirator.php:913
158
  msgid ""
159
  "%1$s (%2$s) has expired at %3$s. The following post \"%4$s\" have now been "
160
  "removed: \"%5$s\". The full list of categories on the post are: \"%6$s\"."
161
  msgstr ""
162
 
163
+ #: post-expirator.php:932
164
  msgid "Post Expiration Complete \"%s\""
165
  msgstr ""
166
 
167
+ #: post-expirator.php:968
168
  msgid "[%1$s] %2$s"
169
  msgstr ""
170
 
171
+ #: post-expirator.php:1540
172
+ msgid ""
173
+ "Select the hierarchical taxonomy to be used for \"category\" based "
174
+ "expiration."
175
  msgstr ""
176
 
177
+ #: post-expirator.php:1542
178
+ msgid "No taxonomies found"
179
  msgstr ""
180
 
181
+ #: views/bulk-edit.php:18 views/menu-diagnostics.php:45 views/quick-edit.php:12
182
+ msgid "Date"
183
  msgstr ""
184
 
185
+ #: views/bulk-edit.php:22
186
+ msgid "No Change"
187
  msgstr ""
188
 
189
+ #: views/bulk-edit.php:23
190
+ msgid "Change expiry date if enabled on posts"
191
  msgstr ""
192
 
193
+ #: views/bulk-edit.php:23
194
+ msgid "Change on posts"
195
  msgstr ""
196
 
197
+ #: views/bulk-edit.php:24
198
+ msgid "Add expiry date if not enabled on posts"
 
 
 
199
  msgstr ""
200
 
201
+ #: views/bulk-edit.php:24
202
+ msgid "Add to posts"
203
  msgstr ""
204
 
205
+ #: views/bulk-edit.php:25
206
+ msgid "Change & Add"
207
  msgstr ""
208
 
209
+ #: views/bulk-edit.php:26
210
+ msgid "Remove from posts"
 
 
211
  msgstr ""
212
 
213
+ #: views/bulk-edit.php:66 views/quick-edit.php:46
214
+ msgid "Type"
 
 
215
  msgstr ""
216
 
217
+ #: views/expire-column.php:3
218
+ msgid "Never"
219
  msgstr ""
220
 
221
+ #: views/how-to-expire.php:30
222
+ msgid "Draft"
 
 
 
 
 
223
  msgstr ""
224
 
225
+ #: views/how-to-expire.php:31
226
+ msgid "Delete"
227
  msgstr ""
228
 
229
+ #: views/how-to-expire.php:32
230
+ msgid "Trash"
 
 
 
 
 
231
  msgstr ""
232
 
233
+ #: views/how-to-expire.php:33
234
+ msgid "Private"
235
  msgstr ""
236
 
237
+ #: views/how-to-expire.php:34
238
+ msgid "Stick"
239
  msgstr ""
240
 
241
+ #: views/how-to-expire.php:35
242
+ msgid "Unstick"
243
  msgstr ""
244
 
245
+ #: views/how-to-expire.php:37
246
+ msgid "Category: Replace"
247
  msgstr ""
248
 
249
+ #: views/how-to-expire.php:38
250
+ msgid "Category: Add"
 
 
251
  msgstr ""
252
 
253
+ #: views/how-to-expire.php:39
254
+ msgid "Category: Remove"
 
 
 
 
255
  msgstr ""
256
 
257
+ #: views/menu-defaults.php:3
258
+ msgid "Default Expiration Values"
259
  msgstr ""
260
 
261
+ #: views/menu-defaults.php:5
262
+ msgid ""
263
+ "Use the values below to set the default actions/values to be used for each "
264
+ "for the corresponding post types. These values can all be overwritten when "
265
+ "creating/editing the post/page."
266
  msgstr ""
267
 
268
+ #: views/menu-defaults.php:51 views/menu-defaults.php:53
269
+ msgid "Active"
270
  msgstr ""
271
 
272
+ #: views/menu-defaults.php:55
273
+ msgid "Inactive"
274
  msgstr ""
275
 
276
+ #: views/menu-defaults.php:56
277
+ msgid "Select whether the post expirator meta box is active for this post type."
 
 
278
  msgstr ""
279
 
280
+ #: views/menu-defaults.php:63
281
+ msgid "Select the default expire action for the post type."
282
+ msgstr ""
283
+
284
+ #: views/menu-defaults.php:67
285
+ msgid "Auto-Enable?"
286
  msgstr ""
287
 
288
+ #: views/menu-defaults.php:69 views/menu-general.php:113
289
+ #: views/menu-general.php:122 views/menu-general.php:143
290
  msgid "Enabled"
291
  msgstr ""
292
 
293
+ #: views/menu-defaults.php:71 views/menu-general.php:115
294
+ #: views/menu-general.php:124 views/menu-general.php:145
295
  msgid "Disabled"
296
  msgstr ""
297
 
298
+ #: views/menu-defaults.php:72
299
+ msgid "Select whether the post expirator is enabled for all new posts."
 
 
300
  msgstr ""
301
 
302
+ #: views/menu-defaults.php:76
303
+ msgid "Taxonomy (hierarchical)"
304
  msgstr ""
305
 
306
+ #: views/menu-defaults.php:82 views/menu-general.php:129
307
+ msgid "Who to notify"
308
+ msgstr ""
309
+
310
+ #: views/menu-defaults.php:85
311
  msgid ""
312
+ "Enter a comma separate list of emails that you would like to be notified "
313
+ "when the post expires."
314
  msgstr ""
315
 
316
+ #: views/menu-defaults.php:90 views/menu-general.php:77
317
+ msgid "None"
318
  msgstr ""
319
 
320
+ #: views/menu-defaults.php:91
321
+ msgid "Inherit from General Settings"
 
 
 
322
  msgstr ""
323
 
324
+ #: views/menu-defaults.php:92 views/menu-defaults.php:116
325
+ #: views/menu-general.php:78 views/menu-general.php:85
326
+ msgid "Custom"
327
  msgstr ""
328
 
329
+ #: views/menu-defaults.php:93
330
+ msgid "Publish Time"
 
 
331
  msgstr ""
332
 
333
+ #: views/menu-defaults.php:106 views/menu-general.php:74
334
+ msgid "Default Date/Time Duration"
335
  msgstr ""
336
 
337
+ #: views/menu-defaults.php:113
338
  msgid ""
339
+ "Set the default expiration date to be used when creating a new post of this "
340
+ "type."
341
  msgstr ""
342
 
343
+ #: views/menu-defaults.php:118 views/menu-general.php:87
344
+ msgid ""
345
+ "Set the custom value to use for the default expiration date. For "
346
+ "information on formatting, see %1$s. For example, you could enter %2$s+1 "
347
+ "month%3$s or %4$s+1 week 2 days 4 hours 2 seconds%5$s or %6$snext "
348
+ "Thursday%7$s."
349
  msgstr ""
350
 
351
+ #: views/menu-defaults.php:129 views/menu-general.php:189
352
+ msgid "Save Changes"
 
 
 
353
  msgstr ""
354
 
355
+ #: views/menu-diagnostics.php:3
356
+ msgid "Advanced Diagnostics"
357
  msgstr ""
358
 
359
+ #: views/menu-diagnostics.php:6
360
+ msgid "Debug Logging"
361
  msgstr ""
362
 
363
+ #: views/menu-diagnostics.php:11
364
+ msgid "Status: Enabled"
365
  msgstr ""
366
 
367
+ #: views/menu-diagnostics.php:11
368
+ msgid "Disable Debugging"
369
  msgstr ""
370
 
371
+ #: views/menu-diagnostics.php:12 views/tabs.php:13
372
+ msgid "View Debug Logs"
373
  msgstr ""
374
 
375
+ #: views/menu-diagnostics.php:14
376
+ msgid "Status: Disabled"
 
 
 
377
  msgstr ""
378
 
379
+ #: views/menu-diagnostics.php:14
380
+ msgid "Enable Debugging"
381
  msgstr ""
382
 
383
+ #: views/menu-diagnostics.php:20 views/menu-diagnostics.php:22
384
+ msgid "Purge Debug Log"
385
  msgstr ""
386
 
387
+ #: views/menu-diagnostics.php:26
388
+ msgid "WP-Cron Status"
389
  msgstr ""
390
 
391
+ #: views/menu-diagnostics.php:30
392
+ msgid "DISABLED"
393
  msgstr ""
394
 
395
+ #: views/menu-diagnostics.php:32
396
+ msgid "ENABLED - OK"
397
  msgstr ""
398
 
399
+ #: views/menu-diagnostics.php:38
400
+ msgid "Current Cron Schedule"
401
  msgstr ""
402
 
403
+ #: views/menu-diagnostics.php:40
404
+ msgid ""
405
+ "The below table will show all currently scheduled cron events with the next "
406
+ "run time."
407
  msgstr ""
408
 
409
+ #: views/menu-diagnostics.php:46
410
+ msgid "Event"
411
  msgstr ""
412
 
413
+ #: views/menu-diagnostics.php:47
414
+ msgid "Arguments / Schedule"
415
  msgstr ""
416
 
417
+ #: views/menu-diagnostics.php:62
418
+ msgid "No Arguments"
419
+ msgstr ""
420
+
421
+ #: views/menu-diagnostics.php:73
422
+ msgid "Single Event"
423
+ msgstr ""
424
+
425
+ #: views/menu-general.php:44
426
  msgid ""
427
+ "The post expirator plugin sets a custom meta value, and then optionally "
428
+ "allows you to select if you want the post changed to a draft status or "
429
+ "deleted when it expires."
430
  msgstr ""
431
 
432
+ #: views/menu-general.php:46
433
+ msgid "Shortcode"
434
  msgstr ""
435
 
436
+ #: views/menu-general.php:47
437
+ msgid "Valid %s attributes:"
438
  msgstr ""
439
 
440
+ #: views/menu-general.php:49
441
+ msgid "%1$s - valid options are %2$sfull%3$s (default), %4$sdate%5$s, %6$stime%7$s"
442
  msgstr ""
443
 
444
+ #: views/menu-general.php:50 views/menu-general.php:51
445
+ msgid "%s - format set here will override the value set on the settings page"
446
  msgstr ""
447
 
448
+ #: views/menu-general.php:57
449
+ msgid "Defaults"
450
  msgstr ""
451
 
452
+ #: views/menu-general.php:60
453
+ msgid "Date Format"
454
  msgstr ""
455
 
456
+ #: views/menu-general.php:63
457
+ msgid ""
458
+ "The default format to use when displaying the expiration date within a post "
459
+ "using the shortcode or within the footer. For information on valid "
460
+ "formatting options, see: %s."
461
  msgstr ""
462
 
463
+ #: views/menu-general.php:67
464
+ msgid "Time Format"
465
  msgstr ""
466
 
467
+ #: views/menu-general.php:70
468
+ msgid ""
469
+ "The default format to use when displaying the expiration time within a post "
470
+ "using the shortcode or within the footer. For information on valid "
471
+ "formatting options, see: %s."
472
  msgstr ""
473
 
474
+ #: views/menu-general.php:79
475
+ msgid "Post/Page Publish Time"
476
  msgstr ""
477
 
478
+ #: views/menu-general.php:81
479
+ msgid ""
480
+ "Set the default expiration date to be used when creating new posts and "
481
+ "pages. Defaults to none."
482
  msgstr ""
483
 
484
+ #: views/menu-general.php:92
485
+ msgid "Default Expiration Category"
486
  msgstr ""
487
 
488
+ #: views/menu-general.php:102
489
+ msgid "Sets the default expiration category for the post."
490
  msgstr ""
491
 
492
+ #: views/menu-general.php:107
493
+ msgid "Expiration Email Notification"
494
  msgstr ""
495
 
496
+ #: views/menu-general.php:108
497
+ msgid ""
498
+ "Whenever a post expires, an email can be sent to alert users of the "
499
+ "expiration."
500
  msgstr ""
501
 
502
+ #: views/menu-general.php:111
503
+ msgid "Enable Email Notification?"
504
+ msgstr ""
505
+
506
+ #: views/menu-general.php:116
507
  msgid ""
508
+ "This will enable or disable the send of email notification on post "
509
+ "expiration."
510
  msgstr ""
511
 
512
+ #: views/menu-general.php:120
513
+ msgid "Include Blog Administrators?"
514
  msgstr ""
515
 
516
+ #: views/menu-general.php:125
517
+ msgid ""
518
+ "This will include all users with the role of \"Administrator\" in the post "
519
+ "expiration email."
520
  msgstr ""
521
 
522
+ #: views/menu-general.php:132
523
+ msgid ""
524
+ "Enter a comma separate list of emails that you would like to be notified "
525
+ "when the post expires. This will be applied to ALL post types. You can "
526
+ "set post type specific emails on the Defaults tab."
527
  msgstr ""
528
 
529
+ #: views/menu-general.php:137
530
+ msgid "Post Footer Display"
531
  msgstr ""
532
 
533
+ #: views/menu-general.php:138
534
  msgid ""
535
+ "Enabling this below will display the expiration date automatically at the "
536
+ "end of any post which is set to expire."
537
  msgstr ""
538
 
539
+ #: views/menu-general.php:141
540
+ msgid "Show in post footer?"
541
  msgstr ""
542
 
543
+ #: views/menu-general.php:146
544
+ msgid ""
545
+ "This will enable or disable displaying the post expiration date in the post "
546
+ "footer."
547
  msgstr ""
548
 
549
+ #: views/menu-general.php:150
550
+ msgid "Footer Contents"
551
  msgstr ""
552
 
553
+ #: views/menu-general.php:153
554
+ msgid ""
555
+ "Enter the text you would like to appear at the bottom of every post that "
556
+ "will expire. The following placeholders will be replaced with the post "
557
+ "expiration date in the following format:"
558
  msgstr ""
559
 
560
+ #: views/menu-general.php:162
561
+ msgid "Footer Style"
562
  msgstr ""
563
 
564
+ #: views/menu-general.php:165
565
+ msgid "This post will expire on"
566
  msgstr ""
567
 
568
+ #: views/menu-general.php:166
569
+ msgid "The inline css which will be used to style the footer text."
570
  msgstr ""
571
 
572
+ #: views/menu-general.php:171
573
+ msgid "Advanced Options"
574
  msgstr ""
575
 
576
+ #: views/menu-general.php:172
577
+ msgid ""
578
+ "Please do not update anything here unless you know what it entails. For "
579
+ "advanced users only."
580
+ msgstr ""
581
+
582
+ #: views/menu-general.php:178
583
+ msgid "Block Editor Support"
584
+ msgstr ""
585
+
586
+ #: views/menu-general.php:180
587
+ msgid "Show Gutenberg style box"
588
  msgstr ""
589
 
590
+ #: views/menu-general.php:182
591
+ msgid "Show Classic Editor style box"
592
+ msgstr ""
593
+
594
+ #: views/menu-general.php:183
595
  msgid ""
596
+ "Toggle between native support for the Block Editor or the backward "
597
+ "compatible Classic Editor style metabox."
598
+ msgstr ""
599
+
600
+ #: views/tabs.php:9
601
+ msgid "General Settings"
602
+ msgstr ""
603
+
604
+ #: views/tabs.php:10
605
+ msgid "Post Types"
606
+ msgstr ""
607
+
608
+ #: views/tabs.php:11
609
+ msgid "Diagnostics"
610
  msgstr ""
611
 
612
  #. Description of the plugin/theme
legacy-functions.php CHANGED
@@ -1,61 +1,63 @@
1
- <?php
2
- /**
3
- * This file provides access to all legacy functions that are now deprecated.
4
- */
5
-
6
- if ( ! function_exists( '_scheduleExpiratorEvent' ) ) {
7
-
8
- /**
9
- * Schedules the single event.
10
- *
11
- * @since 2.4.3
12
- * @deprecated 2.4.3
13
- */
14
- function _scheduleExpiratorEvent( $id, $ts, $opts ) {
15
- postexpirator_schedule_event( $id, $ts, $opts );
16
- }
17
- }
18
-
19
-
20
- if ( ! function_exists( '_unscheduleExpiratorEvent' ) ) {
21
-
22
- /**
23
- * Unschedules the single event.
24
- *
25
- * @since 2.4.3
26
- * @deprecated 2.4.3
27
- */
28
- function _unscheduleExpiratorEvent( $id ) {
29
- postexpirator_unschedule_event( $id );
30
- }
31
- }
32
-
33
-
34
- if ( ! function_exists( 'postExpiratorExpire' ) ) {
35
-
36
- /**
37
- * Expires the post.
38
- *
39
- * @since 2.4.3
40
- * @deprecated 2.4.3
41
- */
42
- function postExpiratorExpire( $id ) {
43
- postexpirator_expire_post( $id );
44
- }
45
- }
46
-
47
-
48
- if ( ! function_exists( '_postExpiratorExpireType' ) ) {
49
-
50
- /**
51
- * Get the HTML for expire type.
52
- *
53
- * @since 2.5.0
54
- * @deprecated 2.5.0
55
- */
56
- function _postExpiratorExpireType( $opts ) {
57
- _postexpirator_expire_type( $opts );
58
- }
59
- }
60
-
61
-
 
 
1
+ <?php
2
+ /**
3
+ * This file provides access to all legacy functions that are now deprecated.
4
+ */
5
+
6
+ if ( ! function_exists( '_scheduleExpiratorEvent' ) ) {
7
+
8
+ /**
9
+ * Schedules the single event.
10
+ *
11
+ * @since 2.4.3
12
+ * @deprecated 2.4.3
13
+ */
14
+ function _scheduleExpiratorEvent( $id, $ts, $opts ) {
15
+ postexpirator_schedule_event( $id, $ts, $opts );
16
+ }
17
+ }
18
+
19
+
20
+ if ( ! function_exists( '_unscheduleExpiratorEvent' ) ) {
21
+
22
+ /**
23
+ * Unschedules the single event.
24
+ *
25
+ * @since 2.4.3
26
+ * @deprecated 2.4.3
27
+ */
28
+ function _unscheduleExpiratorEvent( $id ) {
29
+ postexpirator_unschedule_event( $id );
30
+ }
31
+ }
32
+
33
+
34
+ if ( ! function_exists( 'postExpiratorExpire' ) ) {
35
+
36
+ /**
37
+ * Expires the post.
38
+ *
39
+ * @since 2.4.3
40
+ * @deprecated 2.4.3
41
+ */
42
+ function postExpiratorExpire( $id ) {
43
+ postexpirator_expire_post( $id );
44
+ }
45
+ }
46
+
47
+
48
+ if ( ! function_exists( '_postExpiratorExpireType' ) ) {
49
+
50
+ /**
51
+ * Get the HTML for expire type.
52
+ *
53
+ * @since 2.5.0
54
+ * @deprecated 2.5.0
55
+ */
56
+ function _postExpiratorExpireType( $opts ) {
57
+ ob_start();
58
+ _postexpirator_expire_type( $opts );
59
+ return ob_get_clean();
60
+ }
61
+ }
62
+
63
+
post-expirator-debug.php CHANGED
@@ -1,88 +1,88 @@
1
- <?php
2
-
3
- // phpcs:disable WordPress.DB.PreparedSQL.NotPrepared, WordPress.DB.PreparedSQL.InterpolatedNotPrepared
4
-
5
- /**
6
- * The class that adds debug entries to the database.
7
- */
8
- class PostExpiratorDebug {
9
-
10
- /**
11
- * Constructor.
12
- */
13
- function __construct() {
14
- global $wpdb;
15
- $this->debug_table = $wpdb->prefix . 'postexpirator_debug';
16
- $this->createDBTable();
17
- }
18
-
19
- /**
20
- * Create Database Table to store debugging information if it does not already exist.
21
- */
22
- private function createDBTable() {
23
- global $wpdb;
24
-
25
- if ( $wpdb->get_var( "SHOW TABLES LIKE '" . $this->debug_table . "'" ) !== $this->debug_table ) {
26
- $sql = 'CREATE TABLE `' . $this->debug_table . '` (
27
- `id` INT(9) NOT NULL AUTO_INCREMENT PRIMARY KEY,
28
- `timestamp` TIMESTAMP NOT NULL,
29
- `blog` INT(9) NOT NULL,
30
- `message` text NOT NULL
31
- );';
32
- require_once( ABSPATH . 'wp-admin/includes/upgrade.php' );
33
- dbDelta( $sql );
34
- }
35
- }
36
-
37
- /**
38
- * Drop Database Table.
39
- */
40
- public function removeDBTable() {
41
- global $wpdb;
42
- $wpdb->query( 'DROP TABLE IF EXISTS ' . $this->debug_table );
43
- }
44
-
45
- /**
46
- * Insert into Database Table.
47
- */
48
- public function save( $data ) {
49
- global $wpdb;
50
- if ( is_multisite() ) {
51
- global $current_blog;
52
- $blog = $current_blog->blog_id;
53
- } else {
54
- $blog = 0;
55
- }
56
- $wpdb->query( $wpdb->prepare( 'INSERT INTO ' . $this->debug_table . ' (`timestamp`,`message`,`blog`) VALUES (FROM_UNIXTIME(%d),%s,%s)', time(), $data['message'], $blog ) );
57
- }
58
-
59
- /**
60
- * Get the HTML of the table's data.
61
- */
62
- public function getTable() {
63
- global $wpdb;
64
- $results = $wpdb->get_results( "SELECT * FROM {$this->debug_table} ORDER BY `id` DESC" );
65
- if ( empty( $results ) ) {
66
- print '<p>' . __( 'Debugging table is currently empty.', 'post-expirator' ) . '</p>';
67
- return;
68
- }
69
- print '<table class="post-expirator-debug">';
70
- print '<tr><th class="post-expirator-timestamp">' . __( 'Timestamp', 'post-expirator' ) . '</th>';
71
- print '<th>' . __( 'Message', 'post-expirator' ) . '</th></tr>';
72
- foreach ( $results as $result ) {
73
- print '<tr><td>' . $result->timestamp . '</td>';
74
- print '<td>' . $result->message . '</td></tr>';
75
- }
76
- print '</table>';
77
- }
78
-
79
- /**
80
- * Truncate Database Table.
81
- */
82
- public function purge() {
83
- global $wpdb;
84
- $wpdb->query( "TRUNCATE TABLE {$this->debug_table}" );
85
- }
86
- }
87
-
88
  // phpcs:enable
1
+ <?php
2
+
3
+ // phpcs:disable WordPress.DB.PreparedSQL.NotPrepared, WordPress.DB.PreparedSQL.InterpolatedNotPrepared
4
+
5
+ /**
6
+ * The class that adds debug entries to the database.
7
+ */
8
+ class PostExpiratorDebug {
9
+
10
+ /**
11
+ * Constructor.
12
+ */
13
+ function __construct() {
14
+ global $wpdb;
15
+ $this->debug_table = $wpdb->prefix . 'postexpirator_debug';
16
+ $this->createDBTable();
17
+ }
18
+
19
+ /**
20
+ * Create Database Table to store debugging information if it does not already exist.
21
+ */
22
+ private function createDBTable() {
23
+ global $wpdb;
24
+
25
+ if ( $wpdb->get_var( "SHOW TABLES LIKE '" . $this->debug_table . "'" ) !== $this->debug_table ) {
26
+ $sql = 'CREATE TABLE `' . $this->debug_table . '` (
27
+ `id` INT(9) NOT NULL AUTO_INCREMENT PRIMARY KEY,
28
+ `timestamp` TIMESTAMP NOT NULL,
29
+ `blog` INT(9) NOT NULL,
30
+ `message` text NOT NULL
31
+ );';
32
+ require_once( ABSPATH . 'wp-admin/includes/upgrade.php' );
33
+ dbDelta( $sql );
34
+ }
35
+ }
36
+
37
+ /**
38
+ * Drop Database Table.
39
+ */
40
+ public function removeDBTable() {
41
+ global $wpdb;
42
+ $wpdb->query( 'DROP TABLE IF EXISTS ' . $this->debug_table );
43
+ }
44
+
45
+ /**
46
+ * Insert into Database Table.
47
+ */
48
+ public function save( $data ) {
49
+ global $wpdb;
50
+ if ( is_multisite() ) {
51
+ global $current_blog;
52
+ $blog = $current_blog->blog_id;
53
+ } else {
54
+ $blog = 0;
55
+ }
56
+ $wpdb->query( $wpdb->prepare( 'INSERT INTO ' . $this->debug_table . ' (`timestamp`,`message`,`blog`) VALUES (FROM_UNIXTIME(%d),%s,%s)', time(), $data['message'], $blog ) );
57
+ }
58
+
59
+ /**
60
+ * Get the HTML of the table's data.
61
+ */
62
+ public function getTable() {
63
+ global $wpdb;
64
+ $results = $wpdb->get_results( "SELECT * FROM {$this->debug_table} ORDER BY `id` DESC" );
65
+ if ( empty( $results ) ) {
66
+ print '<p>' . __( 'Debugging table is currently empty.', 'post-expirator' ) . '</p>';
67
+ return;
68
+ }
69
+ print '<table class="post-expirator-debug">';
70
+ print '<tr><th class="post-expirator-timestamp">' . __( 'Timestamp', 'post-expirator' ) . '</th>';
71
+ print '<th>' . __( 'Message', 'post-expirator' ) . '</th></tr>';
72
+ foreach ( $results as $result ) {
73
+ print '<tr><td>' . $result->timestamp . '</td>';
74
+ print '<td>' . $result->message . '</td></tr>';
75
+ }
76
+ print '</table>';
77
+ }
78
+
79
+ /**
80
+ * Truncate Database Table.
81
+ */
82
+ public function purge() {
83
+ global $wpdb;
84
+ $wpdb->query( "TRUNCATE TABLE {$this->debug_table}" );
85
+ }
86
+ }
87
+
88
  // phpcs:enable
post-expirator.php CHANGED
@@ -1,2253 +1,1674 @@
1
- <?php
2
- /*
3
- Plugin Name: Post Expirator
4
- Plugin URI: http://wordpress.org/extend/plugins/post-expirator/
5
- Description: Allows you to add an expiration date (minute) to posts which you can configure to either delete the post, change it to a draft, or update the post categories at expiration time.
6
- Author: PublishPress
7
- Version: 2.4.4
8
- Author URI: http://publishpress.com
9
- Text Domain: post-expirator
10
- Domain Path: /languages
11
- */
12
-
13
- // Default Values
14
- define( 'POSTEXPIRATOR_VERSION', '2.4.4' );
15
- define( 'POSTEXPIRATOR_DATEFORMAT', __( 'l F jS, Y', 'post-expirator' ) );
16
- define( 'POSTEXPIRATOR_TIMEFORMAT', __( 'g:ia', 'post-expirator' ) );
17
- define( 'POSTEXPIRATOR_FOOTERCONTENTS', __( 'Post expires at EXPIRATIONTIME on EXPIRATIONDATE', 'post-expirator' ) );
18
- define( 'POSTEXPIRATOR_FOOTERSTYLE', 'font-style: italic;' );
19
- define( 'POSTEXPIRATOR_FOOTERDISPLAY', '0' );
20
- define( 'POSTEXPIRATOR_EMAILNOTIFICATION', '0' );
21
- define( 'POSTEXPIRATOR_EMAILNOTIFICATIONADMINS', '0' );
22
- define( 'POSTEXPIRATOR_DEBUGDEFAULT', '0' );
23
- define( 'POSTEXPIRATOR_EXPIREDEFAULT', 'null' );
24
- define( 'POSTEXPIRATOR_SLUG', 'post-expirator' );
25
- define( 'POSTEXPIRATOR_BASEDIR', dirname( __FILE__ ) );
26
- define( 'POSTEXPIRATOR_BASEURL', plugins_url( '/', __FILE__ ) );
27
-
28
- require_once POSTEXPIRATOR_BASEDIR . '/functions.php';
29
-
30
-
31
- /**
32
- * Adds links to the plugin listing screen.
33
- *
34
- * @internal
35
- *
36
- * @access private
37
- */
38
- function postexpirator_plugin_action_links( $links, $file ) {
39
- $this_plugin = basename( plugin_dir_url( __FILE__ ) ) . '/post-expirator.php';
40
- if ( $file === $this_plugin ) {
41
- $links[] = '<a href="options-general.php?page=post-expirator">' . __( 'Settings', 'post-expirator' ) . '</a>';
42
- }
43
- return $links;
44
- }
45
- add_filter( 'plugin_action_links', 'postexpirator_plugin_action_links', 10, 2 );
46
-
47
- /**
48
- * Load translation, if it exists.
49
- *
50
- * @internal
51
- *
52
- * @access private
53
- */
54
- function postexpirator_init() {
55
- $plugin_dir = basename( dirname( __FILE__ ) );
56
- load_plugin_textdomain( 'post-expirator', null, $plugin_dir . '/languages/' );
57
- }
58
- add_action( 'plugins_loaded', 'postexpirator_init' );
59
-
60
- /**
61
- * Adds an 'Expires' column to the post display table.
62
- *
63
- * @internal
64
- *
65
- * @access private
66
- */
67
- function postexpirator_add_column( $columns, $type ) {
68
- $defaults = get_option( 'expirationdateDefaults' . ucfirst( $type ) );
69
- if ( ! isset( $defaults['activeMetaBox'] ) || $defaults['activeMetaBox'] === 'active' ) {
70
- $columns['expirationdate'] = __( 'Expires', 'post-expirator' );
71
- }
72
- return $columns;
73
- }
74
- add_filter( 'manage_posts_columns', 'postexpirator_add_column', 10, 2 );
75
-
76
- /**
77
- * Adds sortable columns.
78
- *
79
- * @internal
80
- *
81
- * @access private
82
- */
83
- function postexpirator_manage_sortable_columns() {
84
- $post_types = get_post_types( array('public' => true) );
85
- foreach ( $post_types as $post_type ) {
86
- add_filter( 'manage_edit-' . $post_type . '_sortable_columns', 'postexpirator_sortable_column' );
87
- }
88
- }
89
- add_action( 'init', 'postexpirator_manage_sortable_columns', 100 );
90
-
91
- /**
92
- * Adds an 'Expires' column to the post display table.
93
- *
94
- * @internal
95
- *
96
- * @access private
97
- */
98
- function postexpirator_sortable_column( $columns ) {
99
- $columns['expirationdate'] = 'expirationdate';
100
- return $columns;
101
- }
102
-
103
- /**
104
- * Modify the sorting of posts.
105
- *
106
- * @internal
107
- *
108
- * @access private
109
- */
110
- function postexpirator_orderby( $query ) {
111
- if ( ! is_admin() ) {
112
- return;
113
- }
114
-
115
- $orderby = $query->get( 'orderby' );
116
-
117
- if ( 'expirationdate' === $orderby ) {
118
- $query->set(
119
- 'meta_query', array(
120
- 'relation' => 'OR',
121
- array(
122
- 'key' => '_expiration-date',
123
- 'compare' => 'EXISTS',
124
- ),
125
- array(
126
- 'key' => '_expiration-date',
127
- 'compare' => 'NOT EXISTS',
128
- 'value' => '',
129
- ),
130
- )
131
- );
132
- $query->set( 'orderby', 'meta_value_num' );
133
- }
134
- }
135
- add_action( 'pre_get_posts', 'postexpirator_orderby' );
136
-
137
- /**
138
- * Adds an 'Expires' column to the page display table.
139
- *
140
- * @internal
141
- *
142
- * @access private
143
- */
144
- function postexpirator_add_column_page( $columns ) {
145
- $defaults = get_option( 'expirationdateDefaultsPage' );
146
- if ( ! isset( $defaults['activeMetaBox'] ) || $defaults['activeMetaBox'] === 'active' ) {
147
- $columns['expirationdate'] = __( 'Expires', 'post-expirator' );
148
- }
149
- return $columns;
150
- }
151
- add_filter( 'manage_pages_columns', 'postexpirator_add_column_page' );
152
-
153
- /**
154
- * Fills the 'Expires' column of the post display table.
155
- *
156
- * @internal
157
- *
158
- * @access private
159
- */
160
- function postexpirator_show_value( $column_name ) {
161
- global $post;
162
- $id = $post->ID;
163
- if ( $column_name === 'expirationdate' ) {
164
- $display = __( 'Never', 'post-expirator' );
165
- $ed = get_post_meta( $id, '_expiration-date', true );
166
- if ( $ed ) {
167
- $display = date_i18n( get_option( 'date_format' ) . ' ' . get_option( 'time_format' ), $ed + ( get_option( 'gmt_offset' ) * HOUR_IN_SECONDS ) );
168
- }
169
- echo $display;
170
-
171
- // Values for Quick Edit
172
- if ( $ed ) {
173
- $date = gmdate( 'Y-m-d H:i:s', $ed );
174
- $year = get_date_from_gmt( $date, 'Y' );
175
- $month = get_date_from_gmt( $date, 'm' );
176
- $day = get_date_from_gmt( $date, 'd' );
177
- $hour = get_date_from_gmt( $date, 'H' );
178
- $minute = get_date_from_gmt( $date, 'i' );
179
- echo '<span id="expirationdate_year-' . $id . '" style="display: none;">' . $year . '</span>';
180
- echo '<span id="expirationdate_month-' . $id . '" style="display: none;">' . $month . '</span>';
181
- echo '<span id="expirationdate_day-' . $id . '" style="display: none;">' . $day . '</span>';
182
- echo '<span id="expirationdate_hour-' . $id . '" style="display: none;">' . $hour . '</span>';
183
- echo '<span id="expirationdate_minute-' . $id . '" style="display: none;">' . $minute . '</span>';
184
- echo '<span id="expirationdate_enabled-' . $id . '" style="display: none;">true</span>';
185
- } else {
186
- echo '<span id="expirationdate_year-' . $id . '" style="display: none;">' . date( 'Y' ) . '</span>';
187
- echo '<span id="expirationdate_month-' . $id . '" style="display: none;">' . date( 'm' ) . '</span>';
188
- echo '<span id="expirationdate_day-' . $id . '" style="display: none;">' . date( 'd' ) . '</span>';
189
- echo '<span id="expirationdate_hour-' . $id . '" style="display: none;">' . date( 'H' ) . '</span>';
190
- echo '<span id="expirationdate_minute-' . $id . '" style="display: none;">' . date( 'i' ) . '</span>';
191
- echo '<span id="expirationdate_enabled-' . $id . '" style="display: none;">false</span>';
192
- }
193
- }
194
- }
195
- add_action( 'manage_posts_custom_column', 'postexpirator_show_value' );
196
- add_action( 'manage_pages_custom_column', 'postexpirator_show_value' );
197
-
198
-
199
- /**
200
- * Quick Edit functionality.
201
- *
202
- * @internal
203
- *
204
- * @access private
205
- */
206
- function postexpirator_quickedit( $column_name, $post_type ) {
207
- if ( $column_name !== 'expirationdate' ) {
208
- return;
209
- }
210
- ?>
211
- <div style="clear:both"></div>
212
- <fieldset class="inline-edit-col-left post-expirator-quickedit">
213
- <div class="inline-edit-col">
214
- <div class="inline-edit-group">
215
- <span class="title"><?php _e( 'Post Expirator', 'post-expirator' ); ?></span>
216
- <p><input name="enable-expirationdate" type="checkbox" /><span class="title"><?php _e( 'Enable Post Expiration', 'post-expirator' ); ?></span></p>
217
- <fieldset class="inline-edit-date">
218
- <legend><span class="title"><?php _e( 'Expires', 'post-expirator' ); ?></span></legend>
219
- <div class="timestamp-wrap">
220
- <label>
221
- <span class="screen-reader-text"><?php _e( 'Month', 'post-expirator' ); ?></span>
222
- <select name="expirationdate_month">
223
- <?php
224
- for ( $x = 1; $x <= 12; $x++ ) {
225
- $now = mktime( 0, 0, 0, $x, 1, date_i18n( 'Y' ) );
226
- $monthNumeric = date_i18n( 'm', $now );
227
- $monthStr = date_i18n( 'M', $now );
228
- ?>
229
- <option value="<?php echo $monthNumeric; ?>" data-text="<?php echo $monthStr; ?>"><?php echo $monthNumeric; ?>-<?php echo $monthStr; ?></option>
230
- <?php } ?>
231
-
232
- </select>
233
- </label>
234
- <label>
235
- <span class="screen-reader-text"><?php _e( 'Day', 'post-expirator' ); ?></span>
236
- <input name="expirationdate_day" value="" size="2" maxlength="2" autocomplete="off" type="text" placeholder="<?php echo date( 'd' ); ?>">
237
- </label>,
238
- <label>
239
- <span class="screen-reader-text"><?php _e( 'Year', 'post-expirator' ); ?></span>
240
- <input name="expirationdate_year" value="" size="4" maxlength="4" autocomplete="off" type="text" placeholder="<?php echo date( 'Y' ); ?>">
241
- </label> @
242
- <label>
243
- <span class="screen-reader-text"><?php _e( 'Hour', 'post-expirator' ); ?></span>
244
- <input name="expirationdate_hour" value="" size="2" maxlength="2" autocomplete="off" type="text" placeholder="00">
245
- </label> :
246
- <label>
247
- <span class="screen-reader-text"><?php _e( 'Minute', 'post-expirator' ); ?></span>
248
- <input name="expirationdate_minute" value="" size="2" maxlength="2" autocomplete="off" type="text" placeholder="00">
249
- </label>
250
- </div>
251
- <input name="expirationdate_quickedit" value="true" type="hidden"/>
252
- </fieldset>
253
- </div>
254
- </div>
255
- </fieldset>
256
- <?php
257
-
258
- }
259
- add_action( 'quick_edit_custom_box', 'postexpirator_quickedit', 10, 2 );
260
-
261
- /**
262
- * Bulk Edit functionality.
263
- *
264
- * @internal
265
- *
266
- * @access private
267
- */
268
- function postexpirator_bulkedit( $column_name, $post_type ) {
269
- if ( $column_name !== 'expirationdate' ) {
270
- return;
271
- }
272
- ?>
273
- <div style="clear:both"></div>
274
- <div class="inline-edit-col post-expirator-quickedit">
275
- <div class="inline-edit-col">
276
- <div class="inline-edit-group">
277
- <legend class="inline-edit-legend"><?php _e( 'Post Expirator', 'post-expirator' ); ?></legend>
278
- <fieldset class="inline-edit-date">
279
- <legend><span class="title"><?php _e( 'Expires', 'post-expirator' ); ?></span></legend>
280
- <div class="timestamp-wrap">
281
- <label>
282
- <span class="screen-reader-text"><?php _e( 'Enable Post Expiration', 'post-expirator' ); ?></span>
283
- <select name="expirationdate_status">
284
- <option value="no-change" data-show-fields="false" selected>--<?php _e( 'No Change', 'post-expirator' ); ?>--</option>
285
- <option value="change-only" data-show-fields="true" title="<?php _e( 'Change expiry date if enabled on posts', 'post-expirator' ); ?>"><?php _e( 'Change on posts', 'post-expirator' ); ?></option>
286
- <option value="add-only" data-show-fields="true" title="<?php _e( 'Add expiry date if not enabled on posts', 'post-expirator' ); ?>"><?php _e( 'Add to posts', 'post-expirator' ); ?></option>
287
- <option value="change-add" data-show-fields="true"><?php _e( 'Change & Add', 'post-expirator' ); ?></option>
288
- <option value="remove-only" data-show-fields="false"><?php _e( 'Remove from posts', 'post-expirator' ); ?></option>
289
- </select>
290
- </label>
291
- <span class="post-expirator-date-fields">
292
- <label>
293
- <span class="screen-reader-text"><?php _e( 'Month', 'post-expirator' ); ?></span>
294
- <select name="expirationdate_month">
295
- <?php
296
- for ( $x = 1; $x <= 12; $x++ ) {
297
- $now = mktime( 0, 0, 0, $x, 1, date_i18n( 'Y' ) );
298
- $monthNumeric = date_i18n( 'm', $now );
299
- $monthStr = date_i18n( 'M', $now );
300
- ?>
301
- <option value="<?php echo $monthNumeric; ?>" data-text="<?php echo $monthStr; ?>"><?php echo $monthNumeric; ?>-<?php echo $monthStr; ?></option>
302
- <?php } ?>
303
-
304
- </select>
305
- </label>
306
- <label>
307
- <span class="screen-reader-text"><?php _e( 'Day', 'post-expirator' ); ?></span>
308
- <input name="expirationdate_day" placeholder="<?php echo date( 'd' ); ?>" value="" size="2" maxlength="2" autocomplete="off" type="text">
309
- </label>,
310
- <label>
311
- <span class="screen-reader-text"><?php _e( 'Year', 'post-expirator' ); ?></span>
312
- <input name="expirationdate_year" placeholder="<?php echo date( 'Y' ); ?>" value="" size="4" maxlength="4" autocomplete="off" type="text">
313
- </label> @
314
- <label>
315
- <span class="screen-reader-text"><?php _e( 'Hour', 'post-expirator' ); ?></span>
316
- <input name="expirationdate_hour" placeholder="00" value="" size="2" maxlength="2" autocomplete="off" type="text">
317
- </label> :
318
- <label>
319
- <span class="screen-reader-text"><?php _e( 'Minute', 'post-expirator' ); ?></span>
320
- <input name="expirationdate_minute" placeholder="00" value="" size="2" maxlength="2" autocomplete="off" type="text">
321
- </label>
322
- </span>
323
- </div>
324
- <input name="expirationdate_quickedit" value="true" type="hidden"/>
325
- </fieldset>
326
- </div>
327
- </div>
328
- </div>
329
- <?php
330
-
331
- }
332
- add_action( 'bulk_edit_custom_box', 'postexpirator_bulkedit', 10, 2 );
333
-
334
- /**
335
- * Adds hooks to get the meta box added to pages and custom post types
336
- *
337
- * @internal
338
- *
339
- * @access private
340
- */
341
- function postexpirator_meta_custom() {
342
- $custom_post_types = get_post_types();
343
- array_push( $custom_post_types, 'page' );
344
- foreach ( $custom_post_types as $t ) {
345
- $defaults = get_option( 'expirationdateDefaults' . ucfirst( $t ) );
346
- if ( ! isset( $defaults['activeMetaBox'] ) || $defaults['activeMetaBox'] === 'active' ) {
347
- add_meta_box( 'expirationdatediv', __( 'Post Expirator', 'post-expirator' ), 'postexpirator_meta_box', $t, 'side', 'core' );
348
- }
349
- }
350
- }
351
- add_action( 'add_meta_boxes', 'postexpirator_meta_custom' );
352
-
353
- /**
354
- * Actually adds the meta box
355
- *
356
- * @internal
357
- *
358
- * @access private
359
- */
360
- function postexpirator_meta_box( $post ) {
361
- // Get default month
362
- $expirationdatets = get_post_meta( $post->ID, '_expiration-date', true );
363
- $firstsave = get_post_meta( $post->ID, '_expiration-date-status', true );
364
-
365
- // nonce
366
- wp_nonce_field( '__postexpirator', '_postexpiratornonce' );
367
-
368
- $default = '';
369
- $expireType = '';
370
- $defaults = get_option( 'expirationdateDefaults' . ucfirst( $post->post_type ) );
371
- if ( empty( $expirationdatets ) ) {
372
- $default = get_option( 'expirationdateDefaultDate', POSTEXPIRATOR_EXPIREDEFAULT );
373
- if ( $default === 'null' ) {
374
- $defaultmonth = date_i18n( 'm' );
375
- $defaultday = date_i18n( 'd' );
376
- $defaulthour = date_i18n( 'H' );
377
- $defaultyear = date_i18n( 'Y' );
378
- $defaultminute = date_i18n( 'i' );
379
-
380
- } elseif ( $default === 'custom' ) {
381
- $custom = get_option( 'expirationdateDefaultDateCustom' );
382
- if ( $custom === false ) {
383
- $ts = time();
384
- } else {
385
- $tz = get_option( 'timezone_string' );
386
- if ( $tz ) {
387
- // @TODO Using date_default_timezone_set() and similar isn't allowed, instead use WP internal timezone support.
388
- // phpcs:ignore WordPress.DateTime.RestrictedFunctions.timezone_change_date_default_timezone_set
389
- date_default_timezone_set( $tz );
390
- }
391
-
392
- // strip the quotes in case the user provides them.
393
- $custom = str_replace( '"', '', html_entity_decode( $custom, ENT_QUOTES ) );
394
-
395
- $ts = time() + ( strtotime( $custom ) - time() );
396
- if ( $tz ) {
397
- // @TODO Using date_default_timezone_set() and similar isn't allowed, instead use WP internal timezone support.
398
- // phpcs:ignore WordPress.DateTime.RestrictedFunctions.timezone_change_date_default_timezone_set
399
- date_default_timezone_set( 'UTC' );
400
- }
401
- }
402
- $defaultmonth = get_date_from_gmt( gmdate( 'Y-m-d H:i:s', $ts ), 'm' );
403
- $defaultday = get_date_from_gmt( gmdate( 'Y-m-d H:i:s', $ts ), 'd' );
404
- $defaultyear = get_date_from_gmt( gmdate( 'Y-m-d H:i:s', $ts ), 'Y' );
405
- $defaulthour = get_date_from_gmt( gmdate( 'Y-m-d H:i:s', $ts ), 'H' );
406
- $defaultminute = get_date_from_gmt( gmdate( 'Y-m-d H:i:s', $ts ), 'i' );
407
- }
408
-
409
- $enabled = '';
410
- $disabled = ' disabled="disabled"';
411
- $categories = get_option( 'expirationdateCategoryDefaults' );
412
-
413
- if ( isset( $defaults['expireType'] ) ) {
414
- $expireType = $defaults['expireType'];
415
- }
416
-
417
- // phpcs:ignore WordPress.PHP.StrictComparisons.LooseComparison
418
- if ( isset( $defaults['autoEnable'] ) && ( $firstsave !== 'saved' ) && ( $defaults['autoEnable'] === true || $defaults['autoEnable'] == 1 ) ) {
419
- $enabled = ' checked="checked"';
420
- $disabled = '';
421
- }
422
- } else {
423
- $defaultmonth = get_date_from_gmt( gmdate( 'Y-m-d H:i:s', $expirationdatets ), 'm' );
424
- $defaultday = get_date_from_gmt( gmdate( 'Y-m-d H:i:s', $expirationdatets ), 'd' );
425
- $defaultyear = get_date_from_gmt( gmdate( 'Y-m-d H:i:s', $expirationdatets ), 'Y' );
426
- $defaulthour = get_date_from_gmt( gmdate( 'Y-m-d H:i:s', $expirationdatets ), 'H' );
427
- $defaultminute = get_date_from_gmt( gmdate( 'Y-m-d H:i:s', $expirationdatets ), 'i' );
428
- $enabled = ' checked="checked"';
429
- $disabled = '';
430
- $opts = get_post_meta( $post->ID, '_expiration-date-options', true );
431
- if ( isset( $opts['expireType'] ) ) {
432
- $expireType = $opts['expireType'];
433
- }
434
- $categories = isset( $opts['category'] ) ? $opts['category'] : false;
435
- }
436
-
437
- $rv = array();
438
- $rv[] = '<p><input type="checkbox" name="enable-expirationdate" id="enable-expirationdate" value="checked"' . $enabled . ' onclick="expirationdate_ajax_add_meta(\'enable-expirationdate\')" />';
439
- $rv[] = '<label for="enable-expirationdate">' . __( 'Enable Post Expiration', 'post-expirator' ) . '</label></p>';
440
-
441
- if ( $default === 'publish' ) {
442
- $rv[] = '<em>' . __( 'The published date/time will be used as the expiration value', 'post-expirator' ) . '</em><br/>';
443
- } else {
444
- $rv[] = '<table><tr>';
445
- $rv[] = '<th style="text-align: left;">' . __( 'Year', 'post-expirator' ) . '</th>';
446
- $rv[] = '<th style="text-align: left;">' . __( 'Month', 'post-expirator' ) . '</th>';
447
- $rv[] = '<th style="text-align: left;">' . __( 'Day', 'post-expirator' ) . '</th>';
448
- $rv[] = '</tr><tr>';
449
- $rv[] = '<td>';
450
- $rv[] = '<select name="expirationdate_year" id="expirationdate_year"' . $disabled . '>';
451
- $currentyear = date( 'Y' );
452
-
453
- if ( $defaultyear < $currentyear ) {
454
- $currentyear = $defaultyear;
455
- }
456
-
457
- for ( $i = $currentyear; $i <= $currentyear + 10; $i++ ) {
458
- // phpcs:ignore WordPress.PHP.StrictComparisons.LooseComparison
459
- if ( $i == $defaultyear ) {
460
- $selected = ' selected="selected"';
461
- } else {
462
- $selected = '';
463
- }
464
- $rv[] = '<option' . $selected . '>' . ( $i ) . '</option>';
465
- }
466
- $rv[] = '</select>';
467
- $rv[] = '</td><td>';
468
- $rv[] = '<select name="expirationdate_month" id="expirationdate_month"' . $disabled . '>';
469
-
470
- for ( $i = 1; $i <= 12; $i++ ) {
471
- if ( $defaultmonth === date_i18n( 'm', mktime( 0, 0, 0, $i, 1, date_i18n( 'Y' ) ) ) ) {
472
- $selected = ' selected="selected"';
473
- } else {
474
- $selected = '';
475
- }
476
- $rv[] = '<option value="' . date_i18n( 'm', mktime( 0, 0, 0, $i, 1, date_i18n( 'Y' ) ) ) . '"' . $selected . '>' . date_i18n( 'F', mktime( 0, 0, 0, $i, 1, date_i18n( 'Y' ) ) ) . '</option>';
477
- }
478
-
479
- $rv[] = '</select>';
480
- $rv[] = '</td><td>';
481
- $rv[] = '<input type="text" id="expirationdate_day" name="expirationdate_day" value="' . $defaultday . '" size="2"' . $disabled . ' />,';
482
- $rv[] = '</td></tr><tr>';
483
- $rv[] = '<th style="text-align: left;"></th>';
484
- $rv[] = '<th style="text-align: left;">' . __( 'Hour', 'post-expirator' ) . '(' . date_i18n( 'T', mktime( 0, 0, 0, $i, 1, date_i18n( 'Y' ) ) ) . ')</th>';
485
- $rv[] = '<th style="text-align: left;">' . __( 'Minute', 'post-expirator' ) . '</th>';
486
- $rv[] = '</tr><tr>';
487
- $rv[] = '<td>@</td><td>';
488
- $rv[] = '<select name="expirationdate_hour" id="expirationdate_hour"' . $disabled . '>';
489
-
490
- for ( $i = 1; $i <= 24; $i++ ) {
491
- if ( $defaulthour === date_i18n( 'H', mktime( $i, 0, 0, date_i18n( 'n' ), date_i18n( 'j' ), date_i18n( 'Y' ) ) ) ) {
492
- $selected = ' selected="selected"';
493
- } else {
494
- $selected = '';
495
- }
496
- $rv[] = '<option value="' . date_i18n( 'H', mktime( $i, 0, 0, date_i18n( 'n' ), date_i18n( 'j' ), date_i18n( 'Y' ) ) ) . '"' . $selected . '>' . date_i18n( 'H', mktime( $i, 0, 0, date_i18n( 'n' ), date_i18n( 'j' ), date_i18n( 'Y' ) ) ) . '</option>';
497
- }
498
-
499
- $rv[] = '</select></td><td>';
500
- $rv[] = '<input type="text" id="expirationdate_minute" name="expirationdate_minute" value="' . $defaultminute . '" size="2"' . $disabled . ' />';
501
- $rv[] = '</td></tr></table>';
502
- }
503
- $rv[] = '<input type="hidden" name="expirationdate_formcheck" value="true" />';
504
- echo implode( "\n", $rv );
505
-
506
- echo '<br/>' . __( 'How to expire', 'post-expirator' ) . ': ';
507
- echo _postexpirator_expire_type( array('type' => $post->post_type, 'name' => 'expirationdate_expiretype', 'selected' => $expireType, 'disabled' => $disabled, 'onchange' => 'expirationdate_toggle_category(this)') );
508
- echo '<br/>';
509
-
510
- if ( $post->post_type !== 'page' ) {
511
- if ( isset( $expireType ) && ( $expireType === 'category' || $expireType === 'category-add' || $expireType === 'category-remove' ) ) {
512
- $catdisplay = 'block';
513
- } else {
514
- $catdisplay = 'none';
515
- }
516
- echo '<div id="expired-category-selection" style="display: ' . $catdisplay . '">';
517
- echo '<br/>' . __( 'Expiration Categories', 'post-expirator' ) . ':<br/>';
518
-
519
- echo '<div class="wp-tab-panel" id="post-expirator-cat-list">';
520
- echo '<ul id="categorychecklist" class="list:category categorychecklist form-no-clear">';
521
- $walker = new Walker_PostExpirator_Category_Checklist();
522
- if ( ! empty( $disabled ) ) {
523
- $walker->setDisabled();
524
- }
525
- $taxonomies = get_object_taxonomies( $post->post_type, 'object' );
526
- $taxonomies = wp_filter_object_list( $taxonomies, array('hierarchical' => true) );
527
- if ( sizeof( $taxonomies ) === 0 ) {
528
- echo '<p>' . __( 'You must assign a heirarchical taxonomy to this post type to use this feature.', 'post-expirator' ) . '</p>';
529
- } elseif ( sizeof( $taxonomies ) > 1 && ! isset( $defaults['taxonomy'] ) ) {
530
- echo '<p>' . __( 'More than 1 heirachical taxonomy detected. You must assign a default taxonomy on the settings screen.', 'post-expirator' ) . '</p>';
531
- } else {
532
- $keys = array_keys( $taxonomies );
533
- $taxonomy = isset( $defaults['taxonomy'] ) ? $defaults['taxonomy'] : $keys[0];
534
- wp_terms_checklist( 0, array( 'taxonomy' => $taxonomy, 'walker' => $walker, 'selected_cats' => $categories, 'checked_ontop' => false ) );
535
- echo '<input type="hidden" name="taxonomy-heirarchical" value="' . $taxonomy . '" />';
536
- }
537
- echo '</ul>';
538
- echo '</div>';
539
- if ( isset( $taxonomy ) ) {
540
- echo '<p class="post-expirator-taxonomy-name">' . __( 'Taxonomy Name', 'post-expirator' ) . ': ' . $taxonomy . '</p>';
541
- }
542
- echo '</div>';
543
- }
544
- echo '<div id="expirationdate_ajax_result"></div>';
545
- }
546
-
547
- /**
548
- * Add's ajax javascript.
549
- *
550
- * @internal
551
- *
552
- * @access private
553
- */
554
- function postexpirator_js_admin_header() {
555
- // Define custom JavaScript function
556
- ?>
557
- <script type="text/javascript">
558
- //<![CDATA[
559
- function expirationdate_ajax_add_meta(expireenable) {
560
- var expire = document.getElementById(expireenable);
561
-
562
- if (expire.checked == true) {
563
- var enable = 'true';
564
- if (document.getElementById('expirationdate_month')) {
565
- document.getElementById('expirationdate_month').disabled = false;
566
- document.getElementById('expirationdate_day').disabled = false;
567
- document.getElementById('expirationdate_year').disabled = false;
568
- document.getElementById('expirationdate_hour').disabled = false;
569
- document.getElementById('expirationdate_minute').disabled = false;
570
- }
571
- document.getElementById('expirationdate_expiretype').disabled = false;
572
- var cats = document.getElementsByName('expirationdate_category[]');
573
- var max = cats.length;
574
- for (var i=0; i<max; i++) {
575
- cats[i].disabled = '';
576
- }
577
- } else {
578
- if (document.getElementById('expirationdate_month')) {
579
- document.getElementById('expirationdate_month').disabled = true;
580
- document.getElementById('expirationdate_day').disabled = true;
581
- document.getElementById('expirationdate_year').disabled = true;
582
- document.getElementById('expirationdate_hour').disabled = true;
583
- document.getElementById('expirationdate_minute').disabled = true;
584
- }
585
- document.getElementById('expirationdate_expiretype').disabled = true;
586
- var cats = document.getElementsByName('expirationdate_category[]');
587
- var max = cats.length;
588
- for (var i=0; i<max; i++) {
589
- cats[i].disabled = 'disable';
590
- }
591
- var enable = 'false';
592
- }
593
- return true;
594
- }
595
- function expirationdate_toggle_category(id) {
596
- if (id.options[id.selectedIndex].value == 'category') {
597
- jQuery('#expired-category-selection').show();
598
- } else if (id.options[id.selectedIndex].value == 'category-add') {
599
- jQuery('#expired-category-selection').show(); //TEMP
600
- } else if (id.options[id.selectedIndex].value == 'category-remove') {
601
- jQuery('#expired-category-selection').show(); //TEMP
602
- } else {
603
- jQuery('#expired-category-selection').hide();
604
- }
605
- }
606
- function expirationdate_toggle_defaultdate(id) {
607
- if (id.options[id.selectedIndex].value == 'custom') {
608
- jQuery('#expired-custom-container').show();
609
- } else {
610
- jQuery('#expired-custom-container').hide();
611
- }
612
-
613
- }
614
- //]]>
615
- </script>
616
- <?php
617
- }
618
- add_action( 'admin_head', 'postexpirator_js_admin_header' );
619
-
620
- /**
621
- * Get correct URL (HTTP or HTTPS)
622
- *
623
- * @internal
624
- *
625
- * @access private
626
- */
627
- function expirationdate_get_blog_url() {
628
- if ( is_multisite() ) {
629
- echo network_home_url( '/' );
630
- } else {
631
- echo home_url( '/' );
632
- }
633
- }
634
-
635
- /**
636
- * Called when post is saved - stores expiration-date meta value
637
- *
638
- * @internal
639
- *
640
- * @access private
641
- */
642
- function postexpirator_update_post_meta( $id ) {
643
- // don't run the echo if this is an auto save
644
- if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) {
645
- return;
646
- }
647
-
648
- // don't run the echo if the function is called for saving revision.
649
- $posttype = get_post_type( $id );
650
- if ( $posttype === 'revision' ) {
651
- return;
652
- }
653
-
654
- if ( ! isset( $_POST['expirationdate_quickedit'] ) ) {
655
- if ( ! isset( $_POST['expirationdate_formcheck'] ) ) {
656
- return;
657
- }
658
- }
659
-
660
- if ( isset( $_POST['enable-expirationdate'] ) ) {
661
- $default = get_option( 'expirationdateDefaultDate', POSTEXPIRATOR_EXPIREDEFAULT );
662
- if ( $default === 'publish' ) {
663
- $month = intval( $_POST['mm'] );
664
- $day = intval( $_POST['jj'] );
665
- $year = intval( $_POST['aa'] );
666
- $hour = intval( $_POST['hh'] );
667
- $minute = intval( $_POST['mn'] );
668
- } else {
669
- $month = intval( $_POST['expirationdate_month'] );
670
- $day = intval( $_POST['expirationdate_day'] );
671
- $year = intval( $_POST['expirationdate_year'] );
672
- $hour = intval( $_POST['expirationdate_hour'] );
673
- $minute = intval( $_POST['expirationdate_minute'] );
674
-
675
- if ( empty( $day ) ) {
676
- $day = date( 'd' );
677
- }
678
- if ( empty( $year ) ) {
679
- $year = date( 'Y' );
680
- }
681
- }
682
- $category = isset( $_POST['expirationdate_category'] ) ? $_POST['expirationdate_category'] : 0;
683
-
684
- $ts = get_gmt_from_date( "$year-$month-$day $hour:$minute:0", 'U' );
685
-
686
- if ( isset( $_POST['expirationdate_quickedit'] ) ) {
687
- $ed = get_post_meta( $id, '_expiration-date', true );
688
- if ( $ed ) {
689
- $opts = get_post_meta( $id, '_expiration-date-options', true );
690
- }
691
- } else {
692
- $opts = array();
693
-
694
- // Schedule/Update Expiration
695
- $opts['expireType'] = $_POST['expirationdate_expiretype'];
696
- $opts['id'] = $id;
697
-
698
- if ( $opts['expireType'] === 'category' || $opts['expireType'] === 'category-add' || $opts['expireType'] === 'category-remove' ) {
699
- if ( isset( $category ) && ! empty( $category ) ) {
700
- if ( ! empty( $category ) ) {
701
- $opts['category'] = $category;
702
- $opts['categoryTaxonomy'] = $_POST['taxonomy-heirarchical'];
703
- }
704
- }
705
- }
706
- }
707
- postexpirator_schedule_event( $id, $ts, $opts );
708
- } else {
709
- postexpirator_unschedule_event( $id );
710
- }
711
- }
712
- add_action( 'save_post', 'postexpirator_update_post_meta' );
713
-
714
- /**
715
- * Schedules the single event.
716
- *
717
- * @internal
718
- *
719
- * @access private
720
- */
721
- function postexpirator_schedule_event( $id, $ts, $opts ) {
722
- $debug = postexpirator_debug(); // check for/load debug
723
-
724
- $id = intval( $id );
725
-
726
- do_action( 'postexpiratior_schedule', $id, $ts, $opts ); // allow custom actions
727
-
728
- if ( wp_next_scheduled( 'postExpiratorExpire', array($id) ) !== false ) {
729
- $error = wp_clear_scheduled_hook( 'postExpiratorExpire', array($id), true ); // Remove any existing hooks
730
- if ( POSTEXPIRATOR_DEBUG ) {
731
- $debug->save( array('message' => $id . ' -> EXISTING FOUND - UNSCHEDULED - ' . ( is_wp_error( $error ) ? $error->get_error_message() : 'no error' )) );
732
- }
733
- }
734
-
735
- $error = wp_schedule_single_event( $ts, 'postExpiratorExpire', array($id), true );
736
- if ( POSTEXPIRATOR_DEBUG ) {
737
- $debug->save( array('message' => $id . ' -> SCHEDULED at ' . date_i18n( 'r', $ts ) . ' ' . '(' . $ts . ') with options ' . print_r( $opts, true ) . ' ' . ( is_wp_error( $error ) ? $error->get_error_message() : 'no error' ) ) );
738
- }
739
-
740
- // Update Post Meta
741
- update_post_meta( $id, '_expiration-date', $ts );
742
- if ( ! is_null( $opts ) ) {
743
- update_post_meta( $id, '_expiration-date-options', $opts );
744
- }
745
- update_post_meta( $id, '_expiration-date-status', 'saved' );
746
- }
747
-
748
- /**
749
- * Unschedules the single event.
750
- *
751
- * @internal
752
- *
753
- * @access private
754
- */
755
- function postexpirator_unschedule_event( $id ) {
756
- $debug = postexpirator_debug(); // check for/load debug
757
-
758
- do_action( 'postexpiratior_unschedule', $id ); // allow custom actions
759
-
760
- delete_post_meta( $id, '_expiration-date' );
761
- delete_post_meta( $id, '_expiration-date-options' );
762
-
763
- // Delete Scheduled Expiration
764
- if ( wp_next_scheduled( 'postExpiratorExpire', array($id) ) !== false ) {
765
- wp_clear_scheduled_hook( 'postExpiratorExpire', array($id) ); // Remove any existing hooks
766
- if ( POSTEXPIRATOR_DEBUG ) {
767
- $debug->save( array('message' => $id . ' -> UNSCHEDULED') );
768
- }
769
- }
770
- update_post_meta( $id, '_expiration-date-status', 'saved' );
771
- }
772
-
773
- /**
774
- * The new expiration function, to work with single scheduled events.
775
- *
776
- * This was designed to hopefully be more flexible for future tweaks/modifications to the architecture.
777
- *
778
- * @internal
779
- *
780
- * @access private
781
- */
782
- function postexpirator_expire_post( $id ) {
783
- $debug = postexpirator_debug(); // check for/load debug
784
-
785
- if ( empty( $id ) ) {
786
- if ( POSTEXPIRATOR_DEBUG ) {
787
- $debug->save( array('message' => 'No Post ID found - exiting') );
788
- }
789
- return false;
790
- }
791
-
792
- if ( is_null( get_post( $id ) ) ) {
793
- if ( POSTEXPIRATOR_DEBUG ) {
794
- $debug->save( array('message' => $id . ' -> Post does not exist - exiting') );
795
- }
796
- return false;
797
- }
798
-
799
- $posttype = get_post_type( $id );
800
- $posttitle = get_the_title( $id );
801
- $postlink = get_post_permalink( $id );
802
-
803
- $postoptions = get_post_meta( $id, '_expiration-date-options', true );
804
- $expireType = $category = $categoryTaxonomy = null;
805
-
806
- if ( isset( $postoptions['expireType'] ) ) {
807
- $expireType = $postoptions['expireType'];
808
- }
809
-
810
- if ( isset( $postoptions['category'] ) ) {
811
- $category = $postoptions['category'];
812
- }
813
-
814
- if ( isset( $postoptions['categoryTaxonomy'] ) ) {
815
- $categoryTaxonomy = $postoptions['categoryTaxonomy'];
816
- }
817
-
818
- $ed = get_post_meta( $id, '_expiration-date', true );
819
-
820
- // Check for default expire only if not passed in
821
- if ( empty( $expireType ) ) {
822
- $posttype = get_post_type( $id );
823
- if ( $posttype === 'page' ) {
824
- $expireType = strtolower( get_option( 'expirationdateExpiredPageStatus', POSTEXPIRATOR_PAGESTATUS ) );
825
- } elseif ( $posttype === 'post' ) {
826
- $expireType = strtolower( get_option( 'expirationdateExpiredPostStatus', 'draft' ) );
827
- } else {
828
- $expireType = apply_filters( 'postexpirator_custom_posttype_expire', $expireType, $posttype ); // hook to set defaults for custom post types
829
- }
830
- }
831
-
832
- // Remove KSES - wp_cron runs as an unauthenticated user, which will by default trigger kses filtering,
833
- // even if the post was published by a admin user. It is fairly safe here to remove the filter call since
834
- // we are only changing the post status/meta information and not touching the content.
835
- kses_remove_filters();
836
-
837
- // Do Work
838
- if ( $expireType === 'draft' ) {
839
- if ( wp_update_post( array('ID' => $id, 'post_status' => 'draft') ) === 0 ) {
840
- if ( POSTEXPIRATOR_DEBUG ) {
841
- $debug->save( array('message' => $id . ' -> FAILED ' . $expireType . ' ' . print_r( $postoptions, true )) );
842
- }
843
- } else {
844
- $emailBody = sprintf( __( '%1$s (%2$s) has expired at %3$s. Post status has been successfully changed to "%4$s".', 'post-expirator' ), '##POSTTITLE##', '##POSTLINK##', '##EXPIRATIONDATE##', strtoupper( $expireType ) );
845
- if ( POSTEXPIRATOR_DEBUG ) {
846
- $debug->save( array('message' => $id . ' -> PROCESSED ' . $expireType . ' ' . print_r( $postoptions, true )) );
847
- }
848
- }
849
- } elseif ( $expireType === 'private' ) {
850
- if ( wp_update_post( array('ID' => $id, 'post_status' => 'private') ) === 0 ) {
851
- if ( POSTEXPIRATOR_DEBUG ) {
852
- $debug->save( array('message' => $id . ' -> FAILED ' . $expireType . ' ' . print_r( $postoptions, true )) );
853
- }
854
- } else {
855
- $emailBody = sprintf( __( '%1$s (%2$s) has expired at %3$s. Post status has been successfully changed to "%4$s".', 'post-expirator' ), '##POSTTITLE##', '##POSTLINK##', '##EXPIRATIONDATE##', strtoupper( $expireType ) );
856
- if ( POSTEXPIRATOR_DEBUG ) {
857
- $debug->save( array('message' => $id . ' -> PROCESSED ' . $expireType . ' ' . print_r( $postoptions, true )) );
858
- }
859
- }
860
- } elseif ( $expireType === 'delete' ) {
861
- if ( wp_delete_post( $id ) === false ) {
862
- if ( POSTEXPIRATOR_DEBUG ) {
863
- $debug->save( array('message' => $id . ' -> FAILED ' . $expireType . ' ' . print_r( $postoptions, true )) );
864
- }
865
- } else {
866
- $emailBody = sprintf( __( '%1$s (%2$s) has expired at %3$s. Post status has been successfully changed to "%4$s".', 'post-expirator' ), '##POSTTITLE##', '##POSTLINK##', '##EXPIRATIONDATE##', strtoupper( $expireType ) );
867
- if ( POSTEXPIRATOR_DEBUG ) {
868
- $debug->save( array('message' => $id . ' -> PROCESSED ' . $expireType . ' ' . print_r( $postoptions, true )) );
869
- }
870
- }
871
- } elseif ( $expireType === 'trash' ) {
872
- if ( wp_trash_post( $id ) === false ) {
873
- if ( POSTEXPIRATOR_DEBUG ) {
874
- $debug->save( array('message' => $id . ' -> FAILED ' . $expireType . ' ' . print_r( $postoptions, true )) );
875
- }
876
- } else {
877
- $emailBody = sprintf( __( '%1$s (%2$s) has expired at %3$s. Post status has been successfully changed to "%4$s".', 'post-expirator' ), '##POSTTITLE##', '##POSTLINK##', '##EXPIRATIONDATE##', strtoupper( $expireType ) );
878
- if ( POSTEXPIRATOR_DEBUG ) {
879
- $debug->save( array('message' => $id . ' -> PROCESSED ' . $expireType . ' ' . print_r( $postoptions, true )) );
880
- }
881
- }
882
- } elseif ( $expireType === 'stick' ) {
883
- if ( stick_post( $id ) === false ) {
884
- if ( POSTEXPIRATOR_DEBUG ) {
885
- $debug->save( array('message' => $id . ' -> FAILED ' . $expireType . ' ' . print_r( $postoptions, true )) );
886
- }
887
- } else {
888
- $emailBody = sprintf( __( '%1$s (%2$s) has expired at %3$s. Post "%4$s" status has been successfully set.', 'post-expirator' ), '##POSTTITLE##', '##POSTLINK##', '##EXPIRATIONDATE##', 'STICKY' );
889
- if ( POSTEXPIRATOR_DEBUG ) {
890
- $debug->save( array('message' => $id . ' -> PROCESSED ' . $expireType . ' ' . print_r( $postoptions, true )) );
891
- }
892
- }
893
- } elseif ( $expireType === 'unstick' ) {
894
- if ( unstick_post( $id ) === false ) {
895
- if ( POSTEXPIRATOR_DEBUG ) {
896
- $debug->save( array('message' => $id . ' -> FAILED ' . $expireType . ' ' . print_r( $postoptions, true )) );
897
- }
898
- } else {
899
- $emailBody = sprintf( __( '%1$s (%2$s) has expired at %3$s. Post "%4$s" status has been successfully removed.', 'post-expirator' ), '##POSTTITLE##', '##POSTLINK##', '##EXPIRATIONDATE##', 'STICKY' );
900
- if ( POSTEXPIRATOR_DEBUG ) {
901
- $debug->save( array('message' => $id . ' -> PROCESSED ' . $expireType . ' ' . print_r( $postoptions, true )) );
902
- }
903
- }
904
- } elseif ( $expireType === 'category' ) {
905
- if ( ! empty( $category ) ) {
906
- if ( ! isset( $categoryTaxonomy ) || $categoryTaxonomy === 'category' ) {
907
- if ( wp_update_post( array('ID' => $id, 'post_category' => $category) ) === 0 ) {
908
- if ( POSTEXPIRATOR_DEBUG ) {
909
- $debug->save( array('message' => $id . ' -> FAILED ' . $expireType . ' ' . print_r( $postoptions, true )) );
910
- }
911
- } else {
912
- $emailBody = sprintf( __( '%1$s (%2$s) has expired at %3$s. Post "%4$s" have now been set to "%5$s".', 'post-expirator' ), '##POSTTITLE##', '##POSTLINK##', '##EXPIRATIONDATE##', 'CATEGORIES', implode( ',', _postexpirator_get_cat_names( $category ) ) );
913
- if ( POSTEXPIRATOR_DEBUG ) {
914
- $debug->save( array('message' => $id . ' -> PROCESSED ' . $expireType . ' ' . print_r( $postoptions, true )) );
915
- $debug->save( array('message' => $id . ' -> CATEGORIES REPLACED ' . print_r( _postexpirator_get_cat_names( $category ), true )) );
916
- $debug->save( array('message' => $id . ' -> CATEGORIES COMPLETE ' . print_r( _postexpirator_get_cat_names( $category ), true )) );
917
- }
918
- }
919
- } else {
920
- $terms = array_map( 'intval', $category );
921
- if ( is_wp_error( wp_set_object_terms( $id, $terms, $categoryTaxonomy, false ) ) ) {
922
- if ( POSTEXPIRATOR_DEBUG ) {
923
- $debug->save( array('message' => $id . ' -> FAILED ' . $expireType . ' ' . print_r( $postoptions, true )) );
924
- }
925
- } else {
926
- $emailBody = sprintf( __( '%1$s (%2$s) has expired at %3$s. Post "%4$s" have now been set to "%5$s".', 'post-expirator' ), '##POSTTITLE##', '##POSTLINK##', '##EXPIRATIONDATE##', 'CATEGORIES', implode( ',', _postexpirator_get_cat_names( $category ) ) );
927
- if ( POSTEXPIRATOR_DEBUG ) {
928
- $debug->save( array('message' => $id . ' -> PROCESSED ' . $expireType . ' ' . print_r( $postoptions, true )) );
929
- $debug->save( array('message' => $id . ' -> CATEGORIES REPLACED ' . print_r( _postexpirator_get_cat_names( $category ), true )) );
930
- $debug->save( array('message' => $id . ' -> CATEGORIES COMPLETE ' . print_r( _postexpirator_get_cat_names( $category ), true )) );
931
- }
932
- }
933
- }
934
- } else {
935
- if ( POSTEXPIRATOR_DEBUG ) {
936
- $debug->save( array('message' => $id . ' -> CATEGORIES MISSING ' . $expireType . ' ' . print_r( $postoptions, true )) );
937
- }
938
- }
939
- } elseif ( $expireType === 'category-add' ) {
940
- if ( ! empty( $category ) ) {
941
- if ( ! isset( $categoryTaxonomy ) || $categoryTaxonomy === 'category' ) {
942
- $cats = wp_get_post_categories( $id );
943
- $merged = array_merge( $cats, $category );
944
- if ( wp_update_post( array('ID' => $id, 'post_category' => $merged) ) === 0 ) {
945
- if ( POSTEXPIRATOR_DEBUG ) {
946
- $debug->save( array('message' => $id . ' -> FAILED ' . $expireType . ' ' . print_r( $postoptions, true )) );
947
- }
948
- } else {
949
- $emailBody = sprintf( __( '%1$s (%2$s) has expired at %3$s. The following post "%4$s" have now been added: "%5$s". The full list of categories on the post are: "%6$s".', 'post-expirator' ), '##POSTTITLE##', '##POSTLINK##', '##EXPIRATIONDATE##', 'CATEGORIES', implode( ',', _postexpirator_get_cat_names( $category ) ), implode( ',', _postexpirator_get_cat_names( $merged ) ) );
950
- if ( POSTEXPIRATOR_DEBUG ) {
951
- $debug->save( array('message' => $id . ' -> PROCESSED ' . $expireType . ' ' . print_r( $postoptions, true )) );
952
- $debug->save( array('message' => $id . ' -> CATEGORIES ADDED ' . print_r( _postexpirator_get_cat_names( $category ), true )) );
953
- $debug->save( array('message' => $id . ' -> CATEGORIES COMPLETE ' . print_r( _postexpirator_get_cat_names( $merged ), true )) );
954
- }
955
- }
956
- } else {
957
- $terms = array_map( 'intval', $category );
958
- if ( is_wp_error( wp_set_object_terms( $id, $terms, $categoryTaxonomy, true ) ) ) {
959
- if ( POSTEXPIRATOR_DEBUG ) {
960
- $debug->save( array('message' => $id . ' -> FAILED ' . $expireType . ' ' . print_r( $postoptions, true )) );
961
- }
962
- } else {
963
- $emailBody = sprintf( __( '%1$s (%2$s) has expired at %3$s. The following post "%4$s" have now been added: "%5$s". The full list of categories on the post are: "%6$s".', 'post-expirator' ), '##POSTTITLE##', '##POSTLINK##', '##EXPIRATIONDATE##', 'CATEGORIES', implode( ',', _postexpirator_get_cat_names( $category ) ), implode( ',', _postexpirator_get_cat_names( $merged ) ) );
964
- if ( POSTEXPIRATOR_DEBUG ) {
965
- $debug->save( array('message' => $id . ' -> PROCESSED ' . $expireType . ' ' . print_r( $postoptions, true )) );
966
- $debug->save( array('message' => $id . ' -> CATEGORIES ADDED ' . print_r( _postexpirator_get_cat_names( $category ), true )) );
967
- $debug->save( array('message' => $id . ' -> CATEGORIES COMPLETE ' . print_r( _postexpirator_get_cat_names( $category ), true )) );
968
- }
969
- }
970
- }
971
- } else {
972
- if ( POSTEXPIRATOR_DEBUG ) {
973
- $debug->save( array('message' => $id . ' -> CATEGORIES MISSING ' . $expireType . ' ' . print_r( $postoptions, true )) );
974
- }
975
- }
976
- } elseif ( $expireType === 'category-remove' ) {
977
- if ( ! empty( $category ) ) {
978
- if ( ! isset( $categoryTaxonomy ) || $categoryTaxonomy === 'category' ) {
979
- $cats = wp_get_post_categories( $id );
980
- $merged = array();
981
- foreach ( $cats as $cat ) {
982
- if ( ! in_array( $cat, $category, false ) ) {
983
- $merged[] = $cat;
984
- }
985
- }
986
-
987
- if ( wp_update_post( array('ID' => $id, 'post_category' => $merged) ) === 0 ) {
988
- if ( POSTEXPIRATOR_DEBUG ) {
989
- $debug->save( array('message' => $id . ' -> FAILED ' . $expireType . ' ' . print_r( $postoptions, true )) );
990
- }
991
- } else {
992
- $emailBody = sprintf( __( '%1$s (%2$s) has expired at %3$s. The following post "%4$s" have now been removed: "%5$s". The full list of categories on the post are: "%6$s".', 'post-expirator' ), '##POSTTITLE##', '##POSTLINK##', '##EXPIRATIONDATE##', 'CATEGORIES', implode( ',', _postexpirator_get_cat_names( $category ) ), implode( ',', _postexpirator_get_cat_names( $merged ) ) );
993
- if ( POSTEXPIRATOR_DEBUG ) {
994
- $debug->save( array('message' => $id . ' -> PROCESSED ' . $expireType . ' ' . print_r( $postoptions, true )) );
995
- $debug->save( array('message' => $id . ' -> CATEGORIES REMOVED ' . print_r( _postexpirator_get_cat_names( $category ), true )) );
996
- $debug->save( array('message' => $id . ' -> CATEGORIES COMPLETE ' . print_r( _postexpirator_get_cat_names( $merged ), true )) );
997
- }
998
- }
999
- } else {
1000
- $terms = wp_get_object_terms( $id, $categoryTaxonomy, array('fields' => 'ids') );
1001
- $merged = array();
1002
- foreach ( $terms as $term ) {
1003
- if ( ! in_array( $term, $category, false ) ) {
1004
- $merged[] = $term;
1005
- }
1006
- }
1007
- $terms = array_map( 'intval', $merged );
1008
- if ( is_wp_error( wp_set_object_terms( $id, $terms, $categoryTaxonomy, false ) ) ) {
1009
- if ( POSTEXPIRATOR_DEBUG ) {
1010
- $debug->save( array('message' => $id . ' -> FAILED ' . $expireType . ' ' . print_r( $postoptions, true )) );
1011
- }
1012
- } else {
1013
- $emailBody = sprintf( __( '%1$s (%2$s) has expired at %3$s. The following post "%4$s" have now been removed: "%5$s". The full list of categories on the post are: "%6$s".', 'post-expirator' ), '##POSTTITLE##', '##POSTLINK##', '##EXPIRATIONDATE##', 'CATEGORIES', implode( ',', _postexpirator_get_cat_names( $category ) ), implode( ',', _postexpirator_get_cat_names( $merged ) ) );
1014
- if ( POSTEXPIRATOR_DEBUG ) {
1015
- $debug->save( array('message' => $id . ' -> PROCESSED ' . $expireType . ' ' . print_r( $postoptions, true )) );
1016
- $debug->save( array('message' => $id . ' -> CATEGORIES REMOVED ' . print_r( _postexpirator_get_cat_names( $category ), true )) );
1017
- $debug->save( array('message' => $id . ' -> CATEGORIES COMPLETE ' . print_r( _postexpirator_get_cat_names( $category ), true )) );
1018
- }
1019
- }
1020
- }
1021
- } else {
1022
- if ( POSTEXPIRATOR_DEBUG ) {
1023
- $debug->save( array('message' => $id . ' -> CATEGORIES MISSING ' . $expireType . ' ' . print_r( $postoptions, true )) );
1024
- }
1025
- }
1026
- }
1027
-
1028
- // Process Email
1029
- $emailenabled = get_option( 'expirationdateEmailNotification', POSTEXPIRATOR_EMAILNOTIFICATION );
1030
- // phpcs:ignore WordPress.PHP.StrictComparisons.LooseComparison
1031
- if ( $emailenabled == 1 && isset( $emailBody ) ) {
1032
- $subj = sprintf( __( 'Post Expiration Complete "%s"', 'post-expirator' ), $posttitle );
1033
- $emailBody = str_replace( '##POSTTITLE##', $posttitle, $emailBody );
1034
- $emailBody = str_replace( '##POSTLINK##', $postlink, $emailBody );
1035
- $emailBody = str_replace( '##EXPIRATIONDATE##', get_date_from_gmt( gmdate( 'Y-m-d H:i:s', $ed ), get_option( 'date_format' ) . ' ' . get_option( 'time_format' ) ), $emailBody );
1036
-
1037
- $emails = array();
1038
- // Get Blog Admins
1039
- $emailadmins = get_option( 'expirationdateEmailNotificationAdmins', POSTEXPIRATOR_EMAILNOTIFICATIONADMINS );
1040
- // phpcs:ignore WordPress.PHP.StrictComparisons.LooseComparison
1041
- if ( $emailadmins == 1 ) {
1042
- $blogusers = get_users( 'role=Administrator' );
1043
- foreach ( $blogusers as $user ) {
1044
- $emails[] = $user->user_email;
1045
- }
1046
- }
1047
-
1048
- // Get Global Notification Emails
1049
- $emaillist = get_option( 'expirationdateEmailNotificationList' );
1050
- if ( ! empty( $emaillist ) ) {
1051
- $vals = explode( ',', $emaillist );
1052
- foreach ( $vals as $val ) {
1053
- $emails[] = trim( $val );
1054
- }
1055
- }
1056
-
1057
- // Get Post Type Notification Emails
1058
- $defaults = get_option( 'expirationdateDefaults' . ucfirst( $posttype ) );
1059
- if ( isset( $defaults['emailnotification'] ) && ! empty( $defaults['emailnotification'] ) ) {
1060
- $vals = explode( ',', $defaults['emailnotification'] );
1061
- foreach ( $vals as $val ) {
1062
- $emails[] = trim( $val );
1063
- }
1064
- }
1065
-
1066
- // Send Emails
1067
- foreach ( $emails as $email ) {
1068
- if ( wp_mail( $email, sprintf( __( '[%1$s] %2$s' ), get_option( 'blogname' ), $subj ), $emailBody ) ) {
1069
- if ( POSTEXPIRATOR_DEBUG ) {
1070
- $debug->save( array('message' => $id . ' -> EXPIRATION EMAIL SENT (' . $email . ')') );
1071
- }
1072
- } else {
1073
- if ( POSTEXPIRATOR_DEBUG ) {
1074
- $debug->save( array('message' => $id . ' -> EXPIRATION EMAIL FAILED (' . $email . ')') );
1075
- }
1076
- }
1077
- }
1078
- }
1079
-
1080
- }
1081
- add_action( 'postExpiratorExpire', 'postexpirator_expire_post' );
1082
-
1083
- /**
1084
- * Internal method to get category names corresponding to the category IDs.
1085
- *
1086
- * @internal
1087
- *
1088
- * @access private
1089
- */
1090
- function _postexpirator_get_cat_names( $cats ) {
1091
- $out = array();
1092
- foreach ( $cats as $cat ) {
1093
- $out[ $cat ] = get_the_category_by_id( $cat );
1094
- }
1095
- return $out;
1096
- }
1097
-
1098
- /**
1099
- * Build the menu for the options page
1100
- *
1101
- * @internal
1102
- *
1103
- * @access private
1104
- */
1105
- function postexpirator_menu_tabs( $tab ) {
1106
- echo '<p>';
1107
- if ( empty( $tab ) ) {
1108
- $tab = 'general';
1109
- }
1110
- echo '<a href="' . admin_url( 'options-general.php?page=post-expirator.php&tab=general' ) . '"' . ( $tab === 'general' ? ' style="font-weight: bold; text-decoration:none;"' : '' ) . '>' . __( 'General Settings', 'post-expirator' ) . '</a> | ';
1111
- echo '<a href="' . admin_url( 'options-general.php?page=post-expirator.php&tab=defaults' ) . '"' . ( $tab === 'defaults' ? ' style="font-weight: bold; text-decoration:none;"' : '' ) . '>' . __( 'Defaults', 'post-expirator' ) . '</a> | ';
1112
- echo '<a href="' . admin_url( 'options-general.php?page=post-expirator.php&tab=diagnostics' ) . '"' . ( $tab === 'diagnostics' ? ' style="font-weight: bold; text-decoration:none;"' : '' ) . '>' . __( 'Diagnostics', 'post-expirator' ) . '</a> | ';
1113
- echo '<a href="' . admin_url( 'options-general.php?page=post-expirator.php&tab=viewdebug' ) . '"' . ( $tab === 'viewdebug' ? ' style="font-weight: bold; text-decoration:none;"' : '' ) . '>' . __( 'View Debug Logs', 'post-expirator' ) . '</a>';
1114
- echo '</p><hr/>';
1115
- }
1116
-
1117
- /**
1118
- * Show the menu.
1119
- *
1120
- * @internal
1121
- *
1122
- * @access private
1123
- */
1124
- function postexpirator_menu() {
1125
- $tab = isset( $_GET['tab'] ) ? $_GET['tab'] : '';
1126
-
1127
- echo '<div class="wrap">';
1128
- echo '<h2>' . __( 'Post Expirator Options', 'post-expirator' ) . '</h2>';
1129
-
1130
- postexpirator_menu_tabs( $tab );
1131
- if ( empty( $tab ) || $tab === 'general' ) {
1132
- postexpirator_menu_general();
1133
- } elseif ( $tab === 'defaults' ) {
1134
- postexpirator_menu_defaults();
1135
- } elseif ( $tab === 'diagnostics' ) {
1136
- postexpirator_menu_diagnostics();
1137
- } elseif ( $tab === 'viewdebug' ) {
1138
- postexpirator_menu_debug();
1139
- }
1140
- echo '</div>';
1141
- }
1142
-
1143
- /**
1144
- * Hook's to add plugin page menu
1145
- *
1146
- * @internal
1147
- *
1148
- * @access private
1149
- */
1150
- function postexpirator_add_menu() {
1151
- add_submenu_page( 'options-general.php', __( 'Post Expirator Options', 'post-expirator' ), __( 'Post Expirator', 'post-expirator' ), 'manage_options', basename( __FILE__ ), 'postexpirator_menu' );
1152
- }
1153
- add_action( 'admin_menu', 'postexpirator_add_menu' );
1154
-
1155
- /**
1156
- * Show the Expiration Date options page
1157
- *
1158
- * @internal
1159
- *
1160
- * @access private
1161
- */
1162
- function postexpirator_menu_general() {
1163
- if ( isset( $_POST['expirationdateSave'] ) && $_POST['expirationdateSave'] ) {
1164
- if ( ! isset( $_POST['_postExpiratorMenuGeneral_nonce'] ) || ! wp_verify_nonce( $_POST['_postExpiratorMenuGeneral_nonce'], 'postexpirator_menu_general' ) ) {
1165
- print 'Form Validation Failure: Sorry, your nonce did not verify.';
1166
- exit;
1167
- } else {
1168
- // Filter Content
1169
- $_POST = filter_input_array( INPUT_POST, FILTER_SANITIZE_STRING );
1170
-
1171
- update_option( 'expirationdateDefaultDateFormat', $_POST['expired-default-date-format'] );
1172
- update_option( 'expirationdateDefaultTimeFormat', $_POST['expired-default-time-format'] );
1173
- update_option( 'expirationdateDisplayFooter', $_POST['expired-display-footer'] );
1174
- update_option( 'expirationdateEmailNotification', $_POST['expired-email-notification'] );
1175
- update_option( 'expirationdateEmailNotificationAdmins', $_POST['expired-email-notification-admins'] );
1176
- update_option( 'expirationdateEmailNotificationList', trim( $_POST['expired-email-notification-list'] ) );
1177
- update_option( 'expirationdateFooterContents', $_POST['expired-footer-contents'] );
1178
- update_option( 'expirationdateFooterStyle', $_POST['expired-footer-style'] );
1179
- if ( isset( $_POST['expirationdate_category'] ) ) {
1180
- update_option( 'expirationdateCategoryDefaults', $_POST['expirationdate_category'] );
1181
- }
1182
- update_option( 'expirationdateDefaultDate', $_POST['expired-default-expiration-date'] );
1183
- if ( $_POST['expired-custom-expiration-date'] ) {
1184
- update_option( 'expirationdateDefaultDateCustom', $_POST['expired-custom-expiration-date'] );
1185
- }
1186
- echo "<div id='message' class='updated fade'><p>";
1187
- _e( 'Saved Options!', 'post-expirator' );
1188
- echo '</p></div>';
1189
- }
1190
- }
1191
-
1192
- // phpcs:disable WordPress.NamingConventions.ValidVariableName.InterpolatedVariableNotSnakeCase
1193
- // phpcs:disable WordPress.PHP.StrictComparisons.LooseComparison
1194
-
1195
- // Get Option
1196
- $expirationdateDefaultDateFormat = get_option( 'expirationdateDefaultDateFormat', POSTEXPIRATOR_DATEFORMAT );
1197
- $expirationdateDefaultTimeFormat = get_option( 'expirationdateDefaultTimeFormat', POSTEXPIRATOR_TIMEFORMAT );
1198
- $expireddisplayfooter = get_option( 'expirationdateDisplayFooter', POSTEXPIRATOR_FOOTERDISPLAY );
1199
- $expiredemailnotification = get_option( 'expirationdateEmailNotification', POSTEXPIRATOR_EMAILNOTIFICATION );
1200
- $expiredemailnotificationadmins = get_option( 'expirationdateEmailNotificationAdmins', POSTEXPIRATOR_EMAILNOTIFICATIONADMINS );
1201
- $expiredemailnotificationlist = get_option( 'expirationdateEmailNotificationList', '' );
1202
- $expirationdateFooterContents = get_option( 'expirationdateFooterContents', POSTEXPIRATOR_FOOTERCONTENTS );
1203
- $expirationdateFooterStyle = get_option( 'expirationdateFooterStyle', POSTEXPIRATOR_FOOTERSTYLE );
1204
- $expirationdateDefaultDate = get_option( 'expirationdateDefaultDate', POSTEXPIRATOR_EXPIREDEFAULT );
1205
- $expirationdateDefaultDateCustom = get_option( 'expirationdateDefaultDateCustom' );
1206
-
1207
- $categories = get_option( 'expirationdateCategoryDefaults' );
1208
-
1209
- $expireddisplayfooterenabled = '';
1210
- $expireddisplayfooterdisabled = '';
1211
- if ( $expireddisplayfooter == 0 ) {
1212
- $expireddisplayfooterdisabled = 'checked="checked"';
1213
- } elseif ( $expireddisplayfooter == 1 ) {
1214
- $expireddisplayfooterenabled = 'checked="checked"';
1215
- }
1216
-
1217
- $expiredemailnotificationenabled = '';
1218
- $expiredemailnotificationdisabled = '';
1219
- if ( $expiredemailnotification == 0 ) {
1220
- $expiredemailnotificationdisabled = 'checked="checked"';
1221
- } elseif ( $expiredemailnotification == 1 ) {
1222
- $expiredemailnotificationenabled = 'checked="checked"';
1223
- }
1224
-
1225
- $expiredemailnotificationadminsenabled = '';
1226
- $expiredemailnotificationadminsdisabled = '';
1227
- if ( $expiredemailnotificationadmins == 0 ) {
1228
- $expiredemailnotificationadminsdisabled = 'checked="checked"';
1229
- } elseif ( $expiredemailnotificationadmins == 1 ) {
1230
- $expiredemailnotificationadminsenabled = 'checked="checked"';
1231
- }
1232
- ?>
1233
- <p>
1234
- <?php _e( 'The post expirator plugin sets a custom meta value, and then optionally allows you to select if you want the post changed to a draft status or deleted when it expires.', 'post-expirator' ); ?>
1235
- </p>
1236
- <p>
1237
- <?php _e( 'Valid [postexpirator] attributes:', 'post-expirator' ); ?>
1238
- <ul>
1239
- <li><?php _e( 'type - defaults to full - valid options are full,date,time', 'post-expirator' ); ?></li>
1240
- <li><?php _e( 'dateformat - format set here will override the value set on the settings page', 'post-expirator' ); ?></li>
1241
- <li><?php _e( 'timeformat - format set here will override the value set on the settings page', 'post-expirator' ); ?></li>
1242
- </ul>
1243
- </p>
1244
- <form method="post" id="expirationdate_save_options">
1245
- <?php wp_nonce_field( 'postexpirator_menu_general', '_postExpiratorMenuGeneral_nonce' ); ?>
1246
- <h3><?php _e( 'Defaults', 'post-expirator' ); ?></h3>
1247
- <table class="form-table">
1248
- <tr valign="top">
1249
- <th scope="row"><label for="expired-default-date-format"><?php _e( 'Date Format:', 'post-expirator' ); ?></label></th>
1250
- <td>
1251
- <input type="text" name="expired-default-date-format" id="expired-default-date-format" value="<?php echo $expirationdateDefaultDateFormat; ?>" size="25" /> (<?php echo date_i18n( "$expirationdateDefaultDateFormat" ); ?>)
1252
- <br/>
1253
- <?php _e( 'The default format to use when displaying the expiration date within a post using the [postexpirator] shortcode or within the footer. For information on valid formatting options, see: <a href="http://us2.php.net/manual/en/function.date.php" target="_blank">PHP Date Function</a>.', 'post-expirator' ); ?>
1254
- </td>
1255
- </tr>
1256
- <tr valign="top">
1257
- <th scope="row"><label for="expired-default-time-format"><?php _e( 'Time Format:', 'post-expirator' ); ?></label></th>
1258
- <td>
1259
- <input type="text" name="expired-default-time-format" id="expired-default-time-format" value="<?php echo $expirationdateDefaultTimeFormat; ?>" size="25" /> (<?php echo date_i18n( "$expirationdateDefaultTimeFormat" ); ?>)
1260
- <br/>
1261
- <?php _e( 'The default format to use when displaying the expiration time within a post using the [postexpirator] shortcode or within the footer. For information on valid formatting options, see: <a href="http://us2.php.net/manual/en/function.date.php" target="_blank">PHP Date Function</a>.', 'post-expirator' ); ?>
1262
- </td>
1263
- </tr>
1264
- <tr valign="top">
1265
- <th scope="row"><label for="expired-default-expiration-date"><?php _e( 'Default Date/Time Duration:', 'post-expirator' ); ?></label></th>
1266
- <td>
1267
- <select name="expired-default-expiration-date" id="expired-default-expiration-date" onchange="expirationdate_toggle_defaultdate(this)">
1268
- <option value="null" <?php echo ( $expirationdateDefaultDate == 'null' ) ? ' selected="selected"' : ''; ?>><?php _e( 'None', 'post-expirator' ); ?></option>
1269
- <option value="custom" <?php echo ( $expirationdateDefaultDate == 'custom' ) ? ' selected="selected"' : ''; ?>><?php _e( 'Custom', 'post-expirator' ); ?></option>
1270
- <option value="publish" <?php echo ( $expirationdateDefaultDate == 'publish' ) ? ' selected="selected"' : ''; ?>><?php _e( 'Post/Page Publish Time', 'post-expirator' ); ?></option>
1271
- </select>
1272
- <br/>
1273
- <?php _e( 'Set the default expiration date to be used when creating new posts and pages. Defaults to none.', 'post-expirator' ); ?>
1274
- <?php $show = ( $expirationdateDefaultDate == 'custom' ) ? 'block' : 'none'; ?>
1275
- <div id="expired-custom-container" style="display: <?php echo $show; ?>;">
1276
- <br/><label for="expired-custom-expiration-date">Custom:</label> <input type="text" value="<?php echo $expirationdateDefaultDateCustom; ?>" name="expired-custom-expiration-date" id="expired-custom-expiration-date" />
1277
- <br/>
1278
- <?php echo sprintf( __( 'Set the custom value to use for the default expiration date. For information on formatting, see %1$s. For example, you could enter %2$s+1 month%3$s or %4$s+1 week 2 days 4 hours 2 seconds%5$s or %6$snext Thursday%7$s.', 'post-expirator' ), '<a href="http://php.net/manual/en/function.strtotime.php" target="_new">PHP strtotime function</a>', '<code>', '</code>', '<code>', '</code>', '<code>', '</code>' ); ?>
1279
- </div>
1280
- </td>
1281
- </tr>
1282
- </table>
1283
- <h3><?php _e( 'Category Expiration', 'post-expirator' ); ?></h3>
1284
- <table class="form-table">
1285
- <tr valign="top">
1286
- <th scope="row"><?php _e( 'Default Expiration Category', 'post-expirator' ); ?>:</th>
1287
- <td>
1288
- <?php
1289
- echo '<div class="wp-tab-panel" id="post-expirator-cat-list">';
1290
- echo '<ul id="categorychecklist" class="list:category categorychecklist form-no-clear">';
1291
- $walker = new Walker_PostExpirator_Category_Checklist();
1292
- wp_terms_checklist( 0, array( 'taxonomy' => 'category', 'walker' => $walker, 'selected_cats' => $categories, 'checked_ontop' => false ) );
1293
- echo '</ul>';
1294
- echo '</div>';
1295
- ?>
1296
- <br/>
1297
- <?php _e( "Set's the default expiration category for the post.", 'post-expirator' ); ?>
1298
- </td>
1299
- </tr>
1300
- </table>
1301
-
1302
- <h3><?php _e( 'Expiration Email Notification', 'post-expirator' ); ?></h3>
1303
- <p><?php _e( 'Whenever a post expires, an email can be sent to alert users of the expiration.', 'post-expirator' ); ?></p>
1304
- <table class="form-table">
1305
- <tr valign="top">
1306
- <th scope="row"><?php _e( 'Enable Email Notification?', 'post-expirator' ); ?></th>
1307
- <td>
1308
- <input type="radio" name="expired-email-notification" id="expired-email-notification-true" value="1" <?php echo $expiredemailnotificationenabled; ?>/> <label for="expired-email-notification-true"><?php _e( 'Enabled', 'post-expirator' ); ?></label>
1309
- <br/>
1310
- <input type="radio" name="expired-email-notification" id="expired-email-notification-false" value="0" <?php echo $expiredemailnotificationdisabled; ?>/> <label for="expired-email-notification-false"><?php _e( 'Disabled', 'post-expirator' ); ?></label>
1311
- <br/>
1312
- <?php _e( 'This will enable or disable the send of email notification on post expiration.', 'post-expirator' ); ?>
1313
- </td>
1314
- </tr>
1315
- <tr valign="top">
1316
- <th scope="row"><?php _e( 'Include Blog Administrators?', 'post-expirator' ); ?></th>
1317
- <td>
1318
- <input type="radio" name="expired-email-notification-admins" id="expired-email-notification-admins-true" value="1" <?php echo $expiredemailnotificationadminsenabled; ?>/> <label for="expired-email-notification-admins-true"><?php _e( 'Enabled', 'post-expirator' ); ?></label>
1319
- <br/>
1320
- <input type="radio" name="expired-email-notification-admins" id="expired-email-notification-admins-false" value="0" <?php echo $expiredemailnotificationadminsdisabled; ?>/> <label for="expired-email-notification-admins-false"><?php _e( 'Disabled', 'post-expirator' ); ?></label>
1321
- <br/>
1322
- <?php _e( 'This will include all users with the role of "Administrator" in the post expiration email.', 'post-expirator' ); ?>
1323
- </td>
1324
- </tr>
1325
- <tr valign="top">
1326
- <th scope="row"><label for="expired-email-notification-list"><?php _e( 'Who to notify:', 'post-expirator' ); ?></label></th>
1327
- <td>
1328
- <input class="large-text" type="text" name="expired-email-notification-list" id="expired-email-notification-list" value="<?php echo $expiredemailnotificationlist; ?>" />
1329
- <br/>
1330
- <?php _e( 'Enter a comma seperate list of emails that you would like to be notified when the post expires. This will be applied to ALL post types. You can set post type specific emails on the Defaults tab.', 'post-expirator' ); ?>
1331
- </td>
1332
- </tr>
1333
- </table>
1334
-
1335
- <h3><?php _e( 'Post Footer Display', 'post-expirator' ); ?></h3>
1336
- <p><?php _e( 'Enabling this below will display the expiration date automatically at the end of any post which is set to expire.', 'post-expirator' ); ?></p>
1337
- <table class="form-table">
1338
- <tr valign="top">
1339
- <th scope="row"><?php _e( 'Show in post footer?', 'post-expirator' ); ?></th>
1340
- <td>
1341
- <input type="radio" name="expired-display-footer" id="expired-display-footer-true" value="1" <?php echo $expireddisplayfooterenabled; ?>/> <label for="expired-display-footer-true"><?php _e( 'Enabled', 'post-expirator' ); ?></label>
1342
- <br/>
1343
- <input type="radio" name="expired-display-footer" id="expired-display-footer-false" value="0" <?php echo $expireddisplayfooterdisabled; ?>/> <label for="expired-display-footer-false"><?php _e( 'Disabled', 'post-expirator' ); ?></label>
1344
- <br/>
1345
- <?php _e( 'This will enable or disable displaying the post expiration date in the post footer.', 'post-expirator' ); ?>
1346
- </td>
1347
- </tr>
1348
- <tr valign="top">
1349
- <th scope="row"><label for="expired-footer-contents"><?php _e( 'Footer Contents:', 'post-expirator' ); ?></label></th>
1350
- <td>
1351
- <textarea id="expired-footer-contents" name="expired-footer-contents" rows="3" cols="50"><?php echo $expirationdateFooterContents; ?></textarea>
1352
- <br/>
1353
- <?php _e( 'Enter the text you would like to appear at the bottom of every post that will expire. The following placeholders will be replaced with the post expiration date in the following format:', 'post-expirator' ); ?>
1354
- <ul>
1355
- <li>EXPIRATIONFULL -> <?php echo date_i18n( "$expirationdateDefaultDateFormat $expirationdateDefaultTimeFormat" ); ?></li>
1356
- <li>EXPIRATIONDATE -> <?php echo date_i18n( "$expirationdateDefaultDateFormat" ); ?></li>
1357
- <li>EXPIRATIONTIME -> <?php echo date_i18n( "$expirationdateDefaultTimeFormat" ); ?></li>
1358
- </ul>
1359
- </td>
1360
- </tr>
1361
- <tr valign="top">
1362
- <th scope="row"><label for="expired-footer-style"><?php _e( 'Footer Style:', 'post-expirator' ); ?></label></th>
1363
- <td>
1364
- <input type="text" name="expired-footer-style" id="expired-footer-style" value="<?php echo $expirationdateFooterStyle; ?>" size="25" />
1365
- (<span style="<?php echo $expirationdateFooterStyle; ?>"><?php _e( 'This post will expire on', 'post-expirator' ); ?> <?php echo date_i18n( "$expirationdateDefaultDateFormat $expirationdateDefaultTimeFormat" ); ?></span>)
1366
- <br/>
1367
- <?php _e( 'The inline css which will be used to style the footer text.', 'post-expirator' ); ?>
1368
- </td>
1369
- </tr>
1370
- </table>
1371
- <p class="submit">
1372
- <input type="submit" name="expirationdateSave" class="button-primary" value="<?php _e( 'Save Changes', 'post-expirator' ); ?>" />
1373
- </p>
1374
- </form>
1375
- <?php
1376
- // phpcs:enable
1377
- }
1378
-
1379
- /**
1380
- * The default menu.
1381
- *
1382
- * @internal
1383
- *
1384
- * @access private
1385
- */
1386
- function postexpirator_menu_defaults() {
1387
- $debug = postexpirator_debug();
1388
- $types = get_post_types( array('public' => true, '_builtin' => false) );
1389
- array_unshift( $types, 'post', 'page' );
1390
-
1391
- if ( isset( $_POST['expirationdateSaveDefaults'] ) ) {
1392
- if ( ! isset( $_POST['_postExpiratorMenuDefaults_nonce'] ) || ! wp_verify_nonce( $_POST['_postExpiratorMenuDefaults_nonce'], 'postexpirator_menu_defaults' ) ) {
1393
- print 'Form Validation Failure: Sorry, your nonce did not verify.';
1394
- exit;
1395
- } else {
1396
- // Filter Content
1397
- $_POST = filter_input_array( INPUT_POST, FILTER_SANITIZE_STRING );
1398
-
1399
- $defaults = array();
1400
- foreach ( $types as $type ) {
1401
- if ( isset( $_POST[ 'expirationdate_expiretype-' . $type ] ) ) {
1402
- $defaults[ $type ]['expireType'] = $_POST[ 'expirationdate_expiretype-' . $type ];
1403
- }
1404
- if ( isset( $_POST[ 'expirationdate_autoenable-' . $type ] ) ) {
1405
- $defaults[ $type ]['autoEnable'] = intval( $_POST[ 'expirationdate_autoenable-' . $type ] );
1406
- }
1407
- if ( isset( $_POST[ 'expirationdate_taxonomy-' . $type ] ) ) {
1408
- $defaults[ $type ]['taxonomy'] = $_POST[ 'expirationdate_taxonomy-' . $type ];
1409
- }
1410
- if ( isset( $_POST[ 'expirationdate_activemeta-' . $type ] ) ) {
1411
- $defaults[ $type ]['activeMetaBox'] = $_POST[ 'expirationdate_activemeta-' . $type ];
1412
- }
1413
- $defaults[ $type ]['emailnotification'] = trim( $_POST[ 'expirationdate_emailnotification-' . $type ] );
1414
-
1415
- // Save Settings
1416
- update_option( 'expirationdateDefaults' . ucfirst( $type ), $defaults[ $type ] );
1417
- }
1418
- echo "<div id='message' class='updated fade'><p>";
1419
- _e( 'Saved Options!', 'post-expirator' );
1420
- echo '</p></div>';
1421
- }
1422
- }
1423
-
1424
- ?>
1425
- <form method="post">
1426
- <?php wp_nonce_field( 'postexpirator_menu_defaults', '_postExpiratorMenuDefaults_nonce' ); ?>
1427
- <h3><?php _e( 'Default Expiration Values', 'post-expirator' ); ?></h3>
1428
- <p>
1429
- <?php _e( 'Use the values below to set the default actions/values to be used for each for the corresponding post types. These values can all be overwritten when creating/editing the post/page.', 'post-expirator' ); ?>
1430
- </p>
1431
- <?php
1432
- foreach ( $types as $type ) {
1433
- echo "<fieldset style='border: 1px solid black; border-radius: 6px; padding: 0px 12px; margin-bottom: 20px;'>";
1434
- echo "<legend>Post Type: $type</legend>";
1435
- $defaults = get_option( 'expirationdateDefaults' . ucfirst( $type ) );
1436
-
1437
- // phpcs:ignore WordPress.PHP.StrictComparisons.LooseComparison
1438
- if ( isset( $defaults['autoEnable'] ) && $defaults['autoEnable'] == 1 ) {
1439
- $expiredautoenabled = 'checked = "checked"';
1440
- $expiredautodisabled = '';
1441
- } else {
1442
- $expiredautoenabled = '';
1443
- $expiredautodisabled = 'checked = "checked"';
1444
- }
1445
- if ( isset( $defaults['activeMetaBox'] ) && $defaults['activeMetaBox'] === 'inactive' ) {
1446
- $expiredactivemetaenabled = '';
1447
- $expiredactivemetadisabled = 'checked = "checked"';
1448
- } else {
1449
- $expiredactivemetaenabled = 'checked = "checked"';
1450
- $expiredactivemetadisabled = '';
1451
- }
1452
- if ( ! isset( $defaults['taxonomy'] ) ) {
1453
- $defaults['taxonomy'] = false;
1454
- }
1455
- if ( ! isset( $defaults['emailnotification'] ) ) {
1456
- $defaults['emailnotification'] = '';
1457
- }
1458
- ?>
1459
- <table class="form-table">
1460
- <tr valign="top">
1461
- <th scope="row"><label for="expirationdate_activemeta-<?php echo $type; ?>"><?php _e( 'Active:', 'post-expirator' ); ?></label></th>
1462
- <td>
1463
- <input type="radio" name="expirationdate_activemeta-<?php echo $type; ?>" id="expirationdate_activemeta-true-<?php echo $type; ?>" value="active" <?php echo $expiredactivemetaenabled; ?>/> <label for="expired-active-meta-true"><?php _e( 'Active', 'post-expirator' ); ?></label>
1464
- <br/>
1465
- <input type="radio" name="expirationdate_activemeta-<?php echo $type; ?>" id="expirationdate_activemeta-false-<?php echo $type; ?>" value="inactive" <?php echo $expiredactivemetadisabled; ?>/> <label for="expired-active-meta-false"><?php _e( 'Inactive', 'post-expirator' ); ?></label>
1466
- <br/>
1467
- <?php _e( 'Select whether the post expirator meta box is active for this post type.', 'post-expirator' ); ?>
1468
- </td>
1469
- </tr>
1470
- <tr valign="top">
1471
- <th scope="row"><label for="expirationdate_expiretype-<?php echo $type; ?>"><?php _e( 'How to expire:', 'post-expirator' ); ?></label></th>
1472
- <td>
1473
- <?php echo _postexpirator_expire_type( array('name' => 'expirationdate_expiretype-' . $type, 'selected' => $defaults['expireType']) ); ?>
1474
- </select>
1475
- <br/>
1476
- <?php _e( 'Select the default expire action for the post type.', 'post-expirator' ); ?>
1477
- </td>
1478
- </tr>
1479
- <tr valign="top">
1480
- <th scope="row"><label for="expirationdate_autoenable-<?php echo $type; ?>"><?php _e( 'Auto-Enable?', 'post-expirator' ); ?></label></th>
1481
- <td>
1482
- <input type="radio" name="expirationdate_autoenable-<?php echo $type; ?>" id="expirationdate_autoenable-true-<?php echo $type; ?>" value="1" <?php echo $expiredautoenabled; ?>/> <label for="expired-auto-enable-true"><?php _e( 'Enabled', 'post-expirator' ); ?></label>
1483
- <br/>
1484
- <input type="radio" name="expirationdate_autoenable-<?php echo $type; ?>" id="expirationdate_autoenable-false-<?php echo $type; ?>" value="0" <?php echo $expiredautodisabled; ?>/> <label for="expired-auto-enable-false"><?php _e( 'Disabled', 'post-expirator' ); ?></label>
1485
- <br/>
1486
- <?php _e( 'Select whether the post expirator is enabled for all new posts.', 'post-expirator' ); ?>
1487
- </td>
1488
- </tr>
1489
- <tr valign="top">
1490
- <th scope="row"><label for="expirationdate_taxonomy-<?php echo $type; ?>"><?php _e( 'Taxonomy (hierarchical):', 'post-expirator' ); ?></label></th>
1491
- <td>
1492
- <?php echo _postexpirator_taxonomy( array('type' => $type, 'name' => 'expirationdate_taxonomy-' . $type, 'selected' => $defaults['taxonomy']) ); ?>
1493
- </td>
1494
- </tr>
1495
- <tr valign="top">
1496
- <th scope="row"><label for="expirationdate_emailnotification-<?php echo $type; ?>"><?php _e( 'Who to notify:', 'post-expirator' ); ?></label></th>
1497
- <td>
1498
- <input class="large-text" type="text" name="expirationdate_emailnotification-<?php echo $type; ?>" id="expirationdate_emailnotification-<?php echo $type; ?>" value="<?php echo $defaults['emailnotification']; ?>" />
1499
- <br/>
1500
- <?php _e( 'Enter a comma seperate list of emails that you would like to be notified when the post expires.', 'post-expirator' ); ?>
1501
- </td>
1502
- </tr>
1503
-
1504
- </table>
1505
- </fieldset>
1506
- <?php
1507
- }
1508
- ?>
1509
- <p class="submit">
1510
- <input type="submit" name="expirationdateSaveDefaults" class="button-primary" value="<?php _e( 'Save Changes', 'post-expirator' ); ?>" />
1511
- </p>
1512
- </form>
1513
- <?php
1514
- }
1515
-
1516
- /**
1517
- * Diagnostics menu.
1518
- *
1519
- * @internal
1520
- *
1521
- * @access private
1522
- */
1523
- function postexpirator_menu_diagnostics() {
1524
- if ( $_SERVER['REQUEST_METHOD'] === 'POST' ) {
1525
- if ( ! isset( $_POST['_postExpiratorMenuDiagnostics_nonce'] ) || ! wp_verify_nonce( $_POST['_postExpiratorMenuDiagnostics_nonce'], 'postexpirator_menu_diagnostics' ) ) {
1526
- print 'Form Validation Failure: Sorry, your nonce did not verify.';
1527
- exit;
1528
- }
1529
- if ( isset( $_POST['debugging-disable'] ) ) {
1530
- update_option( 'expirationdateDebug', 0 );
1531
- echo "<div id='message' class='updated fade'><p>";
1532
- _e( 'Debugging Disabled', 'post-expirator' );
1533
- echo '</p></div>';
1534
- } elseif ( isset( $_POST['debugging-enable'] ) ) {
1535
- update_option( 'expirationdateDebug', 1 );
1536
- echo "<div id='message' class='updated fade'><p>";
1537
- _e( 'Debugging Enabled', 'post-expirator' );
1538
- echo '</p></div>';
1539
- } elseif ( isset( $_POST['purge-debug'] ) ) {
1540
- require_once( plugin_dir_path( __FILE__ ) . 'post-expirator-debug.php' );
1541
- $debug = new PostExpiratorDebug();
1542
- $debug->purge();
1543
- echo "<div id='message' class='updated fade'><p>";
1544
- _e( 'Debugging Table Emptied', 'post-expirator' );
1545
- echo '</p></div>';
1546
- }
1547
- }
1548
-
1549
- $debug = postexpirator_debug();
1550
- ?>
1551
- <form method="post" id="postExpiratorMenuUpgrade">
1552
- <?php wp_nonce_field( 'postexpirator_menu_diagnostics', '_postExpiratorMenuDiagnostics_nonce' ); ?>
1553
- <h3><?php _e( 'Advanced Diagnostics', 'post-expirator' ); ?></h3>
1554
- <table class="form-table">
1555
- <tr valign="top">
1556
- <th scope="row"><label for="postexpirator-log"><?php _e( 'Post Expirator Debug Logging:', 'post-expirator' ); ?></label></th>
1557
- <td>
1558
- <?php
1559
- if ( POSTEXPIRATOR_DEBUG ) {
1560
- echo __( 'Status: Enabled', 'post-expirator' ) . '<br/>';
1561
- echo '<input type="submit" class="button" name="debugging-disable" id="debugging-disable" value="' . __( 'Disable Debugging', 'post-expirator' ) . '" />';
1562
- } else {
1563
- echo __( 'Status: Disabled', 'post-expirator' ) . '<br/>';
1564
- echo '<input type="submit" class="button" name="debugging-enable" id="debugging-enable" value="' . __( 'Enable Debugging', 'post-expirator' ) . '" />';
1565
- }
1566
- ?>
1567
- <br/>
1568
- <a href="<?php echo admin_url( 'options-general.php?page=post-expirator.php&tab=viewdebug' ); ?>">View Debug Logs</a>
1569
- </td>
1570
- </tr>
1571
- <tr valign="top">
1572
- <th scope="row"><?php _e( 'Purge Debug Log:', 'post-expirator' ); ?></th>
1573
- <td>
1574
- <input type="submit" class="button" name="purge-debug" id="purge-debug" value="<?php _e( 'Purge Debug Log', 'post-expirator' ); ?>" />
1575
- </td>
1576
- </tr/>
1577
- <tr valign="top">
1578
- <th scope="row"><?php _e( 'WP-Cron Status:', 'post-expirator' ); ?></th>
1579
- <td>
1580
- <?php
1581
- if ( defined( 'DISABLE_WP_CRON' ) && DISABLE_WP_CRON === true ) {
1582
- _e( 'DISABLED', 'post-expirator' );
1583
- } else {
1584
- _e( 'ENABLED - OK', 'post-expirator' );
1585
- }
1586
- ?>
1587
- </td>
1588
- </tr/>
1589
- <tr valign="top">
1590
- <th scope="row"><label for="cron-schedule"><?php _e( 'Current Cron Schedule:', 'post-expirator' ); ?></label></th>
1591
- <td>
1592
- <?php _e( 'The below table will show all currently scheduled cron events with the next run time.', 'post-expirator' ); ?><br/>
1593
- <table>
1594
- <tr>
1595
- <th style="width: 200px;"><?php _e( 'Date', 'post-expirator' ); ?></th>
1596
- <th style="width: 200px;"><?php _e( 'Event', 'post-expirator' ); ?></th>
1597
- <th style="width: 500px;"><?php _e( 'Arguments / Schedule', 'post-expirator' ); ?></th>
1598
- </tr>
1599
- <?php
1600
- $cron = _get_cron_array();
1601
- foreach ( $cron as $key => $value ) {
1602
- foreach ( $value as $eventkey => $eventvalue ) {
1603
- print '<tr>';
1604
- print '<td>' . date_i18n( 'r', $key ) . '</td>';
1605
- print '<td>' . $eventkey . '</td>';
1606
- $arrkey = array_keys( $eventvalue );
1607
- print '<td>';
1608
- foreach ( $arrkey as $eventguid ) {
1609
- print '<table><tr>';
1610
- if ( empty( $eventvalue[ $eventguid ]['args'] ) ) {
1611
- print '<td>No Arguments</td>';
1612
- } else {
1613
- print '<td>';
1614
- $args = array();
1615
- foreach ( $eventvalue[ $eventguid ]['args'] as $key => $value ) {
1616
- $args[] = "$key => $value";
1617
- }
1618
- print implode( "<br/>\n", $args );
1619
- print '</td>';
1620
- }
1621
- if ( empty( $eventvalue[ $eventguid ]['schedule'] ) ) {
1622
- print '<td>' . __( 'Single Event', 'post-expirator' ) . '</td>';
1623
- } else {
1624
- print '<td>' . $eventvalue[ $eventguid ]['schedule'] . ' (' . $eventvalue[ $eventguid ]['interval'] . ')</td>';
1625
- }
1626
- print '</tr></table>';
1627
- }
1628
- print '</td>';
1629
- print '</tr>';
1630
- }
1631
- }
1632
- ?>
1633
- </table>
1634
- </td>
1635
- </tr>
1636
- </table>
1637
- </form>
1638
- <?php
1639
- }
1640
-
1641
- /**
1642
- * Debug menu.
1643
- *
1644
- * @internal
1645
- *
1646
- * @access private
1647
- */
1648
- function postexpirator_menu_debug() {
1649
- require_once( plugin_dir_path( __FILE__ ) . 'post-expirator-debug.php' );
1650
- print '<p>' . __( 'Below is a dump of the debugging table, this should be useful for troubleshooting.', 'post-expirator' ) . '</p>';
1651
- $debug = new PostExpiratorDebug();
1652
- $debug->getTable();
1653
- }
1654
-
1655
- /**
1656
- * Register the shortcode.
1657
- *
1658
- * @internal
1659
- *
1660
- * @access private
1661
- */
1662
- function postexpirator_shortcode( $atts ) {
1663
- global $post;
1664
-
1665
- $expirationdatets = get_post_meta( $post->ID, '_expiration-date', true );
1666
- if ( empty( $expirationdatets ) ) {
1667
- return false;
1668
- }
1669
-
1670
- // @TODO remove extract
1671
- // phpcs:ignore WordPress.PHP.DontExtract.extract_extract
1672
- extract(
1673
- shortcode_atts(
1674
- array(
1675
- 'dateformat' => get_option( 'expirationdateDefaultDateFormat', POSTEXPIRATOR_DATEFORMAT ),
1676
- 'timeformat' => get_option( 'expirationdateDefaultTimeFormat', POSTEXPIRATOR_TIMEFORMAT ),
1677
- 'type' => 'full',
1678
- 'tz' => date( 'T' ),
1679
- ), $atts
1680
- )
1681
- );
1682
-
1683
- if ( empty( $dateformat ) ) {
1684
- global $expirationdateDefaultDateFormat;
1685
- $dateformat = $expirationdateDefaultDateFormat;
1686
- }
1687
-
1688
- if ( empty( $timeformat ) ) {
1689
- global $expirationdateDefaultTimeFormat;
1690
- $timeformat = $expirationdateDefaultTimeFormat;
1691
- }
1692
-
1693
- if ( $type === 'full' ) {
1694
- $format = $dateformat . ' ' . $timeformat;
1695
- } elseif ( $type === 'date' ) {
1696
- $format = $dateformat;
1697
- } elseif ( $type === 'time' ) {
1698
- $format = $timeformat;
1699
- }
1700
-
1701
- return date_i18n( $format, $expirationdatets + ( get_option( 'gmt_offset' ) * HOUR_IN_SECONDS ) );
1702
- }
1703
- add_shortcode( 'postexpirator', 'postexpirator_shortcode' );
1704
-
1705
- /**
1706
- * Add the footer.
1707
- *
1708
- * @internal
1709
- *
1710
- * @access private
1711
- */
1712
- function postexpirator_add_footer( $text ) {
1713
- global $post;
1714
-
1715
- // Check to see if its enabled
1716
- $displayFooter = get_option( 'expirationdateDisplayFooter' );
1717
-
1718
- // phpcs:ignore WordPress.PHP.StrictComparisons.LooseComparison
1719
- if ( $displayFooter === false || $displayFooter == 0 ) {
1720
- return $text;
1721
- }
1722
-
1723
- $expirationdatets = get_post_meta( $post->ID, '_expiration-date', true );
1724
- if ( ! is_numeric( $expirationdatets ) ) {
1725
- return $text;
1726
- }
1727
-
1728
- $dateformat = get_option( 'expirationdateDefaultDateFormat', POSTEXPIRATOR_DATEFORMAT );
1729
- $timeformat = get_option( 'expirationdateDefaultTimeFormat', POSTEXPIRATOR_TIMEFORMAT );
1730
- $expirationdateFooterContents = get_option( 'expirationdateFooterContents', POSTEXPIRATOR_FOOTERCONTENTS );
1731
- $expirationdateFooterStyle = get_option( 'expirationdateFooterStyle', POSTEXPIRATOR_FOOTERSTYLE );
1732
-
1733
- $search = array(
1734
- 'EXPIRATIONFULL',
1735
- 'EXPIRATIONDATE',
1736
- 'EXPIRATIONTIME',
1737
- );
1738
- $replace = array(
1739
- get_date_from_gmt( gmdate( 'Y-m-d H:i:s', $expirationdatets ), "$dateformat $timeformat" ),
1740
- get_date_from_gmt( gmdate( 'Y-m-d H:i:s', $expirationdatets ), $dateformat ),
1741
- get_date_from_gmt( gmdate( 'Y-m-d H:i:s', $expirationdatets ), $timeformat ),
1742
- );
1743
-
1744
- $add_to_footer = '<p style="' . $expirationdateFooterStyle . '">' . str_replace( $search, $replace, $expirationdateFooterContents ) . '</p>';
1745
- return $text . $add_to_footer;
1746
- }
1747
- add_action( 'the_content', 'postexpirator_add_footer', 0 );
1748
-
1749
- /**
1750
- * Check for Debug
1751
- *
1752
- * @internal
1753
- *
1754
- * @access private
1755
- */
1756
- function postexpirator_debug() {
1757
- $debug = get_option( 'expirationdateDebug' );
1758
- // phpcs:ignore WordPress.PHP.StrictComparisons.LooseComparison
1759
- if ( $debug == 1 ) {
1760
- if ( ! defined( 'POSTEXPIRATOR_DEBUG' ) ) {
1761
- define( 'POSTEXPIRATOR_DEBUG', 1 );
1762
- }
1763
- require_once( plugin_dir_path( __FILE__ ) . 'post-expirator-debug.php' ); // Load Class
1764
- return new PostExpiratorDebug();
1765
- } else {
1766
- if ( ! defined( 'POSTEXPIRATOR_DEBUG' ) ) {
1767
- define( 'POSTEXPIRATOR_DEBUG', 0 );
1768
- }
1769
- return false;
1770
- }
1771
- }
1772
-
1773
-
1774
- /**
1775
- * Add Stylesheet
1776
- *
1777
- * @internal
1778
- *
1779
- * @access private
1780
- */
1781
- function postexpirator_css( $screen_id ) {
1782
- switch ( $screen_id ) {
1783
- case 'post.php':
1784
- case 'post-new.php':
1785
- case 'settings_page_post-expirator':
1786
- wp_enqueue_style( 'postexpirator-css', POSTEXPIRATOR_BASEURL . '/assets/css/style.css', array(), POSTEXPIRATOR_VERSION );
1787
- break;
1788
- case 'edit.php':
1789
- wp_enqueue_style( 'postexpirator-edit', POSTEXPIRATOR_BASEURL . '/assets/css/edit.css', array(), POSTEXPIRATOR_VERSION );
1790
- break;
1791
- }
1792
- }
1793
- add_action( 'admin_enqueue_scripts', 'postexpirator_css', 10, 1 );
1794
-
1795
- /**
1796
- * Post Expirator Activation/Upgrade
1797
- *
1798
- * @internal
1799
- *
1800
- * @access private
1801
- */
1802
- function postexpirator_upgrade() {
1803
-
1804
- // Check for current version, if not exists, run activation
1805
- $version = get_option( 'postexpiratorVersion' );
1806
- if ( $version === false ) { // not installed, run default activation
1807
- postexpirator_activate();
1808
- update_option( 'postexpiratorVersion', POSTEXPIRATOR_VERSION );
1809
- } else {
1810
- if ( version_compare( $version, '1.6.1' ) === -1 ) {
1811
- update_option( 'postexpiratorVersion', POSTEXPIRATOR_VERSION );
1812
- update_option( 'expirationdateDefaultDate', POSTEXPIRATOR_EXPIREDEFAULT );
1813
- }
1814
-
1815
- if ( version_compare( $version, '1.6.2' ) === -1 ) {
1816
- update_option( 'postexpiratorVersion', POSTEXPIRATOR_VERSION );
1817
- }
1818
-
1819
- if ( version_compare( $version, '2.0.0-rc1' ) === -1 ) {
1820
- global $wpdb;
1821
-
1822
- // Schedule Events/Migrate Config
1823
- $results = $wpdb->get_results( $wpdb->prepare( 'select post_id, meta_value from ' . $wpdb->postmeta . ' as postmeta, ' . $wpdb->posts . ' as posts where postmeta.post_id = posts.ID AND postmeta.meta_key = %s AND postmeta.meta_value >= %d', 'expiration-date', time() ) );
1824
- foreach ( $results as $result ) {
1825
- wp_schedule_single_event( $result->meta_value, 'postExpiratorExpire', array($result->post_id) );
1826
- $opts = array();
1827
- $opts['id'] = $result->post_id;
1828
- $posttype = get_post_type( $result->post_id );
1829
- if ( $posttype === 'page' ) {
1830
- $opts['expireType'] = strtolower( get_option( 'expirationdateExpiredPageStatus', 'Draft' ) );
1831
- } else {
1832
- $opts['expireType'] = strtolower( get_option( 'expirationdateExpiredPostStatus', 'Draft' ) );
1833
- }
1834
-
1835
- $cat = get_post_meta( $result->post_id, '_expiration-date-category', true );
1836
- if ( ( isset( $cat ) && ! empty( $cat ) ) ) {
1837
- $opts['category'] = $cat;
1838
- $opts['expireType'] = 'category';
1839
- }
1840
- update_post_meta( $result->post_id, '_expiration-date-options', $opts );
1841
- }
1842
-
1843
- // update meta key to new format
1844
- $wpdb->query( $wpdb->prepare( "UPDATE $wpdb->postmeta SET meta_key = %s WHERE meta_key = %s", '_expiration-date', 'expiration-date' ) );
1845
-
1846
- // migrate defaults
1847
- $pagedefault = get_option( 'expirationdateExpiredPageStatus' );
1848
- $postdefault = get_option( 'expirationdateExpiredPostStatus' );
1849
- if ( $pagedefault ) {
1850
- update_option( 'expirationdateDefaultsPage', array('expireType' => $pagedefault) );
1851
- }
1852
- if ( $postdefault ) {
1853
- update_option( 'expirationdateDefaultsPost', array('expireType' => $postdefault) );
1854
- }
1855
-
1856
- delete_option( 'expirationdateCronSchedule' );
1857
- delete_option( 'expirationdateAutoEnabled' );
1858
- delete_option( 'expirationdateExpiredPageStatus' );
1859
- delete_option( 'expirationdateExpiredPostStatus' );
1860
- update_option( 'postexpiratorVersion', POSTEXPIRATOR_VERSION );
1861
- }
1862
-
1863
- if ( version_compare( $version, '2.0.1' ) === -1 ) {
1864
- // Forgot to do this in 2.0.0
1865
- if ( is_multisite() ) {
1866
- global $current_blog;
1867
- wp_clear_scheduled_hook( 'expirationdate_delete_' . $current_blog->blog_id );
1868
- } else {
1869
- wp_clear_scheduled_hook( 'expirationdate_delete' );
1870
- }
1871
-
1872
- update_option( 'postexpiratorVersion', POSTEXPIRATOR_VERSION );
1873
- }
1874
-
1875
- update_option( 'postexpiratorVersion', POSTEXPIRATOR_VERSION );
1876
-
1877
- }
1878
- }
1879
- add_action( 'admin_init', 'postexpirator_upgrade' );
1880
-
1881
- /**
1882
- * Called at plugin activation
1883
- *
1884
- * @internal
1885
- *
1886
- * @access private
1887
- */
1888
- function postexpirator_activate() {
1889
- if ( get_option( 'expirationdateDefaultDateFormat' ) === false ) {
1890
- update_option( 'expirationdateDefaultDateFormat', POSTEXPIRATOR_DATEFORMAT );
1891
- }
1892
- if ( get_option( 'expirationdateDefaultTimeFormat' ) === false ) {
1893
- update_option( 'expirationdateDefaultTimeFormat', POSTEXPIRATOR_TIMEFORMAT );
1894
- }
1895
- if ( get_option( 'expirationdateFooterContents' ) === false ) {
1896
- update_option( 'expirationdateFooterContents', POSTEXPIRATOR_FOOTERCONTENTS );
1897
- }
1898
- if ( get_option( 'expirationdateFooterStyle' ) === false ) {
1899
- update_option( 'expirationdateFooterStyle', POSTEXPIRATOR_FOOTERSTYLE );
1900
- }
1901
- if ( get_option( 'expirationdateDisplayFooter' ) === false ) {
1902
- update_option( 'expirationdateDisplayFooter', POSTEXPIRATOR_FOOTERDISPLAY );
1903
- }
1904
- if ( get_option( 'expirationdateDebug' ) === false ) {
1905
- update_option( 'expirationdateDebug', POSTEXPIRATOR_DEBUGDEFAULT );
1906
- }
1907
- if ( get_option( 'expirationdateDefaultDate' ) === false ) {
1908
- update_option( 'expirationdateDefaultDate', POSTEXPIRATOR_EXPIREDEFAULT );
1909
- }
1910
- }
1911
-
1912
- /**
1913
- * Called at plugin deactivation
1914
- *
1915
- * @internal
1916
- *
1917
- * @access private
1918
- */
1919
- function expirationdate_deactivate() {
1920
- global $current_blog;
1921
- delete_option( 'expirationdateExpiredPostStatus' );
1922
- delete_option( 'expirationdateExpiredPageStatus' );
1923
- delete_option( 'expirationdateDefaultDateFormat' );
1924
- delete_option( 'expirationdateDefaultTimeFormat' );
1925
- delete_option( 'expirationdateDisplayFooter' );
1926
- delete_option( 'expirationdateFooterContents' );
1927
- delete_option( 'expirationdateFooterStyle' );
1928
- delete_option( 'expirationdateCategory' );
1929
- delete_option( 'expirationdateCategoryDefaults' );
1930
- delete_option( 'expirationdateDebug' );
1931
- delete_option( 'postexpiratorVersion' );
1932
- delete_option( 'expirationdateCronSchedule' );
1933
- delete_option( 'expirationdateDefaultDate' );
1934
- delete_option( 'expirationdateDefaultDateCustom' );
1935
- delete_option( 'expirationdateAutoEnabled' );
1936
- delete_option( 'expirationdateDefaultsPage' );
1937
- delete_option( 'expirationdateDefaultsPost' );
1938
- // what about custom post types? - how to cleanup?
1939
- if ( is_multisite() ) {
1940
- wp_clear_scheduled_hook( 'expirationdate_delete_' . $current_blog->blog_id );
1941
- } else {
1942
- wp_clear_scheduled_hook( 'expirationdate_delete' );
1943
- }
1944
- require_once( plugin_dir_path( __FILE__ ) . 'post-expirator-debug.php' );
1945
- $debug = new PostExpiratorDebug();
1946
- $debug->removeDbTable();
1947
- }
1948
- register_deactivation_hook( __FILE__, 'expirationdate_deactivate' );
1949
-
1950
- /**
1951
- * The walker class for category checklist.
1952
- *
1953
- * @internal
1954
- *
1955
- * @access private
1956
- */
1957
- class Walker_PostExpirator_Category_Checklist extends Walker {
1958
-
1959
- /**
1960
- * What the class handles.
1961
- *
1962
- * @var string
1963
- */
1964
- var $tree_type = 'category';
1965
-
1966
- /**
1967
- * DB fields to use.
1968
- *
1969
- * @var array
1970
- */
1971
- var $db_fields = array ('parent' => 'parent', 'id' => 'term_id'); // TODO: decouple this
1972
-
1973
- /**
1974
- * The disabled attribute.
1975
- *
1976
- * @var string
1977
- */
1978
- var $disabled = '';
1979
-
1980
- /**
1981
- * Set the disabled attribute.
1982
- */
1983
- function setDisabled() {
1984
- $this->disabled = 'disabled="disabled"';
1985
- }
1986
-
1987
- /**
1988
- * Starts the list before the elements are added.
1989
- *
1990
- * The $args parameter holds additional values that may be used with the child
1991
- * class methods. This method is called at the start of the output list.
1992
- *
1993
- * @param string $output Used to append additional content (passed by reference).
1994
- * @param int $depth Depth of the item.
1995
- * @param array $args An array of additional arguments.
1996
- */
1997
- function start_lvl( &$output, $depth = 0, $args = array() ) {
1998
- $indent = str_repeat( "\t", $depth );
1999
- $output .= "$indent<ul class='children'>\n";
2000
- }
2001
-
2002
- /**
2003
- * Ends the list of after the elements are added.
2004
- *
2005
- * The $args parameter holds additional values that may be used with the child
2006
- * class methods. This method finishes the list at the end of output of the elements.
2007
- *
2008
- * @param string $output Used to append additional content (passed by reference).
2009
- * @param int $depth Depth of the item.
2010
- * @param array $args An array of additional arguments.
2011
- */
2012
- function end_lvl( &$output, $depth = 0, $args = array() ) {
2013
- $indent = str_repeat( "\t", $depth );
2014
- $output .= "$indent</ul>\n";
2015
- }
2016
-
2017
- /**
2018
- * Start the element output.
2019
- *
2020
- * The $args parameter holds additional values that may be used with the child
2021
- * class methods. Includes the element output also.
2022
- *
2023
- * @param string $output Used to append additional content (passed by reference).
2024
- * @param object $category The data object.
2025
- * @param int $depth Depth of the item.
2026
- * @param array $args An array of additional arguments.
2027
- * @param int $current_object_id ID of the current item.
2028
- */
2029
- function start_el( &$output, $category, $depth = 0, $args = array(), $current_object_id = 0 ) {
2030
- // @TODO remove extract
2031
- // phpcs:ignore WordPress.PHP.DontExtract.extract_extract
2032
- extract( $args );
2033
- if ( empty( $taxonomy ) ) {
2034
- $taxonomy = 'category';
2035
- }
2036
-
2037
- $name = 'expirationdate_category';
2038
-
2039
- $class = in_array( $category->term_id, $popular_cats, true ) ? ' class="expirator-category"' : '';
2040
- $output .= "\n<li id='expirator-{$taxonomy}-{$category->term_id}'$class>" . '<label class="selectit"><input value="' . $category->term_id . '" type="checkbox" name="' . $name . '[]" id="expirator-in-' . $taxonomy . '-' . $category->term_id . '"' . checked( in_array( $category->term_id, $selected_cats, true ), true, false ) . disabled( empty( $args['disabled'] ), false, false ) . ' ' . $this->disabled . '/> ' . esc_html( apply_filters( 'the_category', $category->name ) ) . '</label>';
2041
- }
2042
-
2043
- /**
2044
- * Ends the element output, if needed.
2045
- *
2046
- * The $args parameter holds additional values that may be used with the child class methods.
2047
- *
2048
- * @param string $output Used to append additional content (passed by reference).
2049
- * @param object $category The data object.
2050
- * @param int $depth Depth of the item.
2051
- * @param array $args An array of additional arguments.
2052
- */
2053
- function end_el( &$output, $category, $depth = 0, $args = array() ) {
2054
- $output .= "</li>\n";
2055
- }
2056
- }
2057
-
2058
- /**
2059
- * Get the HTML for expire type.
2060
- *
2061
- * @internal
2062
- *
2063
- * @access private
2064
- */
2065
- function _postexpirator_expire_type( $opts ) {
2066
- if ( empty( $opts ) ) {
2067
- return false;
2068
- }
2069
-
2070
- // @TODO remove extract
2071
- // phpcs:ignore WordPress.PHP.DontExtract.extract_extract
2072
- extract( $opts );
2073
-
2074
- if ( ! isset( $name ) ) {
2075
- return false;
2076
- }
2077
- if ( ! isset( $id ) ) {
2078
- $id = $name;
2079
- }
2080
- if ( ! isset( $disabled ) ) {
2081
- $disabled = false;
2082
- }
2083
- if ( ! isset( $onchange ) ) {
2084
- $onchange = '';
2085
- }
2086
- if ( ! isset( $type ) ) {
2087
- $type = '';
2088
- }
2089
-
2090
- $rv = array();
2091
- // phpcs:ignore WordPress.PHP.StrictComparisons.LooseComparison
2092
- $rv[] = '<select name="' . $name . '" id="' . $id . '"' . ( $disabled == true ? ' disabled="disabled"' : '' ) . ' onchange="' . $onchange . '">';
2093
- $rv[] = '<option value="draft" ' . ( $selected === 'draft' ? 'selected="selected"' : '' ) . '>' . __( 'Draft', 'post-expirator' ) . '</option>';
2094
- $rv[] = '<option value="delete" ' . ( $selected === 'delete' ? 'selected="selected"' : '' ) . '>' . __( 'Delete', 'post-expirator' ) . '</option>';
2095
- $rv[] = '<option value="trash" ' . ( $selected === 'trash' ? 'selected="selected"' : '' ) . '>' . __( 'Trash', 'post-expirator' ) . '</option>';
2096
- $rv[] = '<option value="private" ' . ( $selected === 'private' ? 'selected="selected"' : '' ) . '>' . __( 'Private', 'post-expirator' ) . '</option>';
2097
- $rv[] = '<option value="stick" ' . ( $selected === 'stick' ? 'selected="selected"' : '' ) . '>' . __( 'Stick', 'post-expirator' ) . '</option>';
2098
- $rv[] = '<option value="unstick" ' . ( $selected === 'unstick' ? 'selected="selected"' : '' ) . '>' . __( 'Unstick', 'post-expirator' ) . '</option>';
2099
- if ( $type !== 'page' ) {
2100
- $rv[] = '<option value="category" ' . ( $selected === 'category' ? 'selected="selected"' : '' ) . '>' . __( 'Category: Replace', 'post-expirator' ) . '</option>';
2101
- $rv[] = '<option value="category-add" ' . ( $selected === 'category-add' ? 'selected="selected"' : '' ) . '>' . __( 'Category: Add', 'post-expirator' ) . '</option>';
2102
- $rv[] = '<option value="category-remove" ' . ( $selected === 'category-remove' ? 'selected="selected"' : '' ) . '>' . __( 'Category: Remove', 'post-expirator' ) . '</option>';
2103
- }
2104
- $rv[] = '</select>';
2105
- return implode( "<br/>\n", $rv );
2106
- }
2107
-
2108
- /**
2109
- * Get the HTML for taxonomy.
2110
- *
2111
- * @internal
2112
- *
2113
- * @access private
2114
- */
2115
- function _postexpirator_taxonomy( $opts ) {
2116
- if ( empty( $opts ) ) {
2117
- return false;
2118
- }
2119
-
2120
- // @TODO remove extract
2121
- // phpcs:ignore WordPress.PHP.DontExtract.extract_extract
2122
- extract( $opts );
2123
- if ( ! isset( $name ) ) {
2124
- return false;
2125
- }
2126
- if ( ! isset( $id ) ) {
2127
- $id = $name;
2128
- }
2129
- if ( ! isset( $disabled ) ) {
2130
- $disabled = false;
2131
- }
2132
- if ( ! isset( $onchange ) ) {
2133
- $onchange = '';
2134
- }
2135
- if ( ! isset( $type ) ) {
2136
- $type = '';
2137
- }
2138
-
2139
- $taxonomies = get_object_taxonomies( $type, 'object' );
2140
- $taxonomies = wp_filter_object_list( $taxonomies, array('hierarchical' => true) );
2141
-
2142
- if ( empty( $taxonomies ) ) {
2143
- $disabled = true;
2144
- }
2145
-
2146
- $rv = array();
2147
- if ( $taxonomies ) {
2148
- // phpcs:ignore WordPress.PHP.StrictComparisons.LooseComparison
2149
- $rv[] = '<select name="' . $name . '" id="' . $id . '"' . ( $disabled == true ? ' disabled="disabled"' : '' ) . ' onchange="' . $onchange . '">';
2150
- foreach ( $taxonomies as $taxonomy ) {
2151
- $rv[] = '<option value="' . $taxonomy->name . '" ' . ( $selected === $taxonomy->name ? 'selected="selected"' : '' ) . '>' . $taxonomy->name . '</option>';
2152
- }
2153
-
2154
- $rv[] = '</select>';
2155
- $rv[] = __( 'Select the hierarchical taxonomy to be used for "category" based expiration.', 'post-expirator' );
2156
- } else {
2157
- $rv[] = 'No taxonomies found for post type.';
2158
- }
2159
- return implode( "<br/>\n", $rv );
2160
- }
2161
-
2162
- /**
2163
- * Include the JS.
2164
- *
2165
- * @internal
2166
- *
2167
- * @access private
2168
- */
2169
- function postexpirator_quickedit_javascript() {
2170
- // if using code as plugin
2171
- wp_enqueue_script( 'postexpirator-edit', POSTEXPIRATOR_BASEURL . '/admin-edit.js', array( 'jquery', 'inline-edit-post' ), POSTEXPIRATOR_VERSION, true );
2172
- wp_localize_script(
2173
- 'postexpirator-edit', 'config', array(
2174
- 'ajax' => array(
2175
- 'nonce' => wp_create_nonce( POSTEXPIRATOR_SLUG ),
2176
- 'bulk_edit' => 'manage_wp_posts_using_bulk_quick_save_bulk_edit',
2177
- ),
2178
- )
2179
- );
2180
- }
2181
- add_action( 'admin_print_scripts-edit.php', 'postexpirator_quickedit_javascript' );
2182
-
2183
- /**
2184
- * Receives AJAX call from bulk edit to process save.
2185
- *
2186
- * @internal
2187
- *
2188
- * @access private
2189
- */
2190
- function postexpirator_date_save_bulk_edit() {
2191
- check_ajax_referer( POSTEXPIRATOR_SLUG, 'nonce' );
2192
-
2193
- // we need the post IDs
2194
- $post_ids = ( isset( $_POST['post_ids'] ) && ! empty( $_POST['post_ids'] ) ) ? $_POST['post_ids'] : null;
2195
-
2196
- // if we have post IDs
2197
- if ( ! empty( $post_ids ) && is_array( $post_ids ) ) {
2198
-
2199
- $status = $_POST['expirationdate_status'];
2200
-
2201
- // if no change, do nothing
2202
- if ( $status === 'no-change' ) {
2203
- return;
2204
- }
2205
-
2206
- $month = intval( $_POST['expirationdate_month'] );
2207
- $day = intval( $_POST['expirationdate_day'] );
2208
- $year = intval( $_POST['expirationdate_year'] );
2209
- $hour = intval( $_POST['expirationdate_hour'] );
2210
- $minute = intval( $_POST['expirationdate_minute'] );
2211
-
2212
- // default to current date and/or year if not provided by user.
2213
- if ( empty( $day ) ) {
2214
- $day = date( 'd' );
2215
- }
2216
- if ( empty( $year ) ) {
2217
- $year = date( 'Y' );
2218
- }
2219
-
2220
- $ts = get_gmt_from_date( "$year-$month-$day $hour:$minute:0", 'U' );
2221
-
2222
- if ( ! $ts ) {
2223
- return;
2224
- }
2225
-
2226
- foreach ( $post_ids as $post_id ) {
2227
- $ed = get_post_meta( $post_id, '_expiration-date', true );
2228
- $update_expiry = false;
2229
-
2230
- switch ( $status ) {
2231
- case 'change-only':
2232
- $update_expiry = ! empty( $ed );
2233
- break;
2234
- case 'add-only':
2235
- $update_expiry = empty( $ed );
2236
- break;
2237
- case 'change-add':
2238
- $update_expiry = true;
2239
- break;
2240
- case 'remove-only':
2241
- delete_post_meta( $post_id, '_expiration-date' );
2242
- postexpirator_unschedule_event( $post_id );
2243
- break;
2244
- }
2245
-
2246
- if ( $update_expiry ) {
2247
- update_post_meta( $post_id, '_expiration-date', $ts );
2248
- postexpirator_schedule_event( $post_id, $ts, null );
2249
- }
2250
- }
2251
- }
2252
- }
2253
- add_action( 'wp_ajax_manage_wp_posts_using_bulk_quick_save_bulk_edit', 'postexpirator_date_save_bulk_edit' );
1
+ <?php
2
+ /*
3
+ Plugin Name: Post Expirator
4
+ Plugin URI: http://wordpress.org/extend/plugins/post-expirator/
5
+ Description: Allows you to add an expiration date (minute) to posts which you can configure to either delete the post, change it to a draft, or update the post categories at expiration time.
6
+ Author: Aaron Axelsen
7
+ Version: 2.5.0
8
+ Author URI: http://postexpirator.tuxdocs.net/
9
+ Text Domain: post-expirator
10
+ Domain Path: /languages
11
+ */
12
+
13
+ // Default Values
14
+ define( 'POSTEXPIRATOR_VERSION', '2.5.0' );
15
+ define( 'POSTEXPIRATOR_DATEFORMAT', __( 'l F jS, Y', 'post-expirator' ) );
16
+ define( 'POSTEXPIRATOR_TIMEFORMAT', __( 'g:ia', 'post-expirator' ) );
17
+ define( 'POSTEXPIRATOR_FOOTERCONTENTS', __( 'Post expires at EXPIRATIONTIME on EXPIRATIONDATE', 'post-expirator' ) );
18
+ define( 'POSTEXPIRATOR_FOOTERSTYLE', 'font-style: italic;' );
19
+ define( 'POSTEXPIRATOR_FOOTERDISPLAY', '0' );
20
+ define( 'POSTEXPIRATOR_EMAILNOTIFICATION', '0' );
21
+ define( 'POSTEXPIRATOR_EMAILNOTIFICATIONADMINS', '0' );
22
+ define( 'POSTEXPIRATOR_DEBUGDEFAULT', '0' );
23
+ define( 'POSTEXPIRATOR_EXPIREDEFAULT', 'null' );
24
+ define( 'POSTEXPIRATOR_SLUG', 'post-expirator' );
25
+ define( 'POSTEXPIRATOR_BASEDIR', dirname( __FILE__ ) );
26
+ define( 'POSTEXPIRATOR_BASENAME', basename( __FILE__ ) );
27
+ define( 'POSTEXPIRATOR_BASEURL', plugins_url( '/', __FILE__ ) );
28
+
29
+ require_once POSTEXPIRATOR_BASEDIR . '/functions.php';
30
+
31
+
32
+ /**
33
+ * Adds links to the plugin listing screen.
34
+ *
35
+ * @internal
36
+ *
37
+ * @access private
38
+ */
39
+ function postexpirator_plugin_action_links( $links, $file ) {
40
+ $this_plugin = basename( plugin_dir_url( __FILE__ ) ) . '/post-expirator.php';
41
+ if ( $file === $this_plugin ) {
42
+ $links[] = '<a href="options-general.php?page=post-expirator">' . __( 'Settings', 'post-expirator' ) . '</a>';
43
+ }
44
+ return $links;
45
+ }
46
+ add_filter( 'plugin_action_links', 'postexpirator_plugin_action_links', 10, 2 );
47
+
48
+ /**
49
+ * Load translation, if it exists.
50
+ *
51
+ * @internal
52
+ *
53
+ * @access private
54
+ */
55
+ function postexpirator_init() {
56
+ $plugin_dir = basename( dirname( __FILE__ ) );
57
+ load_plugin_textdomain( 'post-expirator', null, $plugin_dir . '/languages/' );
58
+ }
59
+ add_action( 'plugins_loaded', 'postexpirator_init' );
60
+
61
+ /**
62
+ * Adds an 'Expires' column to the post display table.
63
+ *
64
+ * @internal
65
+ *
66
+ * @access private
67
+ */
68
+ function postexpirator_add_column( $columns, $type ) {
69
+ $defaults = get_option( 'expirationdateDefaults' . ucfirst( $type ) );
70
+ // if settings are not configured, show the metabox by default only for posts and pages
71
+ if ( ( ! isset( $defaults['activeMetaBox'] ) && in_array( $type, array( 'post', 'page' ), true ) ) || $defaults['activeMetaBox'] === 'active' ) {
72
+ $columns['expirationdate'] = __( 'Expires', 'post-expirator' );
73
+ }
74
+ return $columns;
75
+ }
76
+ add_filter( 'manage_posts_columns', 'postexpirator_add_column', 10, 2 );
77
+
78
+ /**
79
+ * Adds sortable columns.
80
+ *
81
+ * @internal
82
+ *
83
+ * @access private
84
+ */
85
+ function postexpirator_manage_sortable_columns() {
86
+ $post_types = postexpirator_get_post_types();
87
+ foreach ( $post_types as $post_type ) {
88
+ add_filter( 'manage_edit-' . $post_type . '_sortable_columns', 'postexpirator_sortable_column' );
89
+ }
90
+ }
91
+ add_action( 'init', 'postexpirator_manage_sortable_columns', 100 );
92
+
93
+ /**
94
+ * Adds an 'Expires' column to the post display table.
95
+ *
96
+ * @internal
97
+ *
98
+ * @access private
99
+ */
100
+ function postexpirator_sortable_column( $columns ) {
101
+ $columns['expirationdate'] = 'expirationdate';
102
+ return $columns;
103
+ }
104
+
105
+ /**
106
+ * Modify the sorting of posts.
107
+ *
108
+ * @internal
109
+ *
110
+ * @access private
111
+ */
112
+ function postexpirator_orderby( $query ) {
113
+ if ( ! is_admin() ) {
114
+ return;
115
+ }
116
+
117
+ $orderby = $query->get( 'orderby' );
118
+
119
+ if ( 'expirationdate' === $orderby ) {
120
+ $query->set(
121
+ 'meta_query', array(
122
+ 'relation' => 'OR',
123
+ array(
124
+ 'key' => '_expiration-date',
125
+ 'compare' => 'EXISTS',
126
+ ),
127
+ array(
128
+ 'key' => '_expiration-date',
129
+ 'compare' => 'NOT EXISTS',
130
+ 'value' => '',
131
+ ),
132
+ )
133
+ );
134
+ $query->set( 'orderby', 'meta_value_num' );
135
+ }
136
+ }
137
+ add_action( 'pre_get_posts', 'postexpirator_orderby' );
138
+
139
+ /**
140
+ * Adds an 'Expires' column to the page display table.
141
+ *
142
+ * @internal
143
+ *
144
+ * @access private
145
+ */
146
+ function postexpirator_add_column_page( $columns ) {
147
+ $defaults = get_option( 'expirationdateDefaultsPage' );
148
+ if ( ! isset( $defaults['activeMetaBox'] ) || $defaults['activeMetaBox'] === 'active' ) {
149
+ $columns['expirationdate'] = __( 'Expires', 'post-expirator' );
150
+ }
151
+ return $columns;
152
+ }
153
+ add_filter( 'manage_pages_columns', 'postexpirator_add_column_page' );
154
+
155
+ /**
156
+ * Fills the 'Expires' column of the post display table.
157
+ *
158
+ * @internal
159
+ *
160
+ * @access private
161
+ */
162
+ function postexpirator_show_value( $column_name ) {
163
+ if ( $column_name !== 'expirationdate' ) {
164
+ return;
165
+ }
166
+
167
+ global $post;
168
+
169
+ // get the attributes that quick edit functionality requires
170
+ // and save it as a JSON encoded HTML attribute
171
+ $attributes = PostExpirator_Facade::get_expire_principles( $post->ID );
172
+ PostExpirator_Display::getInstance()->render_template( 'expire-column', array( 'id' => $post->ID, 'post_type' => $post->post_type, 'attributes' => $attributes ) );
173
+ }
174
+ add_action( 'manage_posts_custom_column', 'postexpirator_show_value' );
175
+ add_action( 'manage_pages_custom_column', 'postexpirator_show_value' );
176
+
177
+
178
+ /**
179
+ * Quick Edit functionality.
180
+ *
181
+ * @internal
182
+ *
183
+ * @access private
184
+ */
185
+ function postexpirator_quickedit( $column_name, $post_type ) {
186
+ if ( $column_name !== 'expirationdate' ) {
187
+ return;
188
+ }
189
+
190
+ $defaults = get_option( 'expirationdateDefaults' . ucfirst( $post_type ) );
191
+ $taxonomy = isset( $defaults['taxonomy'] ) ? $defaults['taxonomy'] : '';
192
+ $label = '';
193
+
194
+ // if settings have not been configured and this is the default post type
195
+ if ( empty( $taxonomy ) && 'post' === $post_type ) {
196
+ $taxonomy = 'category';
197
+ }
198
+
199
+ if ( ! empty( $taxonomy ) ) {
200
+ $tax_object = get_taxonomy( $taxonomy );
201
+ $label = $tax_object ? $tax_object->label : '';
202
+ }
203
+
204
+ PostExpirator_Display::getInstance()->render_template( 'quick-edit', array( 'post_type' => $post_type, 'taxonomy' => $taxonomy, 'tax_label' => $label ) );
205
+ }
206
+ add_action( 'quick_edit_custom_box', 'postexpirator_quickedit', 10, 2 );
207
+
208
+ /**
209
+ * Bulk Edit functionality.
210
+ *
211
+ * @internal
212
+ *
213
+ * @access private
214
+ */
215
+ function postexpirator_bulkedit( $column_name, $post_type ) {
216
+ if ( $column_name !== 'expirationdate' ) {
217
+ return;
218
+ }
219
+
220
+ $defaults = get_option( 'expirationdateDefaults' . ucfirst( $post_type ) );
221
+ $taxonomy = isset( $defaults['taxonomy'] ) ? $defaults['taxonomy'] : '';
222
+ $label = '';
223
+
224
+ // if settings have not been configured and this is the default post type
225
+ if ( empty( $taxonomy ) && 'post' === $post_type ) {
226
+ $taxonomy = 'category';
227
+ }
228
+
229
+ if ( ! empty( $taxonomy ) ) {
230
+ $tax_object = get_taxonomy( $taxonomy );
231
+ $label = $tax_object ? $tax_object->label : '';
232
+ }
233
+
234
+ PostExpirator_Display::getInstance()->render_template( 'bulk-edit', array( 'post_type' => $post_type, 'taxonomy' => $taxonomy, 'tax_label' => $label ) );
235
+ }
236
+ add_action( 'bulk_edit_custom_box', 'postexpirator_bulkedit', 10, 2 );
237
+
238
+ /**
239
+ * Returns the post types that are supported.
240
+ *
241
+ * @internal
242
+ *
243
+ * @access private
244
+ */
245
+ function postexpirator_get_post_types() {
246
+ $post_types = get_post_types( array('public' => true) );
247
+ $post_types = array_merge( $post_types, get_post_types( array('public' => false, '_builtin' => false ) ) );
248
+
249
+ // in case some post types should not be supported.
250
+ $unset_post_types = apply_filters( 'postexpirator_unset_post_types', array( 'attachment' ) );
251
+ if ( $unset_post_types ) {
252
+ foreach ( $unset_post_types as $type ) {
253
+ unset( $post_types[ $type ] );
254
+ }
255
+ }
256
+ return $post_types;
257
+ }
258
+
259
+ /**
260
+ * Adds hooks to get the meta box added to pages and custom post types
261
+ *
262
+ * @internal
263
+ *
264
+ * @access private
265
+ */
266
+ function postexpirator_meta_custom() {
267
+ $post_types = postexpirator_get_post_types();
268
+ foreach ( $post_types as $t ) {
269
+ $defaults = get_option( 'expirationdateDefaults' . ucfirst( $t ) );
270
+ // if settings are not configured, show the metabox by default only for posts and pages
271
+ if ( ( ! isset( $defaults['activeMetaBox'] ) && in_array( $t, array( 'post', 'page' ), true ) ) || $defaults['activeMetaBox'] === 'active' ) {
272
+ add_meta_box( 'expirationdatediv', __( 'Post Expirator', 'post-expirator' ), 'postexpirator_meta_box', $t, 'side', 'core', array( '__back_compat_meta_box' => PostExpirator_Facade::show_gutenberg_metabox() ) );
273
+ }
274
+ }
275
+ }
276
+ add_action( 'add_meta_boxes', 'postexpirator_meta_custom' );
277
+
278
+ /**
279
+ * Actually adds the meta box
280
+ *
281
+ * @internal
282
+ *
283
+ * @access private
284
+ */
285
+ function postexpirator_meta_box( $post ) {
286
+ // Get default month
287
+ $expirationdatets = get_post_meta( $post->ID, '_expiration-date', true );
288
+ $firstsave = get_post_meta( $post->ID, '_expiration-date-status', true );
289
+
290
+ // nonce
291
+ wp_nonce_field( '__postexpirator', '_postexpiratornonce' );
292
+
293
+ $default = '';
294
+ $expireType = '';
295
+ $defaults = get_option( 'expirationdateDefaults' . ucfirst( $post->post_type ) );
296
+ if ( empty( $expirationdatets ) ) {
297
+ $default_expiry = PostExpirator_Facade::get_default_expiry( $post->post_type );
298
+
299
+ $defaultmonth = $default_expiry['month'];
300
+ $defaultday = $default_expiry['day'];
301
+ $defaulthour = $default_expiry['hour'];
302
+ $defaultyear = $default_expiry['year'];
303
+ $defaultminute = $default_expiry['minute'];
304
+
305
+ $enabled = '';
306
+ $disabled = ' disabled="disabled"';
307
+ $categories = get_option( 'expirationdateCategoryDefaults' );
308
+
309
+ if ( isset( $defaults['expireType'] ) ) {
310
+ $expireType = $defaults['expireType'];
311
+ }
312
+
313
+ // phpcs:ignore WordPress.PHP.StrictComparisons.LooseComparison
314
+ if ( isset( $defaults['autoEnable'] ) && ( $firstsave !== 'saved' ) && ( $defaults['autoEnable'] === true || $defaults['autoEnable'] == 1 ) ) {
315
+ $enabled = ' checked="checked"';
316
+ $disabled = '';
317
+ }
318
+ } else {
319
+ $defaultmonth = get_date_from_gmt( gmdate( 'Y-m-d H:i:s', $expirationdatets ), 'm' );
320
+ $defaultday = get_date_from_gmt( gmdate( 'Y-m-d H:i:s', $expirationdatets ), 'd' );
321
+ $defaultyear = get_date_from_gmt( gmdate( 'Y-m-d H:i:s', $expirationdatets ), 'Y' );
322
+ $defaulthour = get_date_from_gmt( gmdate( 'Y-m-d H:i:s', $expirationdatets ), 'H' );
323
+ $defaultminute = get_date_from_gmt( gmdate( 'Y-m-d H:i:s', $expirationdatets ), 'i' );
324
+ $enabled = ' checked="checked"';
325
+ $disabled = '';
326
+
327
+ $attributes = PostExpirator_Facade::get_expire_principles( $post->ID );
328
+ $expireType = $attributes['expireType'];
329
+ $categories = $attributes['category'];
330
+ }
331
+
332
+ $rv = array();
333
+ $rv[] = '<p><input type="checkbox" name="enable-expirationdate" id="enable-expirationdate" value="checked"' . $enabled . ' onclick="expirationdate_ajax_add_meta(\'enable-expirationdate\')" />';
334
+ $rv[] = '<label for="enable-expirationdate">' . __( 'Enable Post Expiration', 'post-expirator' ) . '</label></p>';
335
+
336
+ if ( $default === 'publish' ) {
337
+ $rv[] = '<em>' . __( 'The published date/time will be used as the expiration value', 'post-expirator' ) . '</em><br/>';
338
+ } else {
339
+ $rv[] = '<table><tr>';
340
+ $rv[] = '<th style="text-align: left;">' . __( 'Year', 'post-expirator' ) . '</th>';
341
+ $rv[] = '<th style="text-align: left;">' . __( 'Month', 'post-expirator' ) . '</th>';
342
+ $rv[] = '<th style="text-align: left;">' . __( 'Day', 'post-expirator' ) . '</th>';
343
+ $rv[] = '</tr><tr>';
344
+ $rv[] = '<td>';
345
+ $rv[] = '<select name="expirationdate_year" id="expirationdate_year"' . $disabled . '>';
346
+ $currentyear = date( 'Y' );
347
+
348
+ if ( $defaultyear < $currentyear ) {
349
+ $currentyear = $defaultyear;
350
+ }
351
+
352
+ for ( $i = $currentyear; $i <= $currentyear + 10; $i++ ) {
353
+ // phpcs:ignore WordPress.PHP.StrictComparisons.LooseComparison
354
+ if ( $i == $defaultyear ) {
355
+ $selected = ' selected="selected"';
356
+ } else {
357
+ $selected = '';
358
+ }
359
+ $rv[] = '<option' . $selected . '>' . ( $i ) . '</option>';
360
+ }
361
+ $rv[] = '</select>';
362
+ $rv[] = '</td><td>';
363
+ $rv[] = '<select name="expirationdate_month" id="expirationdate_month"' . $disabled . '>';
364
+
365
+ for ( $i = 1; $i <= 12; $i++ ) {
366
+ if ( $defaultmonth === date_i18n( 'm', mktime( 0, 0, 0, $i, 1, date_i18n( 'Y' ) ) ) ) {
367
+ $selected = ' selected="selected"';
368
+ } else {
369
+ $selected = '';
370
+ }
371
+ $rv[] = '<option value="' . date_i18n( 'm', mktime( 0, 0, 0, $i, 1, date_i18n( 'Y' ) ) ) . '"' . $selected . '>' . date_i18n( 'F', mktime( 0, 0, 0, $i, 1, date_i18n( 'Y' ) ) ) . '</option>';
372
+ }
373
+
374
+ $rv[] = '</select>';
375
+ $rv[] = '</td><td>';
376
+ $rv[] = '<input type="text" id="expirationdate_day" name="expirationdate_day" value="' . $defaultday . '" size="2"' . $disabled . ' />,';
377
+ $rv[] = '</td></tr><tr>';
378
+ $rv[] = '<th style="text-align: left;"></th>';
379
+ $rv[] = '<th style="text-align: left;">' . __( 'Hour', 'post-expirator' ) . '(' . date_i18n( 'T', mktime( 0, 0, 0, $i, 1, date_i18n( 'Y' ) ) ) . ')</th>';
380
+ $rv[] = '<th style="text-align: left;">' . __( 'Minute', 'post-expirator' ) . '</th>';
381
+ $rv[] = '</tr><tr>';
382
+ $rv[] = '<td>@</td><td>';
383
+ $rv[] = '<select name="expirationdate_hour" id="expirationdate_hour"' . $disabled . '>';
384
+
385
+ for ( $i = 1; $i <= 24; $i++ ) {
386
+ if ( $defaulthour === date_i18n( 'H', mktime( $i, 0, 0, date_i18n( 'n' ), date_i18n( 'j' ), date_i18n( 'Y' ) ) ) ) {
387
+ $selected = ' selected="selected"';
388
+ } else {
389
+ $selected = '';
390
+ }
391
+ $rv[] = '<option value="' . date_i18n( 'H', mktime( $i, 0, 0, date_i18n( 'n' ), date_i18n( 'j' ), date_i18n( 'Y' ) ) ) . '"' . $selected . '>' . date_i18n( 'H', mktime( $i, 0, 0, date_i18n( 'n' ), date_i18n( 'j' ), date_i18n( 'Y' ) ) ) . '</option>';
392
+ }
393
+
394
+ $rv[] = '</select></td><td>';
395
+ $rv[] = '<input type="text" id="expirationdate_minute" name="expirationdate_minute" value="' . $defaultminute . '" size="2"' . $disabled . ' />';
396
+ $rv[] = '</td></tr></table>';
397
+ }
398
+ $rv[] = '<input type="hidden" name="expirationdate_formcheck" value="true" />';
399
+ echo implode( "\n", $rv );
400
+
401
+ echo '<br/>' . __( 'How to expire', 'post-expirator' ) . ': ';
402
+ _postexpirator_expire_type( array('type' => $post->post_type, 'name' => 'expirationdate_expiretype', 'selected' => $expireType, 'disabled' => $disabled, 'onchange' => 'expirationdate_toggle_category(this)') );
403
+ echo '<br/>';
404
+
405
+ if ( $post->post_type !== 'page' ) {
406
+ if ( isset( $expireType ) && ( $expireType === 'category' || $expireType === 'category-add' || $expireType === 'category-remove' ) ) {
407
+ $catdisplay = 'block';
408
+ } else {
409
+ $catdisplay = 'none';
410
+ }
411
+ echo '<div id="expired-category-selection" style="display: ' . $catdisplay . '">';
412
+ echo '<br/>' . __( 'Expiration Categories', 'post-expirator' ) . ':<br/>';
413
+
414
+ echo '<div class="wp-tab-panel" id="post-expirator-cat-list">';
415
+ echo '<ul id="categorychecklist" class="list:category categorychecklist form-no-clear">';
416
+ $walker = new Walker_PostExpirator_Category_Checklist();
417
+ if ( ! empty( $disabled ) ) {
418
+ $walker->setDisabled();
419
+ }
420
+ $taxonomies = get_object_taxonomies( $post->post_type, 'object' );
421
+ $taxonomies = wp_filter_object_list( $taxonomies, array('hierarchical' => true) );
422
+ if ( sizeof( $taxonomies ) === 0 ) {
423
+ echo '<p>' . __( 'You must assign a heirarchical taxonomy to this post type to use this feature.', 'post-expirator' ) . '</p>';
424
+ } elseif ( sizeof( $taxonomies ) > 1 && ! isset( $defaults['taxonomy'] ) ) {
425
+ echo '<p>' . __( 'More than 1 heirachical taxonomy detected. You must assign a default taxonomy on the settings screen.', 'post-expirator' ) . '</p>';
426
+ } else {
427
+ $keys = array_keys( $taxonomies );
428
+ $taxonomy = isset( $defaults['taxonomy'] ) ? $defaults['taxonomy'] : $keys[0];
429
+ wp_terms_checklist( 0, array( 'taxonomy' => $taxonomy, 'walker' => $walker, 'selected_cats' => $categories, 'checked_ontop' => false ) );
430
+ echo '<input type="hidden" name="taxonomy-heirarchical" value="' . $taxonomy . '" />';
431
+ }
432
+ echo '</ul>';
433
+ echo '</div>';
434
+ if ( isset( $taxonomy ) ) {
435
+ echo '<p class="post-expirator-taxonomy-name">' . __( 'Taxonomy Name', 'post-expirator' ) . ': ' . $taxonomy . '</p>';
436
+ }
437
+ echo '</div>';
438
+ }
439
+ echo '<div id="expirationdate_ajax_result"></div>';
440
+ }
441
+
442
+ /**
443
+ * Add's ajax javascript.
444
+ *
445
+ * @internal
446
+ *
447
+ * @access private
448
+ */
449
+ function postexpirator_js_admin_header() {
450
+ // Define custom JavaScript function
451
+ ?>
452
+ <script type="text/javascript">
453
+ //<![CDATA[
454
+ function expirationdate_ajax_add_meta(expireenable) {
455
+ var expire = document.getElementById(expireenable);
456
+
457
+ if (expire.checked == true) {
458
+ var enable = 'true';
459
+ if (document.getElementById('expirationdate_month')) {
460
+ document.getElementById('expirationdate_month').disabled = false;
461
+ document.getElementById('expirationdate_day').disabled = false;
462
+ document.getElementById('expirationdate_year').disabled = false;
463
+ document.getElementById('expirationdate_hour').disabled = false;
464
+ document.getElementById('expirationdate_minute').disabled = false;
465
+ }
466
+ document.getElementById('expirationdate_expiretype').disabled = false;
467
+ var cats = document.getElementsByName('expirationdate_category[]');
468
+ var max = cats.length;
469
+ for (var i=0; i<max; i++) {
470
+ cats[i].disabled = '';
471
+ }
472
+ } else {
473
+ if (document.getElementById('expirationdate_month')) {
474
+ document.getElementById('expirationdate_month').disabled = true;
475
+ document.getElementById('expirationdate_day').disabled = true;
476
+ document.getElementById('expirationdate_year').disabled = true;
477
+ document.getElementById('expirationdate_hour').disabled = true;
478
+ document.getElementById('expirationdate_minute').disabled = true;
479
+ }
480
+ document.getElementById('expirationdate_expiretype').disabled = true;
481
+ var cats = document.getElementsByName('expirationdate_category[]');
482
+ var max = cats.length;
483
+ for (var i=0; i<max; i++) {
484
+ cats[i].disabled = 'disable';
485
+ }
486
+ var enable = 'false';
487
+ }
488
+ return true;
489
+ }
490
+ function expirationdate_toggle_category(id) {
491
+ if (id.options[id.selectedIndex].value == 'category') {
492
+ jQuery('#expired-category-selection').show();
493
+ } else if (id.options[id.selectedIndex].value == 'category-add') {
494
+ jQuery('#expired-category-selection').show(); //TEMP
495
+ } else if (id.options[id.selectedIndex].value == 'category-remove') {
496
+ jQuery('#expired-category-selection').show(); //TEMP
497
+ } else {
498
+ jQuery('#expired-category-selection').hide();
499
+ }
500
+ }
501
+ //]]>
502
+ </script>
503
+ <?php
504
+ }
505
+ add_action( 'admin_head', 'postexpirator_js_admin_header' );
506
+
507
+ /**
508
+ * Get correct URL (HTTP or HTTPS)
509
+ *
510
+ * @internal
511
+ *
512
+ * @access private
513
+ */
514
+ function expirationdate_get_blog_url() {
515
+ if ( is_multisite() ) {
516
+ echo network_home_url( '/' );
517
+ } else {
518
+ echo home_url( '/' );
519
+ }
520
+ }
521
+
522
+ /**
523
+ * Called when post is saved - stores expiration-date meta value
524
+ *
525
+ * @internal
526
+ *
527
+ * @access private
528
+ */
529
+ function postexpirator_update_post_meta( $id ) {
530
+ // don't run the echo if this is an auto save
531
+ if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) {
532
+ return;
533
+ }
534
+
535
+ // don't run the echo if the function is called for saving revision.
536
+ $posttype = get_post_type( $id );
537
+ if ( $posttype === 'revision' ) {
538
+ return;
539
+ }
540
+
541
+ // we want to make sure we don't fire the save_post action when we are inside the block editor
542
+ // but this should not stop quick/bulk edit
543
+ if ( PostExpirator_Util::is_gutenberg_active() && PostExpirator_Facade::show_gutenberg_metabox()
544
+ &&
545
+ ! isset( $_POST['expirationdate_quickedit'] ) && ! isset( $_POST['expirationdate_formcheck'] )
546
+ ) {
547
+ return;
548
+ }
549
+
550
+ if ( isset( $_POST['enable-expirationdate'] ) ) {
551
+ $default = get_option( 'expirationdateDefaultDate', POSTEXPIRATOR_EXPIREDEFAULT );
552
+ if ( $default === 'publish' ) {
553
+ $month = intval( $_POST['mm'] );
554
+ $day = intval( $_POST['jj'] );
555
+ $year = intval( $_POST['aa'] );
556
+ $hour = intval( $_POST['hh'] );
557
+ $minute = intval( $_POST['mn'] );
558
+ } else {
559
+ $month = intval( $_POST['expirationdate_month'] );
560
+ $day = intval( $_POST['expirationdate_day'] );
561
+ $year = intval( $_POST['expirationdate_year'] );
562
+ $hour = intval( $_POST['expirationdate_hour'] );
563
+ $minute = intval( $_POST['expirationdate_minute'] );
564
+
565
+ if ( empty( $day ) ) {
566
+ $day = date( 'd' );
567
+ }
568
+ if ( empty( $year ) ) {
569
+ $year = date( 'Y' );
570
+ }
571
+ }
572
+ $category = isset( $_POST['expirationdate_category'] ) ? $_POST['expirationdate_category'] : 0;
573
+
574
+ $ts = get_gmt_from_date( "$year-$month-$day $hour:$minute:0", 'U' );
575
+
576
+ if ( isset( $_POST['expirationdate_quickedit'] ) ) {
577
+ $ed = get_post_meta( $id, '_expiration-date', true );
578
+ if ( $ed ) {
579
+ $opts = PostExpirator_Facade::get_expire_principles( $id );
580
+ if ( isset( $_POST['expirationdate_expiretype'] ) ) {
581
+ $opts['expireType'] = $_POST['expirationdate_expiretype'];
582
+ if ( in_array( $opts['expireType'], array( 'category', 'category-add', 'category-remove' ), true ) ) {
583
+ $opts['category'] = $_POST['expirationdate_category'];
584
+ }
585
+ PostExpirator_Facade::set_expire_principles( $id, $opts );
586
+ }
587
+ }
588
+ } else {
589
+ $opts = array();
590
+
591
+ // Schedule/Update Expiration
592
+ $opts['expireType'] = $_POST['expirationdate_expiretype'];
593
+ $opts['id'] = $id;
594
+
595
+ if ( $opts['expireType'] === 'category' || $opts['expireType'] === 'category-add' || $opts['expireType'] === 'category-remove' ) {
596
+ if ( isset( $category ) && ! empty( $category ) ) {
597
+ if ( ! empty( $category ) ) {
598
+ $opts['category'] = $category;
599
+ $opts['categoryTaxonomy'] = $_POST['taxonomy-heirarchical'];
600
+ }
601
+ }
602
+ }
603
+ }
604
+ postexpirator_schedule_event( $id, $ts, $opts );
605
+ } else {
606
+ postexpirator_unschedule_event( $id );
607
+ }
608
+ }
609
+ add_action( 'save_post', 'postexpirator_update_post_meta' );
610
+
611
+ /**
612
+ * Schedules the single event.
613
+ *
614
+ * @internal
615
+ *
616
+ * @access private
617
+ */
618
+ function postexpirator_schedule_event( $id, $ts, $opts ) {
619
+ $debug = postexpirator_debug(); // check for/load debug
620
+
621
+ $id = intval( $id );
622
+
623
+ do_action( 'postexpiratior_schedule', $id, $ts, $opts ); // allow custom actions
624
+
625
+ if ( wp_next_scheduled( 'postExpiratorExpire', array($id) ) !== false ) {
626
+ $error = wp_clear_scheduled_hook( 'postExpiratorExpire', array($id), true ); // Remove any existing hooks
627
+ if ( POSTEXPIRATOR_DEBUG ) {
628
+ $debug->save( array('message' => $id . ' -> EXISTING FOUND - UNSCHEDULED - ' . ( is_wp_error( $error ) ? $error->get_error_message() : 'no error' )) );
629
+ }
630
+ }
631
+
632
+ $error = wp_schedule_single_event( $ts, 'postExpiratorExpire', array($id), true );
633
+ if ( POSTEXPIRATOR_DEBUG ) {
634
+ $debug->save( array('message' => $id . ' -> SCHEDULED at ' . date_i18n( 'r', $ts ) . ' ' . '(' . $ts . ') with options ' . print_r( $opts, true ) . ' ' . ( is_wp_error( $error ) ? $error->get_error_message() : 'no error' ) ) );
635
+ }
636
+
637
+ // Update Post Meta
638
+ update_post_meta( $id, '_expiration-date', $ts );
639
+ if ( ! is_null( $opts ) ) {
640
+ PostExpirator_Facade::set_expire_principles( $id, $opts );
641
+ }
642
+ update_post_meta( $id, '_expiration-date-status', 'saved' );
643
+ }
644
+
645
+ /**
646
+ * Unschedules the single event.
647
+ *
648
+ * @internal
649
+ *
650
+ * @access private
651
+ */
652
+ function postexpirator_unschedule_event( $id ) {
653
+ $debug = postexpirator_debug(); // check for/load debug
654
+
655
+ do_action( 'postexpiratior_unschedule', $id ); // allow custom actions
656
+
657
+ delete_post_meta( $id, '_expiration-date' );
658
+ delete_post_meta( $id, '_expiration-date-options' );
659
+ delete_post_meta( $id, '_expiration-date-type' );
660
+ delete_post_meta( $id, '_expiration-date-categories' );
661
+ delete_post_meta( $id, '_expiration-date-taxonomy' );
662
+
663
+ // Delete Scheduled Expiration
664
+ if ( wp_next_scheduled( 'postExpiratorExpire', array($id) ) !== false ) {
665
+ wp_clear_scheduled_hook( 'postExpiratorExpire', array($id) ); // Remove any existing hooks
666
+ if ( POSTEXPIRATOR_DEBUG ) {
667
+ $debug->save( array('message' => $id . ' -> UNSCHEDULED') );
668
+ }
669
+ }
670
+ delete_post_meta( $id, '_expiration-date-status' );
671
+ }
672
+
673
+ /**
674
+ * The new expiration function, to work with single scheduled events.
675
+ *
676
+ * This was designed to hopefully be more flexible for future tweaks/modifications to the architecture.
677
+ *
678
+ * @internal
679
+ *
680
+ * @access private
681
+ */
682
+ function postexpirator_expire_post( $id ) {
683
+ $debug = postexpirator_debug(); // check for/load debug
684
+
685
+ if ( empty( $id ) ) {
686
+ if ( POSTEXPIRATOR_DEBUG ) {
687
+ $debug->save( array('message' => 'No Post ID found - exiting') );
688
+ }
689
+ return false;
690
+ }
691
+
692
+ if ( is_null( get_post( $id ) ) ) {
693
+ if ( POSTEXPIRATOR_DEBUG ) {
694
+ $debug->save( array('message' => $id . ' -> Post does not exist - exiting') );
695
+ }
696
+ return false;
697
+ }
698
+
699
+ $posttype = get_post_type( $id );
700
+ $posttitle = get_the_title( $id );
701
+ $postlink = get_post_permalink( $id );
702
+
703
+ $postoptions = PostExpirator_Facade::get_expire_principles( $id );
704
+ $expireType = $category = $categoryTaxonomy = null;
705
+
706
+ if ( isset( $postoptions['expireType'] ) ) {
707
+ $expireType = $postoptions['expireType'];
708
+ }
709
+
710
+ if ( isset( $postoptions['category'] ) ) {
711
+ $category = $postoptions['category'];
712
+ }
713
+
714
+ if ( isset( $postoptions['categoryTaxonomy'] ) ) {
715
+ $categoryTaxonomy = $postoptions['categoryTaxonomy'];
716
+ }
717
+
718
+ $ed = get_post_meta( $id, '_expiration-date', true );
719
+
720
+ // Check for default expire only if not passed in
721
+ if ( empty( $expireType ) ) {
722
+ $posttype = get_post_type( $id );
723
+ if ( $posttype === 'page' ) {
724
+ $expireType = strtolower( get_option( 'expirationdateExpiredPageStatus', POSTEXPIRATOR_PAGESTATUS ) );
725
+ } elseif ( $posttype === 'post' ) {
726
+ $expireType = strtolower( get_option( 'expirationdateExpiredPostStatus', 'draft' ) );
727
+ } else {
728
+ $expireType = apply_filters( 'postexpirator_custom_posttype_expire', $expireType, $posttype ); // hook to set defaults for custom post types
729
+ }
730
+ }
731
+
732
+ // Remove KSES - wp_cron runs as an unauthenticated user, which will by default trigger kses filtering,
733
+ // even if the post was published by a admin user. It is fairly safe here to remove the filter call since
734
+ // we are only changing the post status/meta information and not touching the content.
735
+ kses_remove_filters();
736
+
737
+ // Do Work
738
+ if ( $expireType === 'draft' ) {
739
+ if ( wp_update_post( array('ID' => $id, 'post_status' => 'draft') ) === 0 ) {
740
+ if ( POSTEXPIRATOR_DEBUG ) {
741
+ $debug->save( array('message' => $id . ' -> FAILED ' . $expireType . ' ' . print_r( $postoptions, true )) );
742
+ }
743
+ } else {
744
+ $emailBody = sprintf( __( '%1$s (%2$s) has expired at %3$s. Post status has been successfully changed to "%4$s".', 'post-expirator' ), '##POSTTITLE##', '##POSTLINK##', '##EXPIRATIONDATE##', strtoupper( $expireType ) );
745
+ if ( POSTEXPIRATOR_DEBUG ) {
746
+ $debug->save( array('message' => $id . ' -> PROCESSED ' . $expireType . ' ' . print_r( $postoptions, true )) );
747
+ }
748
+ }
749
+ } elseif ( $expireType === 'private' ) {
750
+ if ( wp_update_post( array('ID' => $id, 'post_status' => 'private') ) === 0 ) {
751
+ if ( POSTEXPIRATOR_DEBUG ) {
752
+ $debug->save( array('message' => $id . ' -> FAILED ' . $expireType . ' ' . print_r( $postoptions, true )) );
753
+ }
754
+ } else {
755
+ $emailBody = sprintf( __( '%1$s (%2$s) has expired at %3$s. Post status has been successfully changed to "%4$s".', 'post-expirator' ), '##POSTTITLE##', '##POSTLINK##', '##EXPIRATIONDATE##', strtoupper( $expireType ) );
756
+ if ( POSTEXPIRATOR_DEBUG ) {
757
+ $debug->save( array('message' => $id . ' -> PROCESSED ' . $expireType . ' ' . print_r( $postoptions, true )) );
758
+ }
759
+ }
760
+ } elseif ( $expireType === 'delete' ) {
761
+ if ( wp_delete_post( $id ) === false ) {
762
+ if ( POSTEXPIRATOR_DEBUG ) {
763
+ $debug->save( array('message' => $id . ' -> FAILED ' . $expireType . ' ' . print_r( $postoptions, true )) );
764
+ }
765
+ } else {
766
+ $emailBody = sprintf( __( '%1$s (%2$s) has expired at %3$s. Post status has been successfully changed to "%4$s".', 'post-expirator' ), '##POSTTITLE##', '##POSTLINK##', '##EXPIRATIONDATE##', strtoupper( $expireType ) );
767
+ if ( POSTEXPIRATOR_DEBUG ) {
768
+ $debug->save( array('message' => $id . ' -> PROCESSED ' . $expireType . ' ' . print_r( $postoptions, true )) );
769
+ }
770
+ }
771
+ } elseif ( $expireType === 'trash' ) {
772
+ if ( wp_trash_post( $id ) === false ) {
773
+ if ( POSTEXPIRATOR_DEBUG ) {
774
+ $debug->save( array('message' => $id . ' -> FAILED ' . $expireType . ' ' . print_r( $postoptions, true )) );
775
+ }
776
+ } else {
777
+ $emailBody = sprintf( __( '%1$s (%2$s) has expired at %3$s. Post status has been successfully changed to "%4$s".', 'post-expirator' ), '##POSTTITLE##', '##POSTLINK##', '##EXPIRATIONDATE##', strtoupper( $expireType ) );
778
+ if ( POSTEXPIRATOR_DEBUG ) {
779
+ $debug->save( array('message' => $id . ' -> PROCESSED ' . $expireType . ' ' . print_r( $postoptions, true )) );
780
+ }
781
+ }
782
+ } elseif ( $expireType === 'stick' ) {
783
+ if ( stick_post( $id ) === false ) {
784
+ if ( POSTEXPIRATOR_DEBUG ) {
785
+ $debug->save( array('message' => $id . ' -> FAILED ' . $expireType . ' ' . print_r( $postoptions, true )) );
786
+ }
787
+ } else {
788
+ $emailBody = sprintf( __( '%1$s (%2$s) has expired at %3$s. Post "%4$s" status has been successfully set.', 'post-expirator' ), '##POSTTITLE##', '##POSTLINK##', '##EXPIRATIONDATE##', 'STICKY' );
789
+ if ( POSTEXPIRATOR_DEBUG ) {
790
+ $debug->save( array('message' => $id . ' -> PROCESSED ' . $expireType . ' ' . print_r( $postoptions, true )) );
791
+ }
792
+ }
793
+ } elseif ( $expireType === 'unstick' ) {
794
+ if ( unstick_post( $id ) === false ) {
795
+ if ( POSTEXPIRATOR_DEBUG ) {
796
+ $debug->save( array('message' => $id . ' -> FAILED ' . $expireType . ' ' . print_r( $postoptions, true )) );
797
+ }
798
+ } else {
799
+ $emailBody = sprintf( __( '%1$s (%2$s) has expired at %3$s. Post "%4$s" status has been successfully removed.', 'post-expirator' ), '##POSTTITLE##', '##POSTLINK##', '##EXPIRATIONDATE##', 'STICKY' );
800
+ if ( POSTEXPIRATOR_DEBUG ) {
801
+ $debug->save( array('message' => $id . ' -> PROCESSED ' . $expireType . ' ' . print_r( $postoptions, true )) );
802
+ }
803
+ }
804
+ } elseif ( $expireType === 'category' ) {
805
+ if ( ! empty( $category ) ) {
806
+ if ( ! isset( $categoryTaxonomy ) || $categoryTaxonomy === 'category' ) {
807
+ if ( wp_update_post( array('ID' => $id, 'post_category' => $category) ) === 0 ) {
808
+ if ( POSTEXPIRATOR_DEBUG ) {
809
+ $debug->save( array('message' => $id . ' -> FAILED ' . $expireType . ' ' . print_r( $postoptions, true )) );
810
+ }
811
+ } else {
812
+ $emailBody = sprintf( __( '%1$s (%2$s) has expired at %3$s. Post "%4$s" have now been set to "%5$s".', 'post-expirator' ), '##POSTTITLE##', '##POSTLINK##', '##EXPIRATIONDATE##', 'CATEGORIES', implode( ',', _postexpirator_get_cat_names( $category ) ) );
813
+ if ( POSTEXPIRATOR_DEBUG ) {
814
+ $debug->save( array('message' => $id . ' -> PROCESSED ' . $expireType . ' ' . print_r( $postoptions, true )) );
815
+ $debug->save( array('message' => $id . ' -> CATEGORIES REPLACED ' . print_r( _postexpirator_get_cat_names( $category ), true )) );
816
+ $debug->save( array('message' => $id . ' -> CATEGORIES COMPLETE ' . print_r( _postexpirator_get_cat_names( $category ), true )) );
817
+ }
818
+ }
819
+ } else {
820
+ $terms = array_map( 'intval', $category );
821
+ if ( is_wp_error( wp_set_object_terms( $id, $terms, $categoryTaxonomy, false ) ) ) {
822
+ if ( POSTEXPIRATOR_DEBUG ) {
823
+ $debug->save( array('message' => $id . ' -> FAILED ' . $expireType . ' ' . print_r( $postoptions, true )) );
824
+ }
825
+ } else {
826
+ $emailBody = sprintf( __( '%1$s (%2$s) has expired at %3$s. Post "%4$s" have now been set to "%5$s".', 'post-expirator' ), '##POSTTITLE##', '##POSTLINK##', '##EXPIRATIONDATE##', 'CATEGORIES', implode( ',', _postexpirator_get_cat_names( $category ) ) );
827
+ if ( POSTEXPIRATOR_DEBUG ) {
828
+ $debug->save( array('message' => $id . ' -> PROCESSED ' . $expireType . ' ' . print_r( $postoptions, true )) );
829
+ $debug->save( array('message' => $id . ' -> CATEGORIES REPLACED ' . print_r( _postexpirator_get_cat_names( $category ), true )) );
830
+ $debug->save( array('message' => $id . ' -> CATEGORIES COMPLETE ' . print_r( _postexpirator_get_cat_names( $category ), true )) );
831
+ }
832
+ }
833
+ }
834
+ } else {
835
+ if ( POSTEXPIRATOR_DEBUG ) {
836
+ $debug->save( array('message' => $id . ' -> CATEGORIES MISSING ' . $expireType . ' ' . print_r( $postoptions, true )) );
837
+ }
838
+ }
839
+ } elseif ( $expireType === 'category-add' ) {
840
+ if ( ! empty( $category ) ) {
841
+ if ( ! isset( $categoryTaxonomy ) || $categoryTaxonomy === 'category' ) {
842
+ $cats = wp_get_post_categories( $id );
843
+ $merged = array_merge( $cats, $category );
844
+ if ( wp_update_post( array('ID' => $id, 'post_category' => $merged) ) === 0 ) {
845
+ if ( POSTEXPIRATOR_DEBUG ) {
846
+ $debug->save( array('message' => $id . ' -> FAILED ' . $expireType . ' ' . print_r( $postoptions, true )) );
847
+ }
848
+ } else {
849
+ $emailBody = sprintf( __( '%1$s (%2$s) has expired at %3$s. The following post "%4$s" have now been added: "%5$s". The full list of categories on the post are: "%6$s".', 'post-expirator' ), '##POSTTITLE##', '##POSTLINK##', '##EXPIRATIONDATE##', 'CATEGORIES', implode( ',', _postexpirator_get_cat_names( $category ) ), implode( ',', _postexpirator_get_cat_names( $merged ) ) );
850
+ if ( POSTEXPIRATOR_DEBUG ) {
851
+ $debug->save( array('message' => $id . ' -> PROCESSED ' . $expireType . ' ' . print_r( $postoptions, true )) );
852
+ $debug->save( array('message' => $id . ' -> CATEGORIES ADDED ' . print_r( _postexpirator_get_cat_names( $category ), true )) );
853
+ $debug->save( array('message' => $id . ' -> CATEGORIES COMPLETE ' . print_r( _postexpirator_get_cat_names( $merged ), true )) );
854
+ }
855
+ }
856
+ } else {
857
+ $terms = array_map( 'intval', $category );
858
+ if ( is_wp_error( wp_set_object_terms( $id, $terms, $categoryTaxonomy, true ) ) ) {
859
+ if ( POSTEXPIRATOR_DEBUG ) {
860
+ $debug->save( array('message' => $id . ' -> FAILED ' . $expireType . ' ' . print_r( $postoptions, true )) );
861
+ }
862
+ } else {
863
+ $emailBody = sprintf( __( '%1$s (%2$s) has expired at %3$s. The following post "%4$s" have now been added: "%5$s". The full list of categories on the post are: "%6$s".', 'post-expirator' ), '##POSTTITLE##', '##POSTLINK##', '##EXPIRATIONDATE##', 'CATEGORIES', implode( ',', _postexpirator_get_cat_names( $category ) ), implode( ',', _postexpirator_get_cat_names( $merged ) ) );
864
+ if ( POSTEXPIRATOR_DEBUG ) {
865
+ $debug->save( array('message' => $id . ' -> PROCESSED ' . $expireType . ' ' . print_r( $postoptions, true )) );
866
+ $debug->save( array('message' => $id . ' -> CATEGORIES ADDED ' . print_r( _postexpirator_get_cat_names( $category ), true )) );
867
+ $debug->save( array('message' => $id . ' -> CATEGORIES COMPLETE ' . print_r( _postexpirator_get_cat_names( $category ), true )) );
868
+ }
869
+ }
870
+ }
871
+ } else {
872
+ if ( POSTEXPIRATOR_DEBUG ) {
873
+ $debug->save( array('message' => $id . ' -> CATEGORIES MISSING ' . $expireType . ' ' . print_r( $postoptions, true )) );
874
+ }
875
+ }
876
+ } elseif ( $expireType === 'category-remove' ) {
877
+ if ( ! empty( $category ) ) {
878
+ if ( ! isset( $categoryTaxonomy ) || $categoryTaxonomy === 'category' ) {
879
+ $cats = wp_get_post_categories( $id );
880
+ $merged = array();
881
+ foreach ( $cats as $cat ) {
882
+ if ( ! in_array( $cat, $category, false ) ) {
883
+ $merged[] = $cat;
884
+ }
885
+ }
886
+
887
+ if ( wp_update_post( array('ID' => $id, 'post_category' => $merged) ) === 0 ) {
888
+ if ( POSTEXPIRATOR_DEBUG ) {
889
+ $debug->save( array('message' => $id . ' -> FAILED ' . $expireType . ' ' . print_r( $postoptions, true )) );
890
+ }
891
+ } else {
892
+ $emailBody = sprintf( __( '%1$s (%2$s) has expired at %3$s. The following post "%4$s" have now been removed: "%5$s". The full list of categories on the post are: "%6$s".', 'post-expirator' ), '##POSTTITLE##', '##POSTLINK##', '##EXPIRATIONDATE##', 'CATEGORIES', implode( ',', _postexpirator_get_cat_names( $category ) ), implode( ',', _postexpirator_get_cat_names( $merged ) ) );
893
+ if ( POSTEXPIRATOR_DEBUG ) {
894
+ $debug->save( array('message' => $id . ' -> PROCESSED ' . $expireType . ' ' . print_r( $postoptions, true )) );
895
+ $debug->save( array('message' => $id . ' -> CATEGORIES REMOVED ' . print_r( _postexpirator_get_cat_names( $category ), true )) );
896
+ $debug->save( array('message' => $id . ' -> CATEGORIES COMPLETE ' . print_r( _postexpirator_get_cat_names( $merged ), true )) );
897
+ }
898
+ }
899
+ } else {
900
+ $terms = wp_get_object_terms( $id, $categoryTaxonomy, array('fields' => 'ids') );
901
+ $merged = array();
902
+ foreach ( $terms as $term ) {
903
+ if ( ! in_array( $term, $category, false ) ) {
904
+ $merged[] = $term;
905
+ }
906
+ }
907
+ $terms = array_map( 'intval', $merged );
908
+ if ( is_wp_error( wp_set_object_terms( $id, $terms, $categoryTaxonomy, false ) ) ) {
909
+ if ( POSTEXPIRATOR_DEBUG ) {
910
+ $debug->save( array('message' => $id . ' -> FAILED ' . $expireType . ' ' . print_r( $postoptions, true )) );
911
+ }
912
+ } else {
913
+ $emailBody = sprintf( __( '%1$s (%2$s) has expired at %3$s. The following post "%4$s" have now been removed: "%5$s". The full list of categories on the post are: "%6$s".', 'post-expirator' ), '##POSTTITLE##', '##POSTLINK##', '##EXPIRATIONDATE##', 'CATEGORIES', implode( ',', _postexpirator_get_cat_names( $category ) ), implode( ',', _postexpirator_get_cat_names( $merged ) ) );
914
+ if ( POSTEXPIRATOR_DEBUG ) {
915
+ $debug->save( array('message' => $id . ' -> PROCESSED ' . $expireType . ' ' . print_r( $postoptions, true )) );
916
+ $debug->save( array('message' => $id . ' -> CATEGORIES REMOVED ' . print_r( _postexpirator_get_cat_names( $category ), true )) );
917
+ $debug->save( array('message' => $id . ' -> CATEGORIES COMPLETE ' . print_r( _postexpirator_get_cat_names( $category ), true )) );
918
+ }
919
+ }
920
+ }
921
+ } else {
922
+ if ( POSTEXPIRATOR_DEBUG ) {
923
+ $debug->save( array('message' => $id . ' -> CATEGORIES MISSING ' . $expireType . ' ' . print_r( $postoptions, true )) );
924
+ }
925
+ }
926
+ }
927
+
928
+ // Process Email
929
+ $emailenabled = get_option( 'expirationdateEmailNotification', POSTEXPIRATOR_EMAILNOTIFICATION );
930
+ // phpcs:ignore WordPress.PHP.StrictComparisons.LooseComparison
931
+ if ( $emailenabled == 1 && isset( $emailBody ) ) {
932
+ $subj = sprintf( __( 'Post Expiration Complete "%s"', 'post-expirator' ), $posttitle );
933
+ $emailBody = str_replace( '##POSTTITLE##', $posttitle, $emailBody );
934
+ $emailBody = str_replace( '##POSTLINK##', $postlink, $emailBody );
935
+ $emailBody = str_replace( '##EXPIRATIONDATE##', get_date_from_gmt( gmdate( 'Y-m-d H:i:s', $ed ), get_option( 'date_format' ) . ' ' . get_option( 'time_format' ) ), $emailBody );
936
+
937
+ $emails = array();
938
+ // Get Blog Admins
939
+ $emailadmins = get_option( 'expirationdateEmailNotificationAdmins', POSTEXPIRATOR_EMAILNOTIFICATIONADMINS );
940
+ // phpcs:ignore WordPress.PHP.StrictComparisons.LooseComparison
941
+ if ( $emailadmins == 1 ) {
942
+ $blogusers = get_users( 'role=Administrator' );
943
+ foreach ( $blogusers as $user ) {
944
+ $emails[] = $user->user_email;
945
+ }
946
+ }
947
+
948
+ // Get Global Notification Emails
949
+ $emaillist = get_option( 'expirationdateEmailNotificationList' );
950
+ if ( ! empty( $emaillist ) ) {
951
+ $vals = explode( ',', $emaillist );
952
+ foreach ( $vals as $val ) {
953
+ $emails[] = trim( $val );
954
+ }
955
+ }
956
+
957
+ // Get Post Type Notification Emails
958
+ $defaults = get_option( 'expirationdateDefaults' . ucfirst( $posttype ) );
959
+ if ( isset( $defaults['emailnotification'] ) && ! empty( $defaults['emailnotification'] ) ) {
960
+ $vals = explode( ',', $defaults['emailnotification'] );
961
+ foreach ( $vals as $val ) {
962
+ $emails[] = trim( $val );
963
+ }
964
+ }
965
+
966
+ // Send Emails
967
+ foreach ( $emails as $email ) {
968
+ if ( wp_mail( $email, sprintf( __( '[%1$s] %2$s' ), get_option( 'blogname' ), $subj ), $emailBody ) ) {
969
+ if ( POSTEXPIRATOR_DEBUG ) {
970
+ $debug->save( array('message' => $id . ' -> EXPIRATION EMAIL SENT (' . $email . ')') );
971
+ }
972
+ } else {
973
+ if ( POSTEXPIRATOR_DEBUG ) {
974
+ $debug->save( array('message' => $id . ' -> EXPIRATION EMAIL FAILED (' . $email . ')') );
975
+ }
976
+ }
977
+ }
978
+ }
979
+
980
+ }
981
+ add_action( 'postExpiratorExpire', 'postexpirator_expire_post' );
982
+
983
+ /**
984
+ * Internal method to get category names corresponding to the category IDs.
985
+ *
986
+ * @internal
987
+ *
988
+ * @access private
989
+ */
990
+ function _postexpirator_get_cat_names( $cats ) {
991
+ $out = array();
992
+ foreach ( $cats as $cat ) {
993
+ $out[ $cat ] = get_the_category_by_id( $cat );
994
+ }
995
+ return $out;
996
+ }
997
+
998
+
999
+ /**
1000
+ * Show the menu.
1001
+ *
1002
+ * @internal
1003
+ *
1004
+ * @access private
1005
+ */
1006
+ function postexpirator_menu() {
1007
+ _deprecated_function( __FUNCTION__, '2.5' );
1008
+ }
1009
+
1010
+ /**
1011
+ * Hook's to add plugin page menu
1012
+ *
1013
+ * @internal
1014
+ *
1015
+ * @access private
1016
+ */
1017
+ function postexpirator_add_menu() {
1018
+ _deprecated_function( __FUNCTION__, '2.5' );
1019
+ }
1020
+
1021
+ /**
1022
+ * Show the Expiration Date options page
1023
+ *
1024
+ * @internal
1025
+ *
1026
+ * @access private
1027
+ */
1028
+ function postexpirator_menu_general() {
1029
+ _deprecated_function( __FUNCTION__, '2.5' );
1030
+ PostExpirator_Display::getInstance()->load_tab( 'general' );
1031
+ }
1032
+
1033
+ /**
1034
+ * The default menu.
1035
+ *
1036
+ * @internal
1037
+ *
1038
+ * @access private
1039
+ */
1040
+ function postexpirator_menu_defaults() {
1041
+ _deprecated_function( __FUNCTION__, '2.5' );
1042
+ PostExpirator_Display::getInstance()->load_tab( 'defaults' );
1043
+ }
1044
+
1045
+ /**
1046
+ * Diagnostics menu.
1047
+ *
1048
+ * @internal
1049
+ *
1050
+ * @access private
1051
+ */
1052
+ function postexpirator_menu_diagnostics() {
1053
+ _deprecated_function( __FUNCTION__, '2.5' );
1054
+ PostExpirator_Display::getInstance()->load_tab( 'diagnostics' );
1055
+ }
1056
+
1057
+ /**
1058
+ * Debug menu.
1059
+ *
1060
+ * @internal
1061
+ *
1062
+ * @access private
1063
+ */
1064
+ function postexpirator_menu_debug() {
1065
+ _deprecated_function( __FUNCTION__, '2.5' );
1066
+ PostExpirator_Display::getInstance()->load_tab( 'viewdebug' );
1067
+ }
1068
+
1069
+ /**
1070
+ * Register the shortcode.
1071
+ *
1072
+ * @internal
1073
+ *
1074
+ * @access private
1075
+ */
1076
+ function postexpirator_shortcode( $atts ) {
1077
+ global $post;
1078
+
1079
+ $expirationdatets = get_post_meta( $post->ID, '_expiration-date', true );
1080
+ if ( empty( $expirationdatets ) ) {
1081
+ return false;
1082
+ }
1083
+
1084
+ // @TODO remove extract
1085
+ // phpcs:ignore WordPress.PHP.DontExtract.extract_extract
1086
+ extract(
1087
+ shortcode_atts(
1088
+ array(
1089
+ 'dateformat' => get_option( 'expirationdateDefaultDateFormat', POSTEXPIRATOR_DATEFORMAT ),
1090
+ 'timeformat' => get_option( 'expirationdateDefaultTimeFormat', POSTEXPIRATOR_TIMEFORMAT ),
1091
+ 'type' => 'full',
1092
+ 'tz' => date( 'T' ),
1093
+ ), $atts
1094
+ )
1095
+ );
1096
+
1097
+ if ( empty( $dateformat ) ) {
1098
+ global $expirationdateDefaultDateFormat;
1099
+ $dateformat = $expirationdateDefaultDateFormat;
1100
+ }
1101
+
1102
+ if ( empty( $timeformat ) ) {
1103
+ global $expirationdateDefaultTimeFormat;
1104
+ $timeformat = $expirationdateDefaultTimeFormat;
1105
+ }
1106
+
1107
+ if ( $type === 'full' ) {
1108
+ $format = $dateformat . ' ' . $timeformat;
1109
+ } elseif ( $type === 'date' ) {
1110
+ $format = $dateformat;
1111
+ } elseif ( $type === 'time' ) {
1112
+ $format = $timeformat;
1113
+ }
1114
+
1115
+ return date_i18n( $format, $expirationdatets + ( get_option( 'gmt_offset' ) * HOUR_IN_SECONDS ) );
1116
+ }
1117
+ add_shortcode( 'postexpirator', 'postexpirator_shortcode' );
1118
+
1119
+ /**
1120
+ * Add the footer.
1121
+ *
1122
+ * @internal
1123
+ *
1124
+ * @access private
1125
+ */
1126
+ function postexpirator_add_footer( $text ) {
1127
+ global $post;
1128
+
1129
+ // Check to see if its enabled
1130
+ $displayFooter = get_option( 'expirationdateDisplayFooter' );
1131
+
1132
+ // phpcs:ignore WordPress.PHP.StrictComparisons.LooseComparison
1133
+ if ( $displayFooter === false || $displayFooter == 0 ) {
1134
+ return $text;
1135
+ }
1136
+
1137
+ $expirationdatets = get_post_meta( $post->ID, '_expiration-date', true );
1138
+ if ( ! is_numeric( $expirationdatets ) ) {
1139
+ return $text;
1140
+ }
1141
+
1142
+ $dateformat = get_option( 'expirationdateDefaultDateFormat', POSTEXPIRATOR_DATEFORMAT );
1143
+ $timeformat = get_option( 'expirationdateDefaultTimeFormat', POSTEXPIRATOR_TIMEFORMAT );
1144
+ $expirationdateFooterContents = get_option( 'expirationdateFooterContents', POSTEXPIRATOR_FOOTERCONTENTS );
1145
+ $expirationdateFooterStyle = get_option( 'expirationdateFooterStyle', POSTEXPIRATOR_FOOTERSTYLE );
1146
+
1147
+ $search = array(
1148
+ 'EXPIRATIONFULL',
1149
+ 'EXPIRATIONDATE',
1150
+ 'EXPIRATIONTIME',
1151
+ );
1152
+ $replace = array(
1153
+ get_date_from_gmt( gmdate( 'Y-m-d H:i:s', $expirationdatets ), "$dateformat $timeformat" ),
1154
+ get_date_from_gmt( gmdate( 'Y-m-d H:i:s', $expirationdatets ), $dateformat ),
1155
+ get_date_from_gmt( gmdate( 'Y-m-d H:i:s', $expirationdatets ), $timeformat ),
1156
+ );
1157
+
1158
+ $add_to_footer = '<p style="' . $expirationdateFooterStyle . '">' . str_replace( $search, $replace, $expirationdateFooterContents ) . '</p>';
1159
+ return $text . $add_to_footer;
1160
+ }
1161
+ add_action( 'the_content', 'postexpirator_add_footer', 0 );
1162
+
1163
+ /**
1164
+ * Check for Debug
1165
+ *
1166
+ * @internal
1167
+ *
1168
+ * @access private
1169
+ */
1170
+ function postexpirator_debug() {
1171
+ $debug = get_option( 'expirationdateDebug' );
1172
+ // phpcs:ignore WordPress.PHP.StrictComparisons.LooseComparison
1173
+ if ( $debug == 1 ) {
1174
+ if ( ! defined( 'POSTEXPIRATOR_DEBUG' ) ) {
1175
+ define( 'POSTEXPIRATOR_DEBUG', 1 );
1176
+ }
1177
+ require_once( plugin_dir_path( __FILE__ ) . 'post-expirator-debug.php' ); // Load Class
1178
+ return new PostExpiratorDebug();
1179
+ } else {
1180
+ if ( ! defined( 'POSTEXPIRATOR_DEBUG' ) ) {
1181
+ define( 'POSTEXPIRATOR_DEBUG', 0 );
1182
+ }
1183
+ return false;
1184
+ }
1185
+ }
1186
+
1187
+
1188
+ /**
1189
+ * Add Stylesheet
1190
+ *
1191
+ * @internal
1192
+ *
1193
+ * @access private
1194
+ */
1195
+ function postexpirator_css( $screen_id ) {
1196
+ switch ( $screen_id ) {
1197
+ case 'post.php':
1198
+ case 'post-new.php':
1199
+ case 'settings_page_post-expirator':
1200
+ wp_enqueue_style( 'postexpirator-css', POSTEXPIRATOR_BASEURL . '/assets/css/style.css', array(), POSTEXPIRATOR_VERSION );
1201
+ break;
1202
+ case 'edit.php':
1203
+ wp_enqueue_style( 'postexpirator-edit', POSTEXPIRATOR_BASEURL . '/assets/css/edit.css', array(), POSTEXPIRATOR_VERSION );
1204
+ break;
1205
+ }
1206
+ }
1207
+ add_action( 'admin_enqueue_scripts', 'postexpirator_css', 10, 1 );
1208
+
1209
+ /**
1210
+ * Post Expirator Activation/Upgrade
1211
+ *
1212
+ * @internal
1213
+ *
1214
+ * @access private
1215
+ */
1216
+ function postexpirator_upgrade() {
1217
+
1218
+ // Check for current version, if not exists, run activation
1219
+ $version = get_option( 'postexpiratorVersion' );
1220
+ if ( $version === false ) { // not installed, run default activation
1221
+ postexpirator_activate();
1222
+ update_option( 'postexpiratorVersion', POSTEXPIRATOR_VERSION );
1223
+ } else {
1224
+ if ( version_compare( $version, '1.6.1' ) === -1 ) {
1225
+ update_option( 'postexpiratorVersion', POSTEXPIRATOR_VERSION );
1226
+ update_option( 'expirationdateDefaultDate', POSTEXPIRATOR_EXPIREDEFAULT );
1227
+ }
1228
+
1229
+ if ( version_compare( $version, '1.6.2' ) === -1 ) {
1230
+ update_option( 'postexpiratorVersion', POSTEXPIRATOR_VERSION );
1231
+ }
1232
+
1233
+ if ( version_compare( $version, '2.0.0-rc1' ) === -1 ) {
1234
+ global $wpdb;
1235
+
1236
+ // Schedule Events/Migrate Config
1237
+ $results = $wpdb->get_results( $wpdb->prepare( 'select post_id, meta_value from ' . $wpdb->postmeta . ' as postmeta, ' . $wpdb->posts . ' as posts where postmeta.post_id = posts.ID AND postmeta.meta_key = %s AND postmeta.meta_value >= %d', 'expiration-date', time() ) );
1238
+ foreach ( $results as $result ) {
1239
+ wp_schedule_single_event( $result->meta_value, 'postExpiratorExpire', array($result->post_id) );
1240
+ $opts = array();
1241
+ $opts['id'] = $result->post_id;
1242
+ $posttype = get_post_type( $result->post_id );
1243
+ if ( $posttype === 'page' ) {
1244
+ $opts['expireType'] = strtolower( get_option( 'expirationdateExpiredPageStatus', 'Draft' ) );
1245
+ } else {
1246
+ $opts['expireType'] = strtolower( get_option( 'expirationdateExpiredPostStatus', 'Draft' ) );
1247
+ }
1248
+
1249
+ $cat = get_post_meta( $result->post_id, '_expiration-date-category', true );
1250
+ if ( ( isset( $cat ) && ! empty( $cat ) ) ) {
1251
+ $opts['category'] = $cat;
1252
+ $opts['expireType'] = 'category';
1253
+ }
1254
+
1255
+ PostExpirator_Facade::set_expire_principles( $result->post_id, $opts );
1256
+
1257
+ }
1258
+
1259
+ // update meta key to new format
1260
+ $wpdb->query( $wpdb->prepare( "UPDATE $wpdb->postmeta SET meta_key = %s WHERE meta_key = %s", '_expiration-date', 'expiration-date' ) );
1261
+
1262
+ // migrate defaults
1263
+ $pagedefault = get_option( 'expirationdateExpiredPageStatus' );
1264
+ $postdefault = get_option( 'expirationdateExpiredPostStatus' );
1265
+ if ( $pagedefault ) {
1266
+ update_option( 'expirationdateDefaultsPage', array('expireType' => $pagedefault) );
1267
+ }
1268
+ if ( $postdefault ) {
1269
+ update_option( 'expirationdateDefaultsPost', array('expireType' => $postdefault) );
1270
+ }
1271
+
1272
+ delete_option( 'expirationdateCronSchedule' );
1273
+ delete_option( 'expirationdateAutoEnabled' );
1274
+ delete_option( 'expirationdateExpiredPageStatus' );
1275
+ delete_option( 'expirationdateExpiredPostStatus' );
1276
+ update_option( 'postexpiratorVersion', POSTEXPIRATOR_VERSION );
1277
+ }
1278
+
1279
+ if ( version_compare( $version, '2.0.1' ) === -1 ) {
1280
+ // Forgot to do this in 2.0.0
1281
+ if ( is_multisite() ) {
1282
+ global $current_blog;
1283
+ wp_clear_scheduled_hook( 'expirationdate_delete_' . $current_blog->blog_id );
1284
+ } else {
1285
+ wp_clear_scheduled_hook( 'expirationdate_delete' );
1286
+ }
1287
+
1288
+ update_option( 'postexpiratorVersion', POSTEXPIRATOR_VERSION );
1289
+ }
1290
+
1291
+ update_option( 'postexpiratorVersion', POSTEXPIRATOR_VERSION );
1292
+
1293
+ }
1294
+ }
1295
+ add_action( 'admin_init', 'postexpirator_upgrade' );
1296
+
1297
+ /**
1298
+ * Called at plugin activation
1299
+ *
1300
+ * @internal
1301
+ *
1302
+ * @access private
1303
+ */
1304
+ function postexpirator_activate() {
1305
+ if ( get_option( 'expirationdateDefaultDateFormat' ) === false ) {
1306
+ update_option( 'expirationdateDefaultDateFormat', POSTEXPIRATOR_DATEFORMAT );
1307
+ }
1308
+ if ( get_option( 'expirationdateDefaultTimeFormat' ) === false ) {
1309
+ update_option( 'expirationdateDefaultTimeFormat', POSTEXPIRATOR_TIMEFORMAT );
1310
+ }
1311
+ if ( get_option( 'expirationdateFooterContents' ) === false ) {
1312
+ update_option( 'expirationdateFooterContents', POSTEXPIRATOR_FOOTERCONTENTS );
1313
+ }
1314
+ if ( get_option( 'expirationdateFooterStyle' ) === false ) {
1315
+ update_option( 'expirationdateFooterStyle', POSTEXPIRATOR_FOOTERSTYLE );
1316
+ }
1317
+ if ( get_option( 'expirationdateDisplayFooter' ) === false ) {
1318
+ update_option( 'expirationdateDisplayFooter', POSTEXPIRATOR_FOOTERDISPLAY );
1319
+ }
1320
+ if ( get_option( 'expirationdateDebug' ) === false ) {
1321
+ update_option( 'expirationdateDebug', POSTEXPIRATOR_DEBUGDEFAULT );
1322
+ }
1323
+ if ( get_option( 'expirationdateDefaultDate' ) === false ) {
1324
+ update_option( 'expirationdateDefaultDate', POSTEXPIRATOR_EXPIREDEFAULT );
1325
+ }
1326
+ if ( get_option( 'expirationdateGutenbergSupport' ) === false ) {
1327
+ update_option( 'expirationdateGutenbergSupport', 1 );
1328
+ }
1329
+ }
1330
+
1331
+ /**
1332
+ * Called at plugin deactivation
1333
+ *
1334
+ * @internal
1335
+ *
1336
+ * @access private
1337
+ */
1338
+ function expirationdate_deactivate() {
1339
+ global $current_blog;
1340
+ delete_option( 'expirationdateExpiredPostStatus' );
1341
+ delete_option( 'expirationdateExpiredPageStatus' );
1342
+ delete_option( 'expirationdateDefaultDateFormat' );
1343
+ delete_option( 'expirationdateDefaultTimeFormat' );
1344
+ delete_option( 'expirationdateDisplayFooter' );
1345
+ delete_option( 'expirationdateFooterContents' );
1346
+ delete_option( 'expirationdateFooterStyle' );
1347
+ delete_option( 'expirationdateCategory' );
1348
+ delete_option( 'expirationdateCategoryDefaults' );
1349
+ delete_option( 'expirationdateDebug' );
1350
+ delete_option( 'postexpiratorVersion' );
1351
+ delete_option( 'expirationdateCronSchedule' );
1352
+ delete_option( 'expirationdateDefaultDate' );
1353
+ delete_option( 'expirationdateDefaultDateCustom' );
1354
+ delete_option( 'expirationdateAutoEnabled' );
1355
+ delete_option( 'expirationdateDefaultsPage' );
1356
+ delete_option( 'expirationdateDefaultsPost' );
1357
+ delete_option( 'expirationdateGutenbergSupport' );
1358
+ // what about custom post types? - how to cleanup?
1359
+ if ( is_multisite() ) {
1360
+ wp_clear_scheduled_hook( 'expirationdate_delete_' . $current_blog->blog_id );
1361
+ } else {
1362
+ wp_clear_scheduled_hook( 'expirationdate_delete' );
1363
+ }
1364
+ require_once( plugin_dir_path( __FILE__ ) . 'post-expirator-debug.php' );
1365
+ $debug = new PostExpiratorDebug();
1366
+ $debug->removeDbTable();
1367
+ }
1368
+ register_deactivation_hook( __FILE__, 'expirationdate_deactivate' );
1369
+
1370
+ /**
1371
+ * The walker class for category checklist.
1372
+ *
1373
+ * @internal
1374
+ *
1375
+ * @access private
1376
+ */
1377
+ class Walker_PostExpirator_Category_Checklist extends Walker {
1378
+
1379
+ /**
1380
+ * What the class handles.
1381
+ *
1382
+ * @var string
1383
+ */
1384
+ var $tree_type = 'category';
1385
+
1386
+ /**
1387
+ * DB fields to use.
1388
+ *
1389
+ * @var array
1390
+ */
1391
+ var $db_fields = array ('parent' => 'parent', 'id' => 'term_id'); // TODO: decouple this
1392
+
1393
+ /**
1394
+ * The disabled attribute.
1395
+ *
1396
+ * @var string
1397
+ */
1398
+ var $disabled = '';
1399
+
1400
+ /**
1401
+ * Set the disabled attribute.
1402
+ */
1403
+ function setDisabled() {
1404
+ $this->disabled = 'disabled="disabled"';
1405
+ }
1406
+
1407
+ /**
1408
+ * Starts the list before the elements are added.
1409
+ *
1410
+ * The $args parameter holds additional values that may be used with the child
1411
+ * class methods. This method is called at the start of the output list.
1412
+ *
1413
+ * @param string $output Used to append additional content (passed by reference).
1414
+ * @param int $depth Depth of the item.
1415
+ * @param array $args An array of additional arguments.
1416
+ */
1417
+ function start_lvl( &$output, $depth = 0, $args = array() ) {
1418
+ $indent = str_repeat( "\t", $depth );
1419
+ $output .= "$indent<ul class='children'>\n";
1420
+ }
1421
+
1422
+ /**
1423
+ * Ends the list of after the elements are added.
1424
+ *
1425
+ * The $args parameter holds additional values that may be used with the child
1426
+ * class methods. This method finishes the list at the end of output of the elements.
1427
+ *
1428
+ * @param string $output Used to append additional content (passed by reference).
1429
+ * @param int $depth Depth of the item.
1430
+ * @param array $args An array of additional arguments.
1431
+ */
1432
+ function end_lvl( &$output, $depth = 0, $args = array() ) {
1433
+ $indent = str_repeat( "\t", $depth );
1434
+ $output .= "$indent</ul>\n";
1435
+ }
1436
+
1437
+ /**
1438
+ * Start the element output.
1439
+ *
1440
+ * The $args parameter holds additional values that may be used with the child
1441
+ * class methods. Includes the element output also.
1442
+ *
1443
+ * @param string $output Used to append additional content (passed by reference).
1444
+ * @param object $category The data object.
1445
+ * @param int $depth Depth of the item.
1446
+ * @param array $args An array of additional arguments.
1447
+ * @param int $current_object_id ID of the current item.
1448
+ */
1449
+ function start_el( &$output, $category, $depth = 0, $args = array(), $current_object_id = 0 ) {
1450
+ // @TODO remove extract
1451
+ // phpcs:ignore WordPress.PHP.DontExtract.extract_extract
1452
+ extract( $args );
1453
+ if ( empty( $taxonomy ) ) {
1454
+ $taxonomy = 'category';
1455
+ }
1456
+
1457
+ $name = 'expirationdate_category';
1458
+
1459
+ $class = in_array( $category->term_id, $popular_cats, true ) ? ' class="expirator-category"' : '';
1460
+ $output .= "\n<li id='expirator-{$taxonomy}-{$category->term_id}'$class>" . '<label class="selectit"><input value="' . $category->term_id . '" type="checkbox" name="' . $name . '[]" id="expirator-in-' . $taxonomy . '-' . $category->term_id . '"' . checked( in_array( $category->term_id, $selected_cats, true ), true, false ) . disabled( empty( $args['disabled'] ), false, false ) . ' ' . $this->disabled . '/> ' . esc_html( apply_filters( 'the_category', $category->name ) ) . '</label>';
1461
+ }
1462
+
1463
+ /**
1464
+ * Ends the element output, if needed.
1465
+ *
1466
+ * The $args parameter holds additional values that may be used with the child class methods.
1467
+ *
1468
+ * @param string $output Used to append additional content (passed by reference).
1469
+ * @param object $category The data object.
1470
+ * @param int $depth Depth of the item.
1471
+ * @param array $args An array of additional arguments.
1472
+ */
1473
+ function end_el( &$output, $category, $depth = 0, $args = array() ) {
1474
+ $output .= "</li>\n";
1475
+ }
1476
+ }
1477
+
1478
+ /**
1479
+ * Get the HTML for expire type.
1480
+ *
1481
+ * @internal
1482
+ *
1483
+ * @access private
1484
+ */
1485
+ function _postexpirator_expire_type( $opts ) {
1486
+ if ( empty( $opts ) ) {
1487
+ return false;
1488
+ }
1489
+
1490
+ PostExpirator_Display::getInstance()->render_template( 'how-to-expire', array( 'opts' => $opts ) );
1491
+ }
1492
+
1493
+ /**
1494
+ * Get the HTML for taxonomy.
1495
+ *
1496
+ * @internal
1497
+ *
1498
+ * @access private
1499
+ */
1500
+ function _postexpirator_taxonomy( $opts ) {
1501
+ if ( empty( $opts ) ) {
1502
+ return false;
1503
+ }
1504
+
1505
+ // @TODO remove extract
1506
+ // phpcs:ignore WordPress.PHP.DontExtract.extract_extract
1507
+ extract( $opts );
1508
+ if ( ! isset( $name ) ) {
1509
+ return false;
1510
+ }
1511
+ if ( ! isset( $id ) ) {
1512
+ $id = $name;
1513
+ }
1514
+ if ( ! isset( $disabled ) ) {
1515
+ $disabled = false;
1516
+ }
1517
+ if ( ! isset( $onchange ) ) {
1518
+ $onchange = '';
1519
+ }
1520
+ if ( ! isset( $type ) ) {
1521
+ $type = '';
1522
+ }
1523
+
1524
+ $taxonomies = get_object_taxonomies( $type, 'object' );
1525
+ $taxonomies = wp_filter_object_list( $taxonomies, array('hierarchical' => true) );
1526
+
1527
+ if ( empty( $taxonomies ) ) {
1528
+ $disabled = true;
1529
+ }
1530
+
1531
+ $rv = array();
1532
+ if ( $taxonomies ) {
1533
+ // phpcs:ignore WordPress.PHP.StrictComparisons.LooseComparison
1534
+ $rv[] = '<select name="' . $name . '" id="' . $id . '"' . ( $disabled == true ? ' disabled="disabled"' : '' ) . ' onchange="' . $onchange . '">';
1535
+ foreach ( $taxonomies as $taxonomy ) {
1536
+ $rv[] = '<option value="' . $taxonomy->name . '" ' . ( $selected === $taxonomy->name ? 'selected="selected"' : '' ) . '>' . $taxonomy->label . '</option>';
1537
+ }
1538
+
1539
+ $rv[] = '</select>';
1540
+ $rv[] = '<p class="description">' . __( 'Select the hierarchical taxonomy to be used for "category" based expiration.', 'post-expirator' ) . '</p>';
1541
+ } else {
1542
+ $rv[] = __( 'No taxonomies found', 'post-expirator' );
1543
+ }
1544
+ return implode( "<br/>\n", $rv );
1545
+ }
1546
+
1547
+ /**
1548
+ * Include the JS.
1549
+ *
1550
+ * @internal
1551
+ *
1552
+ * @access private
1553
+ */
1554
+ function postexpirator_quickedit_javascript() {
1555
+ // if using code as plugin
1556
+ wp_enqueue_script( 'postexpirator-edit', POSTEXPIRATOR_BASEURL . '/assets/js/admin-edit.js', array( 'jquery', 'inline-edit-post' ), POSTEXPIRATOR_VERSION, true );
1557
+ wp_localize_script(
1558
+ 'postexpirator-edit', 'config', array(
1559
+ 'ajax' => array(
1560
+ 'nonce' => wp_create_nonce( POSTEXPIRATOR_SLUG ),
1561
+ 'bulk_edit' => 'manage_wp_posts_using_bulk_quick_save_bulk_edit',
1562
+ ),
1563
+ )
1564
+ );
1565
+ }
1566
+ add_action( 'admin_print_scripts-edit.php', 'postexpirator_quickedit_javascript' );
1567
+
1568
+ /**
1569
+ * Receives AJAX call from bulk edit to process save.
1570
+ *
1571
+ * @internal
1572
+ *
1573
+ * @access private
1574
+ */
1575
+ function postexpirator_date_save_bulk_edit() {
1576
+ check_ajax_referer( POSTEXPIRATOR_SLUG, 'nonce' );
1577
+
1578
+ // we need the post IDs
1579
+ $post_ids = ( isset( $_POST['post_ids'] ) && ! empty( $_POST['post_ids'] ) ) ? $_POST['post_ids'] : null;
1580
+
1581
+ // if we have post IDs
1582
+ if ( ! empty( $post_ids ) && is_array( $post_ids ) ) {
1583
+
1584
+ $status = $_POST['expirationdate_status'];
1585
+
1586
+ // if no change, do nothing
1587
+ if ( $status === 'no-change' ) {
1588
+ return;
1589
+ }
1590
+
1591
+ $month = intval( $_POST['expirationdate_month'] );
1592
+ $day = intval( $_POST['expirationdate_day'] );
1593
+ $year = intval( $_POST['expirationdate_year'] );
1594
+ $hour = intval( $_POST['expirationdate_hour'] );
1595
+ $minute = intval( $_POST['expirationdate_minute'] );
1596
+
1597
+ // default to current date and/or year if not provided by user.
1598
+ if ( empty( $day ) ) {
1599
+ $day = date( 'd' );
1600
+ }
1601
+ if ( empty( $year ) ) {
1602
+ $year = date( 'Y' );
1603
+ }
1604
+
1605
+ $ts = get_gmt_from_date( "$year-$month-$day $hour:$minute:0", 'U' );
1606
+
1607
+ if ( ! $ts ) {
1608
+ return;
1609
+ }
1610
+
1611
+ foreach ( $post_ids as $post_id ) {
1612
+ $ed = get_post_meta( $post_id, '_expiration-date', true );
1613
+ $update_expiry = false;
1614
+
1615
+ switch ( $status ) {
1616
+ case 'change-only':
1617
+ $update_expiry = ! empty( $ed );
1618
+ break;
1619
+ case 'add-only':
1620
+ $update_expiry = empty( $ed );
1621
+ break;
1622
+ case 'change-add':
1623
+ $update_expiry = true;
1624
+ break;
1625
+ case 'remove-only':
1626
+ delete_post_meta( $post_id, '_expiration-date' );
1627
+ postexpirator_unschedule_event( $post_id );
1628
+ break;
1629
+ }
1630
+
1631
+ if ( $update_expiry ) {
1632
+ $opts = PostExpirator_Facade::get_expire_principles( $post_id );
1633
+ $opts['expireType'] = $_POST['expirationdate_expiretype'];
1634
+
1635
+ if ( in_array( $opts['expireType'], array( 'category', 'category-add', 'category-remove' ), true ) ) {
1636
+ $opts['category'] = $_POST['expirationdate_category'];
1637
+ }
1638
+
1639
+ PostExpirator_Facade::set_expire_principles( $post_id, $opts );
1640
+ update_post_meta( $post_id, '_expiration-date', $ts );
1641
+ postexpirator_schedule_event( $post_id, $ts, null );
1642
+ }
1643
+ }
1644
+ }
1645
+ }
1646
+ add_action( 'wp_ajax_manage_wp_posts_using_bulk_quick_save_bulk_edit', 'postexpirator_date_save_bulk_edit' );
1647
+
1648
+ /**
1649
+ * Autoloads the classes.
1650
+ */
1651
+ function postexpirator_autoload( $class ) {
1652
+ $namespaces = array( 'PostExpirator' );
1653
+ foreach ( $namespaces as $namespace ) {
1654
+ if ( substr( $class, 0, strlen( $namespace ) ) === $namespace ) {
1655
+ $class = str_replace( '_', '', strstr( $class, '_' ) );
1656
+ $filename = plugin_dir_path( __FILE__ ) . 'classes/' . sprintf( '%s.class.php', $class );
1657
+ if ( is_readable( $filename ) ) {
1658
+ require_once $filename;
1659
+ return true;
1660
+ }
1661
+ }
1662
+ }
1663
+ return false;
1664
+ }
1665
+ spl_autoload_register( 'postexpirator_autoload' );
1666
+
1667
+ /**
1668
+ * Launch the plugin by initializing its helpers.
1669
+ */
1670
+ function postexpirator_launch() {
1671
+ PostExpirator_Facade::getInstance();
1672
+ }
1673
+ postexpirator_launch();
1674
+
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
readme.txt CHANGED
@@ -1,359 +1,346 @@
1
- === Post Expirator: Schedule WordPress Posts to Automatically Unpublish ===
2
- Contributors: publishpress, kevinB, stevejburge, andergmartins
3
- Author: publishpress
4
- Author URI: https://publishpress.com
5
- Tags: expire, posts, pages, schedule
6
- Requires at least: 4.0
7
- Tested up to: 5.8
8
- Stable tag: 2.4.4
9
-
10
- Add an expiration date to posts. When your post is automatically unpublished, you can delete the post, change the status, or update the post categories.
11
-
12
- == Description ==
13
-
14
- The Post Expirator plugin allows you to add an expiration date to posts. pages and other content type. When your post is automatically unpublished, you can delete the post, change the status, or update the post categories.
15
-
16
- Here's an overview of what you can do with Post Expirator:
17
-
18
- * Choose expiry dates for content in any post type.
19
- * Select expiry dates in the right sidebar when editing posts.
20
- * Modify, remove or completely delete content when the expiry date arrives.
21
- * Modify expiry dates using "Quick Edit" and "Bulk Edit".
22
- * Receive email notifications when your content expires.
23
- * Show expiry dates in your content, automatically or with shortcodes.
24
-
25
- ## Options for Expiring Posts
26
-
27
- When your posts expire, you can perform these changes on your content:
28
-
29
- * Change the status to "Draft".
30
- * Delete the post.
31
- * Send the post to the Trash.
32
- * Change the status to "Private".
33
- * Enable the “Stick to the top of the blog” option.
34
- * Disable the “Stick to the top of the blog” option.
35
- * Remove all existing categories, and add new categories.
36
- * Keep all existing categories, and add new categories.
37
- * Keep all existing categories, except for those specified in this change.
38
-
39
- [Click here for more details on expiring posts](https://publishpress.com/knowledge-base/ways-to-expire-posts/).
40
-
41
- ## Display the Expiry Date in Your Content
42
-
43
- Post Expirator allows you to place automatically show the expiry date inside your articles. The expiry will be added at the bottom of your post.
44
-
45
- [Click here to see the Footer Display options](https://publishpress.com/knowledge-base/footer-display/).
46
-
47
- You can use shortcodes to show the expiration date inside your posts. You can customize the shortcode output with several formatting options.
48
-
49
- [Click here to see the shortcode options](https://publishpress.com/knowledge-base/shortcodes-to-show-expiration-date/).
50
-
51
- ## Expiry Defaults for Post Types
52
-
53
- Post Expirator can support any post type in WordPress. Go to Settings > Post Expirator > Defaults and you can choose default expiry options for each post type.
54
-
55
- [Click here to see the default options](https://publishpress.com/knowledge-base/defaults-for-post-types/).
56
-
57
- ## Post Expirator Email Notifications
58
-
59
- The Post Expirator plugin can send you email notifications when your content is unpublished. You can control the emails by going to Settings > Post Expirator > General Settings.
60
-
61
- [Click here to see the notification options](https://publishpress.com/knowledge-base/email-notifications/).
62
-
63
- ## Details on How Post Expiry Works
64
-
65
- For each expiration event, a custom cron job is scheduled. This can help reduce server overhead for busy sites. This plugin REQUIRES that WP-CRON is setup and functional on your webhost. Some hosts do not support this, so please check and confirm if you run into issues using the plugin.
66
-
67
- [Click here to see the technical details for this plugin](https://publishpress.com/knowledge-base/scheduling-cron-jobs/).
68
-
69
- = Join PublishPress and get the Pro plugins =
70
-
71
- The Pro versions of the PublishPress plugins are well worth your investment. The Pro versions have extra features and faster support. [Click here to join PublishPress](https://publishpress.com/pricing/).
72
-
73
- Join PublishPress and you'll get access to these Pro plugins:
74
-
75
- * [PublishPress Authors Pro](https://publishpress.com/authors) allows you to add multiple authors and guest authors to WordPress posts.
76
- * [PublishPress Blocks Pro](https://publishpress.com/blocks) has everything you need to build professional websites with the WordPress block editor.
77
- * [PublishPress Capabilities Pro](https://publishpress.com/capabilities) is the plugin to manage your WordPress user roles, permissions, and capabilities.
78
- * [PublishPress Checklists Pro](https://publishpress.com/checklists) enables you to define tasks that must be completed before content is published.
79
- * [PublishPress Permissions Pro](https://publishpress.com/permissions) is the plugin for advanced WordPress permissions.
80
- * [PublishPress Pro](https://publishpress.com/publishpress) is the plugin for managing and scheduling WordPress content.
81
- * [PublishPress Revisions Pro](https://publishpress.com/revisions) allows you to update your published pages with teamwork and precision.
82
- * [PublishPress Series Pro](https://publishpress.com/series) enables you to group content together into a series
83
-
84
- Together, these plugins are a suite of powerful publishing tools for WordPress. If you need to create a professional workflow in WordPress, with moderation, revisions, permissions and more... then you should try PublishPress.
85
-
86
-
87
- == Installation ==
88
-
89
- This section describes how to install the plugin and get it working.
90
-
91
- 1. Unzip the plugin contents to the `/wp-content/plugins/post-expirator/` directory
92
- 2. Activate the plugin through the 'Plugins' menu in WordPress
93
-
94
- == Screenshots ==
95
-
96
- 1. Adding expiration date to a post
97
- 2. Viewing the expiration dates on the post overview screen
98
- 3. Settings screen
99
-
100
- == Screenshots ==
101
-
102
- 1. Adding expiration date to a post
103
- 2. Viewing the expiration dates on the post overview screen
104
- 3. Settings screen
105
-
106
- == Changelog ==
107
-
108
- = [2.4.4] - 22 Jul 2021 =
109
-
110
- * Fixed: Fix conflict with the plugin WCFM, #60;
111
- * Fixed: Fix the Category: Remove option, #61;
112
-
113
- = [2.4.3] - 07 Jul 2021 =
114
-
115
- * Added: Expose wrappers for legacy functions, #40;
116
- * Added: Support for quotes in Default expiry, #43;
117
- * Fixed: Default expiry duration is broken for future years, #39;
118
- * Fixed: Translation bug, #5;
119
- * Fixed: Post expiring one year early, #24;
120
- * Changed: Bulk and Quick Edit boxes default to current date/year, #46;
121
-
122
- = [2.4.2] =
123
-
124
- * Fixed: Bulk edit does not change scheduled event bug, #29;
125
- * Fixed: Date not being translated in shortcode, #16;
126
- * Fixed: Bulk Edit doesn't work, #4;
127
-
128
- = [2.4.1] =
129
-
130
- * Fix: Updated deprecated .live jQuery reference.
131
-
132
- = [2.4.0] =
133
-
134
- * Fix: Fixed PHP Error with PHP 7.
135
-
136
- = [2.3.1] =
137
-
138
- * Fix: Fixed PHP Error that snuck in on some installations.
139
-
140
- = [2.3.0] =
141
-
142
- * New: Email notification upon post expiration. A global email can be set, blog admins can be selected and/or specific users based on post type can be notified.
143
- * New: Expiration Option Added - Stick/Unstick post is now available.
144
- * New: Expiration Option Added - Trash post is now available.
145
- * New: Added custom actions that can be hooked into when expiration events are scheduled / unscheduled.
146
- * Fix: Minor HTML Code Issues
147
-
148
- = [2.2.2] =
149
-
150
- * Fix: Quick Edit did not retain the expire type setting, and defaulted back to "Draft". This has been resolved.
151
-
152
- = [2.2.1] =
153
-
154
- * Fix: Fixed issue with bulk edit not correctly updating the expiration date.
155
-
156
- = [2.2.0] =
157
-
158
- * New: Quick Edit - setting expiration date and toggling post expiration status can now be done via quick edit.
159
- * New: Bulk Edit - changing expiration date on posts that already are configured can now be done via bulk edit.
160
- * New: Added ability to order by Expiration Date in dashboard.
161
- * New: Adjusted formatting on defaults page. Multiple post types are now displayed cleaner.
162
- * Fix: Minor Code Cleanup
163
-
164
- = [2.1.4] =
165
-
166
- * Fix: PHP Strict errors with 5.4+
167
- * Fix: Removed temporary timezone conversion - now using core functions again
168
-
169
- = [2.1.3] =
170
-
171
- * Fix: Default category selection now saves correctly on default settings screen
172
-
173
- = [2.1.2] =
174
-
175
- * Security: Added form nonce for protect against possible CSRF
176
- * Security: Fixed XSS issue on settings pages
177
- * New: Added check to show if WP_CRON is enabled on diagnostics page
178
- * Fix: Minor Code Cleanup
179
-
180
- = [2.1.1] =
181
-
182
- * New: Added the option to disable post expirator for certain post types if desired
183
- * Fix: Fixed php warning issue cause when post type defaults are not set
184
-
185
- = [2.1.0] =
186
-
187
- * New: Added support for hierarchical custom taxonomy
188
- * New: Enhanced custom post type support
189
- * Fix: Updated debug function to be friendly for scripted calls
190
- * Fix: Change to only show public custom post types on defaults screen
191
- * Fix: Removed category expiration options for 'pages', which is currently unsupported
192
- * Fix: Some date calls were getting "double" converted for the timezone pending how other plugins handled date - this issue should now be resolved
193
-
194
- = [2.0.1] =
195
-
196
- * Removes old scheduled hook - this was not done completely in the 2.0.0 upgrade
197
- * Old option cleanup
198
-
199
- = [2.0.0] =
200
-
201
- This is a major update of the core functions of this plugin. All current plugins and settings should be upgraded to the new formats and work as expected. Any posts currently schedule to be expirated in the future will be automatically upgraded to the new format.
202
-
203
- * New: Improved debug calls and logging
204
- * New: Added the ability to expire to a "private" post
205
- * New: Added the ability to expire by adding or removing categories. The old way of doing things is now known as replacing categories
206
- * New: Revamped the expiration process - the plugin no longer runs on an minute, hourly, or other schedule. Each expiration event schedules a unique event to run, conserving system resources and making things more efficient
207
- * New: The type of expiration event can be selected for each post, directly from the post editing screen
208
- * New: Ability to set defaults for each post type (including custom posts)
209
- * New: Renamed expiration-date meta value to _expiration-date
210
- * New: Revamped timezone handling to be more correct with WordPress standards and fix conflicts with other plugins
211
- * New: 'Expires' column on post display table now uses the default date/time formats set for the blog
212
- * Fix: Removed kses filter calls when then schedule task runs that was causing code entered as unfiltered_html to be removed
213
- * Fix: Updated some calls of date to now use date_i18n
214
- * Fix: Most (if not all) php error/warnings should be addressed
215
- * Fix: Updated wpdb calls in the debug class to use wpdb_prepare correctly
216
- * Fix: Changed menu capability option from "edit_plugin" to "manage_options"
217
-
218
- = [1.6.2] =
219
-
220
- * Added the ability to configure the post expirator to be enabled by default for all new posts
221
- * Changed some instances of mktime to time
222
- * Fixed missing global call for MS installs
223
-
224
- = [1.6.1] =
225
-
226
- * Tweaked error messages, removed clicks for reset cron event
227
- * Switched cron schedule functions to use "current_time('timestamp')"
228
- * Cleaned up default values code
229
- * Added option to allow user to select any cron schedule (minute, hourly, twicedaily, daily) - including other defined schedules
230
- * Added option to set default expiration duration - options are none, custom, or publish time
231
- * Code cleanup - php notice
232
-
233
- = [1.6] =
234
-
235
- * Fixed invalid html
236
- * Fixed i18n issues with dates
237
- * Fixed problem when using "Network Activate" - reworked plugin activation process
238
- * Replaced "Upgrade" tab with new "Diagnostics" tab
239
- * Reworked expire logic to limit the number of sql queries needed
240
- * Added debugging
241
- * Various code cleanup
242
-
243
- = [1.5.4] =
244
-
245
- * Cleaned up deprecated function calls
246
-
247
- = [1.5.3] =
248
-
249
- * Fixed bug with sql expiration query (props to Robert & John)
250
-
251
- = [1.5.2] =
252
-
253
- * Fixed bug with shortcode that was displaying the expiration date in the incorrect timezone
254
- * Fixed typo on settings page with incorrect shortcode name
255
-
256
- = [1.5.1] =
257
-
258
- * Fixed bug that was not allow custom post types to work
259
-
260
- = [1.5] =
261
-
262
- * Moved Expirator Box to Sidebar and cleaned up meta code
263
- * Added ability to expire post to category
264
-
265
- = [1.4.3] =
266
-
267
- * Fixed issue with 3.0 multisite detection
268
-
269
- = [1.4.2] =
270
-
271
- * Added post expirator POT to /languages folder
272
- * Fixed issue with plugin admin navigation
273
- * Fixed timezone issue on plugin options screen
274
-
275
- = [1.4.1] =
276
-
277
- * Added support for custom post types (Thanks Thierry)
278
- * Added i18n support (Thanks Thierry)
279
- * Fixed issue where expiration date was not shown in the correct timezone in the footer
280
- * Fixed issue where on some systems the expiration did not happen when scheduled
281
-
282
- = [1.4] =
283
-
284
- NOTE: After upgrading, you may need to reset the cron schedules. Following onscreen notice if prompted. Previously scheduled posts will not be updated, they will be deleted referncing the old timezone setting. If you wish to update them, you will need to manually update the expiration time.
285
-
286
- * Fixed compatability issues with Wordpress - plugin was originally coded for WPMU - should now work on both
287
- * Added ability to schedule post expiration by minute
288
- * Fixed timezone - now uses the same timezone as configured by the blog
289
-
290
- = [1.3.1] =
291
-
292
- * Fixed sporadic issue of expired posts not being removed
293
-
294
- = [1.3] =
295
-
296
- * Expiration date is now retained across all post status changes
297
- * Modified date/time format options for shortcode postexpirator tag
298
- * Added the ability to add text automatically to the post footer if expiration date is set
299
-
300
- = [1.2.1] =
301
-
302
- * Fixed issue with display date format not being recognized after upgrade
303
-
304
- = [1.2] =
305
-
306
- * Changed wording from "Expiration Date" to "Post Expirator" and moved the configuration options to the "Settings" tab.
307
- * Added shortcode tag [postexpirator] to display the post expiration date within the post
308
- ** Added new setting for the default format
309
- * Fixed bug where expiration date was removed when a post was auto saved
310
-
311
- = [1.1] =
312
-
313
- * Expired posts retain expiration date
314
-
315
- = [1.0] =
316
-
317
- * Initial Release
318
-
319
- == Upgrade Notice ==
320
-
321
- = 2.2.0 =
322
- Quick Edit/Bulk Edit Added. Sortable Expiration Date Fields Added
323
-
324
- = 2.1.4 =
325
- Fixed PHP Strict errors with 5.4+
326
- Removed temporary timezone conversion functions
327
-
328
-
329
- = 2.1.3 =
330
- Default category selection now saves correctly on default settings screen
331
-
332
- = 2.1.2 =
333
- Important Update - Security Fixes - See Changelog
334
-
335
- = 2.0.1 =
336
- Removes old scheduled hook - this was not done completely in the 2.0.0 upgrade
337
-
338
- = 2.0.0 =
339
- This is a major update of the core functions of this plugin. All current plugins and settings should be upgraded to the new formats and work as expected. Any posts currently schedule to be expirated in the future will be automatically upgraded to the new format.
340
-
341
- = 1.6.1 =
342
- Tweaked error messages, added option to allow user to select cron schedule and set default exiration duration
343
-
344
- = 1.6 =
345
- Fixed invalid html
346
- Fixed i18n issues with dates
347
- Fixed problem when using "Network Activate" - reworked plugin activation process
348
- Replaced "Upgrade" tab with new "Diagnostics" tab
349
- Reworked expire logic to limit the number of sql queries needed
350
- Added debugging
351
-
352
- = 1.5.4 =
353
- Cleaned up deprecated function calls
354
-
355
- = 1.5.3 =
356
- Fixed bug with sql expiration query (props to Robert & John)
357
-
358
- = 1.5.2 =
359
- Fixed shortcode timezone issue
1
+ === Post Expirator: Automatically Unpublish WordPress Posts ===
2
+ Contributors: publishpress, kevinB, stevejburge, andergmartins
3
+ Author: publishpress
4
+ Author URI: https://publishpress.com
5
+ Tags: expire, posts, pages, schedule
6
+ Requires at least: 4.0
7
+ Tested up to: 5.8
8
+ Stable tag: 2.5.0
9
+
10
+ Add an expiration date to posts. When your post is automatically unpublished, you can delete the post, change the status, or update the post categories.
11
+
12
+ == Description ==
13
+
14
+ The Post Expirator plugin allows you to add an expiration date to posts. pages and other content type. When your post is automatically unpublished, you can delete the post, change the status, or update the post categories.
15
+
16
+ Here's an overview of what you can do with Post Expirator:
17
+
18
+ * Choose expiry dates for content in any post type.
19
+ * Select expiry dates in the right sidebar when editing posts.
20
+ * Modify, remove or completely delete content when the expiry date arrives.
21
+ * Modify expiry dates using "Quick Edit" and "Bulk Edit".
22
+ * Receive email notifications when your content expires.
23
+ * Show expiry dates in your content, automatically or with shortcodes.
24
+
25
+ ## Options for Expiring Posts
26
+
27
+ When your posts expire, you can perform these changes on your content:
28
+
29
+ * Change the status to "Draft".
30
+ * Delete the post.
31
+ * Send the post to the Trash.
32
+ * Change the status to "Private".
33
+ * Enable the “Stick to the top of the blog” option.
34
+ * Disable the “Stick to the top of the blog” option.
35
+ * Remove all existing categories, and add new categories.
36
+ * Keep all existing categories, and add new categories.
37
+ * Keep all existing categories, except for those specified in this change.
38
+
39
+ [Click here for more details on expiring posts](https://publishpress.com/knowledge-base/ways-to-expire-posts/).
40
+
41
+ ## Display the Expiry Date in Your Content
42
+
43
+ Post Expirator allows you to place automatically show the expiry date inside your articles. The expiry will be added at the bottom of your post.
44
+
45
+ [Click here to see the Footer Display options](https://publishpress.com/knowledge-base/footer-display/).
46
+
47
+ You can use shortcodes to show the expiration date inside your posts. You can customize the shortcode output with several formatting options.
48
+
49
+ [Click here to see the shortcode options](https://publishpress.com/knowledge-base/shortcodes-to-show-expiration-date/).
50
+
51
+ ## Expiry Defaults for Post Types
52
+
53
+ Post Expirator can support any post type in WordPress. Go to Settings > Post Expirator > Defaults and you can choose default expiry options for each post type.
54
+
55
+ [Click here to see the default options](https://publishpress.com/knowledge-base/defaults-for-post-types/).
56
+
57
+ ## Post Expirator Email Notifications
58
+
59
+ The Post Expirator plugin can send you email notifications when your content is unpublished. You can control the emails by going to Settings > Post Expirator > General Settings.
60
+
61
+ [Click here to see the notification options](https://publishpress.com/knowledge-base/email-notifications/).
62
+
63
+ ## Details on How Post Expiry Works
64
+
65
+ For each expiration event, a custom cron job is scheduled. This can help reduce server overhead for busy sites. This plugin REQUIRES that WP-CRON is setup and functional on your webhost. Some hosts do not support this, so please check and confirm if you run into issues using the plugin.
66
+
67
+ [Click here to see the technical details for this plugin](https://publishpress.com/knowledge-base/scheduling-cron-jobs/).
68
+
69
+ == Installation ==
70
+
71
+ This section describes how to install the plugin and get it working.
72
+
73
+ 1. Unzip the plugin contents to the `/wp-content/plugins/post-expirator/` directory
74
+ 2. Activate the plugin through the 'Plugins' menu in WordPress
75
+
76
+ == Screenshots ==
77
+
78
+ 1. Adding expiration date to a post
79
+ 2. Viewing the expiration dates on the post overview screen
80
+ 3. Settings screen
81
+
82
+ == Changelog ==
83
+
84
+ = [2.5.0] - 08 Aug 2021 =
85
+
86
+ * Fixed: Appearance Widgets screen shows PHP Notice, #92;
87
+ * Fixed: Stop the Post Expirator box from appearing in non-public post types, #78;
88
+ * Added: Add "How to Expire" to Quick Edit, #62;
89
+ * Changed: Settings UI enhancement, #14;
90
+ * Fixed: Hide metabox from Media Library files, #56;
91
+ * Added: Support for Gutenberg block editor, #10;
92
+ * Added: Set a default time per post type, #12;
93
+
94
+
95
+ = [2.4.4] - 22 Jul 2021 =
96
+
97
+ * Fixed: Fix conflict with the plugin WCFM, #60;
98
+ * Fixed: Fix the Category: Remove option, #61;
99
+
100
+ = [2.4.3] - 07 Jul 2021 =
101
+
102
+ * Added: Expose wrappers for legacy functions, #40;
103
+ * Added: Support for quotes in Default expiry, #43;
104
+ * Fixed: Default expiry duration is broken for future years, #39;
105
+ * Fixed: Translation bug, #5;
106
+ * Fixed: Post expiring one year early, #24;
107
+ * Changed: Bulk and Quick Edit boxes default to current date/year, #46;
108
+
109
+ = [2.4.2] =
110
+
111
+ * Fixed: Bulk edit does not change scheduled event bug, #29;
112
+ * Fixed: Date not being translated in shortcode, #16;
113
+ * Fixed: Bulk Edit doesn't work, #4;
114
+
115
+ = [2.4.1] =
116
+
117
+ * Fix: Updated deprecated .live jQuery reference.
118
+
119
+ = [2.4.0] =
120
+
121
+ * Fix: Fixed PHP Error with PHP 7.
122
+
123
+ = [2.3.1] =
124
+
125
+ * Fix: Fixed PHP Error that snuck in on some installations.
126
+
127
+ = [2.3.0] =
128
+
129
+ * New: Email notification upon post expiration. A global email can be set, blog admins can be selected and/or specific users based on post type can be notified.
130
+ * New: Expiration Option Added - Stick/Unstick post is now available.
131
+ * New: Expiration Option Added - Trash post is now available.
132
+ * New: Added custom actions that can be hooked into when expiration events are scheduled / unscheduled.
133
+ * Fix: Minor HTML Code Issues
134
+
135
+ = [2.2.2] =
136
+
137
+ * Fix: Quick Edit did not retain the expire type setting, and defaulted back to "Draft". This has been resolved.
138
+
139
+ = [2.2.1] =
140
+
141
+ * Fix: Fixed issue with bulk edit not correctly updating the expiration date.
142
+
143
+ = [2.2.0] =
144
+
145
+ * New: Quick Edit - setting expiration date and toggling post expiration status can now be done via quick edit.
146
+ * New: Bulk Edit - changing expiration date on posts that already are configured can now be done via bulk edit.
147
+ * New: Added ability to order by Expiration Date in dashboard.
148
+ * New: Adjusted formatting on defaults page. Multiple post types are now displayed cleaner.
149
+ * Fix: Minor Code Cleanup
150
+
151
+ = [2.1.4] =
152
+
153
+ * Fix: PHP Strict errors with 5.4+
154
+ * Fix: Removed temporary timezone conversion - now using core functions again
155
+
156
+ = [2.1.3] =
157
+
158
+ * Fix: Default category selection now saves correctly on default settings screen
159
+
160
+ = [2.1.2] =
161
+
162
+ * Security: Added form nonce for protect against possible CSRF
163
+ * Security: Fixed XSS issue on settings pages
164
+ * New: Added check to show if WP_CRON is enabled on diagnostics page
165
+ * Fix: Minor Code Cleanup
166
+
167
+ = [2.1.1] =
168
+
169
+ * New: Added the option to disable post expirator for certain post types if desired
170
+ * Fix: Fixed php warning issue cause when post type defaults are not set
171
+
172
+ = [2.1.0] =
173
+
174
+ * New: Added support for hierarchical custom taxonomy
175
+ * New: Enhanced custom post type support
176
+ * Fix: Updated debug function to be friendly for scripted calls
177
+ * Fix: Change to only show public custom post types on defaults screen
178
+ * Fix: Removed category expiration options for 'pages', which is currently unsupported
179
+ * Fix: Some date calls were getting "double" converted for the timezone pending how other plugins handled date - this issue should now be resolved
180
+
181
+ = [2.0.1] =
182
+
183
+ * Removes old scheduled hook - this was not done completely in the 2.0.0 upgrade
184
+ * Old option cleanup
185
+
186
+ = [2.0.0] =
187
+
188
+ This is a major update of the core functions of this plugin. All current plugins and settings should be upgraded to the new formats and work as expected. Any posts currently schedule to be expirated in the future will be automatically upgraded to the new format.
189
+
190
+ * New: Improved debug calls and logging
191
+ * New: Added the ability to expire to a "private" post
192
+ * New: Added the ability to expire by adding or removing categories. The old way of doing things is now known as replacing categories
193
+ * New: Revamped the expiration process - the plugin no longer runs on an minute, hourly, or other schedule. Each expiration event schedules a unique event to run, conserving system resources and making things more efficient
194
+ * New: The type of expiration event can be selected for each post, directly from the post editing screen
195
+ * New: Ability to set defaults for each post type (including custom posts)
196
+ * New: Renamed expiration-date meta value to _expiration-date
197
+ * New: Revamped timezone handling to be more correct with WordPress standards and fix conflicts with other plugins
198
+ * New: 'Expires' column on post display table now uses the default date/time formats set for the blog
199
+ * Fix: Removed kses filter calls when then schedule task runs that was causing code entered as unfiltered_html to be removed
200
+ * Fix: Updated some calls of date to now use date_i18n
201
+ * Fix: Most (if not all) php error/warnings should be addressed
202
+ * Fix: Updated wpdb calls in the debug class to use wpdb_prepare correctly
203
+ * Fix: Changed menu capability option from "edit_plugin" to "manage_options"
204
+
205
+ = [1.6.2] =
206
+
207
+ * Added the ability to configure the post expirator to be enabled by default for all new posts
208
+ * Changed some instances of mktime to time
209
+ * Fixed missing global call for MS installs
210
+
211
+ = [1.6.1] =
212
+
213
+ * Tweaked error messages, removed clicks for reset cron event
214
+ * Switched cron schedule functions to use "current_time('timestamp')"
215
+ * Cleaned up default values code
216
+ * Added option to allow user to select any cron schedule (minute, hourly, twicedaily, daily) - including other defined schedules
217
+ * Added option to set default expiration duration - options are none, custom, or publish time
218
+ * Code cleanup - php notice
219
+
220
+ = [1.6] =
221
+
222
+ * Fixed invalid html
223
+ * Fixed i18n issues with dates
224
+ * Fixed problem when using "Network Activate" - reworked plugin activation process
225
+ * Replaced "Upgrade" tab with new "Diagnostics" tab
226
+ * Reworked expire logic to limit the number of sql queries needed
227
+ * Added debugging
228
+ * Various code cleanup
229
+
230
+ = [1.5.4] =
231
+
232
+ * Cleaned up deprecated function calls
233
+
234
+ = [1.5.3] =
235
+
236
+ * Fixed bug with sql expiration query (props to Robert & John)
237
+
238
+ = [1.5.2] =
239
+
240
+ * Fixed bug with shortcode that was displaying the expiration date in the incorrect timezone
241
+ * Fixed typo on settings page with incorrect shortcode name
242
+
243
+ = [1.5.1] =
244
+
245
+ * Fixed bug that was not allow custom post types to work
246
+
247
+ = [1.5] =
248
+
249
+ * Moved Expirator Box to Sidebar and cleaned up meta code
250
+ * Added ability to expire post to category
251
+
252
+ = [1.4.3] =
253
+
254
+ * Fixed issue with 3.0 multisite detection
255
+
256
+ = [1.4.2] =
257
+
258
+ * Added post expirator POT to /languages folder
259
+ * Fixed issue with plugin admin navigation
260
+ * Fixed timezone issue on plugin options screen
261
+
262
+ = [1.4.1] =
263
+
264
+ * Added support for custom post types (Thanks Thierry)
265
+ * Added i18n support (Thanks Thierry)
266
+ * Fixed issue where expiration date was not shown in the correct timezone in the footer
267
+ * Fixed issue where on some systems the expiration did not happen when scheduled
268
+
269
+ = [1.4] =
270
+
271
+ NOTE: After upgrading, you may need to reset the cron schedules. Following onscreen notice if prompted. Previously scheduled posts will not be updated, they will be deleted referncing the old timezone setting. If you wish to update them, you will need to manually update the expiration time.
272
+
273
+ * Fixed compatability issues with Wordpress - plugin was originally coded for WPMU - should now work on both
274
+ * Added ability to schedule post expiration by minute
275
+ * Fixed timezone - now uses the same timezone as configured by the blog
276
+
277
+ = [1.3.1] =
278
+
279
+ * Fixed sporadic issue of expired posts not being removed
280
+
281
+ = [1.3] =
282
+
283
+ * Expiration date is now retained across all post status changes
284
+ * Modified date/time format options for shortcode postexpirator tag
285
+ * Added the ability to add text automatically to the post footer if expiration date is set
286
+
287
+ = [1.2.1] =
288
+
289
+ * Fixed issue with display date format not being recognized after upgrade
290
+
291
+ = [1.2] =
292
+
293
+ * Changed wording from "Expiration Date" to "Post Expirator" and moved the configuration options to the "Settings" tab.
294
+ * Added shortcode tag [postexpirator] to display the post expiration date within the post
295
+ ** Added new setting for the default format
296
+ * Fixed bug where expiration date was removed when a post was auto saved
297
+
298
+ = [1.1] =
299
+
300
+ * Expired posts retain expiration date
301
+
302
+ = [1.0] =
303
+
304
+ * Initial Release
305
+
306
+ == Upgrade Notice ==
307
+
308
+ = 2.2.0 =
309
+ Quick Edit/Bulk Edit Added. Sortable Expiration Date Fields Added
310
+
311
+ = 2.1.4 =
312
+ Fixed PHP Strict errors with 5.4+
313
+ Removed temporary timezone conversion functions
314
+
315
+
316
+ = 2.1.3 =
317
+ Default category selection now saves correctly on default settings screen
318
+
319
+ = 2.1.2 =
320
+ Important Update - Security Fixes - See Changelog
321
+
322
+ = 2.0.1 =
323
+ Removes old scheduled hook - this was not done completely in the 2.0.0 upgrade
324
+
325
+ = 2.0.0 =
326
+ This is a major update of the core functions of this plugin. All current plugins and settings should be upgraded to the new formats and work as expected. Any posts currently schedule to be expirated in the future will be automatically upgraded to the new format.
327
+
328
+ = 1.6.1 =
329
+ Tweaked error messages, added option to allow user to select cron schedule and set default exiration duration
330
+
331
+ = 1.6 =
332
+ Fixed invalid html
333
+ Fixed i18n issues with dates
334
+ Fixed problem when using "Network Activate" - reworked plugin activation process
335
+ Replaced "Upgrade" tab with new "Diagnostics" tab
336
+ Reworked expire logic to limit the number of sql queries needed
337
+ Added debugging
338
+
339
+ = 1.5.4 =
340
+ Cleaned up deprecated function calls
341
+
342
+ = 1.5.3 =
343
+ Fixed bug with sql expiration query (props to Robert & John)
344
+
345
+ = 1.5.2 =
346
+ Fixed shortcode timezone issue
 
 
 
 
 
 
 
 
 
 
 
 
 
vendor/autoload.php ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ // autoload.php @generated by Composer
4
+
5
+ require_once __DIR__ . '/composer/autoload_real.php';
6
+
7
+ return ComposerAutoloaderInit252d08f02d77dcc4a9b095ab08120c6d::getLoader();
vendor/composer/ClassLoader.php ADDED
@@ -0,0 +1,445 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*
4
+ * This file is part of Composer.
5
+ *
6
+ * (c) Nils Adermann <naderman@naderman.de>
7
+ * Jordi Boggiano <j.boggiano@seld.be>
8
+ *
9
+ * For the full copyright and license information, please view the LICENSE
10
+ * file that was distributed with this source code.
11
+ */
12
+
13
+ namespace Composer\Autoload;
14
+
15
+ /**
16
+ * ClassLoader implements a PSR-0, PSR-4 and classmap class loader.
17
+ *
18
+ * $loader = new \Composer\Autoload\ClassLoader();
19
+ *
20
+ * // register classes with namespaces
21
+ * $loader->add('Symfony\Component', __DIR__.'/component');
22
+ * $loader->add('Symfony', __DIR__.'/framework');
23
+ *
24
+ * // activate the autoloader
25
+ * $loader->register();
26
+ *
27
+ * // to enable searching the include path (eg. for PEAR packages)
28
+ * $loader->setUseIncludePath(true);
29
+ *
30
+ * In this example, if you try to use a class in the Symfony\Component
31
+ * namespace or one of its children (Symfony\Component\Console for instance),
32
+ * the autoloader will first look for the class under the component/
33
+ * directory, and it will then fallback to the framework/ directory if not
34
+ * found before giving up.
35
+ *
36
+ * This class is loosely based on the Symfony UniversalClassLoader.
37
+ *
38
+ * @author Fabien Potencier <fabien@symfony.com>
39
+ * @author Jordi Boggiano <j.boggiano@seld.be>
40
+ * @see https://www.php-fig.org/psr/psr-0/
41
+ * @see https://www.php-fig.org/psr/psr-4/
42
+ */
43
+ class ClassLoader
44
+ {
45
+ // PSR-4
46
+ private $prefixLengthsPsr4 = array();
47
+ private $prefixDirsPsr4 = array();
48
+ private $fallbackDirsPsr4 = array();
49
+
50
+ // PSR-0
51
+ private $prefixesPsr0 = array();
52
+ private $fallbackDirsPsr0 = array();
53
+
54
+ private $useIncludePath = false;
55
+ private $classMap = array();
56
+ private $classMapAuthoritative = false;
57
+ private $missingClasses = array();
58
+ private $apcuPrefix;
59
+
60
+ public function getPrefixes()
61
+ {
62
+ if (!empty($this->prefixesPsr0)) {
63
+ return call_user_func_array('array_merge', array_values($this->prefixesPsr0));
64
+ }
65
+
66
+ return array();
67
+ }
68
+
69
+ public function getPrefixesPsr4()
70
+ {
71
+ return $this->prefixDirsPsr4;
72
+ }
73
+
74
+ public function getFallbackDirs()
75
+ {
76
+ return $this->fallbackDirsPsr0;
77
+ }
78
+
79
+ public function getFallbackDirsPsr4()
80
+ {
81
+ return $this->fallbackDirsPsr4;
82
+ }
83
+
84
+ public function getClassMap()
85
+ {
86
+ return $this->classMap;
87
+ }
88
+
89
+ /**
90
+ * @param array $classMap Class to filename map
91
+ */
92
+ public function addClassMap(array $classMap)
93
+ {
94
+ if ($this->classMap) {
95
+ $this->classMap = array_merge($this->classMap, $classMap);
96
+ } else {
97
+ $this->classMap = $classMap;
98
+ }
99
+ }
100
+
101
+ /**
102
+ * Registers a set of PSR-0 directories for a given prefix, either
103
+ * appending or prepending to the ones previously set for this prefix.
104
+ *
105
+ * @param string $prefix The prefix
106
+ * @param array|string $paths The PSR-0 root directories
107
+ * @param bool $prepend Whether to prepend the directories
108
+ */
109
+ public function add($prefix, $paths, $prepend = false)
110
+ {
111
+ if (!$prefix) {
112
+ if ($prepend) {
113
+ $this->fallbackDirsPsr0 = array_merge(
114
+ (array) $paths,
115
+ $this->fallbackDirsPsr0
116
+ );
117
+ } else {
118
+ $this->fallbackDirsPsr0 = array_merge(
119
+ $this->fallbackDirsPsr0,
120
+ (array) $paths
121
+ );
122
+ }
123
+
124
+ return;
125
+ }
126
+
127
+ $first = $prefix[0];
128
+ if (!isset($this->prefixesPsr0[$first][$prefix])) {
129
+ $this->prefixesPsr0[$first][$prefix] = (array) $paths;
130
+
131
+ return;
132
+ }
133
+ if ($prepend) {
134
+ $this->prefixesPsr0[$first][$prefix] = array_merge(
135
+ (array) $paths,
136
+ $this->prefixesPsr0[$first][$prefix]
137
+ );
138
+ } else {
139
+ $this->prefixesPsr0[$first][$prefix] = array_merge(
140
+ $this->prefixesPsr0[$first][$prefix],
141
+ (array) $paths
142
+ );
143
+ }
144
+ }
145
+
146
+ /**
147
+ * Registers a set of PSR-4 directories for a given namespace, either
148
+ * appending or prepending to the ones previously set for this namespace.
149
+ *
150
+ * @param string $prefix The prefix/namespace, with trailing '\\'
151
+ * @param array|string $paths The PSR-4 base directories
152
+ * @param bool $prepend Whether to prepend the directories
153
+ *
154
+ * @throws \InvalidArgumentException
155
+ */
156
+ public function addPsr4($prefix, $paths, $prepend = false)
157
+ {
158
+ if (!$prefix) {
159
+ // Register directories for the root namespace.
160
+ if ($prepend) {
161
+ $this->fallbackDirsPsr4 = array_merge(
162
+ (array) $paths,
163
+ $this->fallbackDirsPsr4
164
+ );
165
+ } else {
166
+ $this->fallbackDirsPsr4 = array_merge(
167
+ $this->fallbackDirsPsr4,
168
+ (array) $paths
169
+ );
170
+ }
171
+ } elseif (!isset($this->prefixDirsPsr4[$prefix])) {
172
+ // Register directories for a new namespace.
173
+ $length = strlen($prefix);
174
+ if ('\\' !== $prefix[$length - 1]) {
175
+ throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
176
+ }
177
+ $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
178
+ $this->prefixDirsPsr4[$prefix] = (array) $paths;
179
+ } elseif ($prepend) {
180
+ // Prepend directories for an already registered namespace.
181
+ $this->prefixDirsPsr4[$prefix] = array_merge(
182
+ (array) $paths,
183
+ $this->prefixDirsPsr4[$prefix]
184
+ );
185
+ } else {
186
+ // Append directories for an already registered namespace.
187
+ $this->prefixDirsPsr4[$prefix] = array_merge(
188
+ $this->prefixDirsPsr4[$prefix],
189
+ (array) $paths
190
+ );
191
+ }
192
+ }
193
+
194
+ /**
195
+ * Registers a set of PSR-0 directories for a given prefix,
196
+ * replacing any others previously set for this prefix.
197
+ *
198
+ * @param string $prefix The prefix
199
+ * @param array|string $paths The PSR-0 base directories
200
+ */
201
+ public function set($prefix, $paths)
202
+ {
203
+ if (!$prefix) {
204
+ $this->fallbackDirsPsr0 = (array) $paths;
205
+ } else {
206
+ $this->prefixesPsr0[$prefix[0]][$prefix] = (array) $paths;
207
+ }
208
+ }
209
+
210
+ /**
211
+ * Registers a set of PSR-4 directories for a given namespace,
212
+ * replacing any others previously set for this namespace.
213
+ *
214
+ * @param string $prefix The prefix/namespace, with trailing '\\'
215
+ * @param array|string $paths The PSR-4 base directories
216
+ *
217
+ * @throws \InvalidArgumentException
218
+ */
219
+ public function setPsr4($prefix, $paths)
220
+ {
221
+ if (!$prefix) {
222
+ $this->fallbackDirsPsr4 = (array) $paths;
223
+ } else {
224
+ $length = strlen($prefix);
225
+ if ('\\' !== $prefix[$length - 1]) {
226
+ throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
227
+ }
228
+ $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
229
+ $this->prefixDirsPsr4[$prefix] = (array) $paths;
230
+ }
231
+ }
232
+
233
+ /**
234
+ * Turns on searching the include path for class files.
235
+ *
236
+ * @param bool $useIncludePath
237
+ */
238
+ public function setUseIncludePath($useIncludePath)
239
+ {
240
+ $this->useIncludePath = $useIncludePath;
241
+ }
242
+
243
+ /**
244
+ * Can be used to check if the autoloader uses the include path to check
245
+ * for classes.
246
+ *
247
+ * @return bool
248
+ */
249
+ public function getUseIncludePath()
250
+ {
251
+ return $this->useIncludePath;
252
+ }
253
+
254
+ /**
255
+ * Turns off searching the prefix and fallback directories for classes
256
+ * that have not been registered with the class map.
257
+ *
258
+ * @param bool $classMapAuthoritative
259
+ */
260
+ public function setClassMapAuthoritative($classMapAuthoritative)
261
+ {
262
+ $this->classMapAuthoritative = $classMapAuthoritative;
263
+ }
264
+
265
+ /**
266
+ * Should class lookup fail if not found in the current class map?
267
+ *
268
+ * @return bool
269
+ */
270
+ public function isClassMapAuthoritative()
271
+ {
272
+ return $this->classMapAuthoritative;
273
+ }
274
+
275
+ /**
276
+ * APCu prefix to use to cache found/not-found classes, if the extension is enabled.
277
+ *
278
+ * @param string|null $apcuPrefix
279
+ */
280
+ public function setApcuPrefix($apcuPrefix)
281
+ {
282
+ $this->apcuPrefix = function_exists('apcu_fetch') && filter_var(ini_get('apc.enabled'), FILTER_VALIDATE_BOOLEAN) ? $apcuPrefix : null;
283
+ }
284
+
285
+ /**
286
+ * The APCu prefix in use, or null if APCu caching is not enabled.
287
+ *
288
+ * @return string|null
289
+ */
290
+ public function getApcuPrefix()
291
+ {
292
+ return $this->apcuPrefix;
293
+ }
294
+
295
+ /**
296
+ * Registers this instance as an autoloader.
297
+ *
298
+ * @param bool $prepend Whether to prepend the autoloader or not
299
+ */
300
+ public function register($prepend = false)
301
+ {
302
+ spl_autoload_register(array($this, 'loadClass'), true, $prepend);
303
+ }
304
+
305
+ /**
306
+ * Unregisters this instance as an autoloader.
307
+ */
308
+ public function unregister()
309
+ {
310
+ spl_autoload_unregister(array($this, 'loadClass'));
311
+ }
312
+
313
+ /**
314
+ * Loads the given class or interface.
315
+ *
316
+ * @param string $class The name of the class
317
+ * @return bool|null True if loaded, null otherwise
318
+ */
319
+ public function loadClass($class)
320
+ {
321
+ if ($file = $this->findFile($class)) {
322
+ includeFile($file);
323
+
324
+ return true;
325
+ }
326
+ }
327
+
328
+ /**
329
+ * Finds the path to the file where the class is defined.
330
+ *
331
+ * @param string $class The name of the class
332
+ *
333
+ * @return string|false The path if found, false otherwise
334
+ */
335
+ public function findFile($class)
336
+ {
337
+ // class map lookup
338
+ if (isset($this->classMap[$class])) {
339
+ return $this->classMap[$class];
340
+ }
341
+ if ($this->classMapAuthoritative || isset($this->missingClasses[$class])) {
342
+ return false;
343
+ }
344
+ if (null !== $this->apcuPrefix) {
345
+ $file = apcu_fetch($this->apcuPrefix.$class, $hit);
346
+ if ($hit) {
347
+ return $file;
348
+ }
349
+ }
350
+
351
+ $file = $this->findFileWithExtension($class, '.php');
352
+
353
+ // Search for Hack files if we are running on HHVM
354
+ if (false === $file && defined('HHVM_VERSION')) {
355
+ $file = $this->findFileWithExtension($class, '.hh');
356
+ }
357
+
358
+ if (null !== $this->apcuPrefix) {
359
+ apcu_add($this->apcuPrefix.$class, $file);
360
+ }
361
+
362
+ if (false === $file) {
363
+ // Remember that this class does not exist.
364
+ $this->missingClasses[$class] = true;
365
+ }
366
+
367
+ return $file;
368
+ }
369
+
370
+ private function findFileWithExtension($class, $ext)
371
+ {
372
+ // PSR-4 lookup
373
+ $logicalPathPsr4 = strtr($class, '\\', DIRECTORY_SEPARATOR) . $ext;
374
+
375
+ $first = $class[0];
376
+ if (isset($this->prefixLengthsPsr4[$first])) {
377
+ $subPath = $class;
378
+ while (false !== $lastPos = strrpos($subPath, '\\')) {
379
+ $subPath = substr($subPath, 0, $lastPos);
380
+ $search = $subPath . '\\';
381
+ if (isset($this->prefixDirsPsr4[$search])) {
382
+ $pathEnd = DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $lastPos + 1);
383
+ foreach ($this->prefixDirsPsr4[$search] as $dir) {
384
+ if (file_exists($file = $dir . $pathEnd)) {
385
+ return $file;
386
+ }
387
+ }
388
+ }
389
+ }
390
+ }
391
+
392
+ // PSR-4 fallback dirs
393
+ foreach ($this->fallbackDirsPsr4 as $dir) {
394
+ if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr4)) {
395
+ return $file;
396
+ }
397
+ }
398
+
399
+ // PSR-0 lookup
400
+ if (false !== $pos = strrpos($class, '\\')) {
401
+ // namespaced class name
402
+ $logicalPathPsr0 = substr($logicalPathPsr4, 0, $pos + 1)
403
+ . strtr(substr($logicalPathPsr4, $pos + 1), '_', DIRECTORY_SEPARATOR);
404
+ } else {
405
+ // PEAR-like class name
406
+ $logicalPathPsr0 = strtr($class, '_', DIRECTORY_SEPARATOR) . $ext;
407
+ }
408
+
409
+ if (isset($this->prefixesPsr0[$first])) {
410
+ foreach ($this->prefixesPsr0[$first] as $prefix => $dirs) {
411
+ if (0 === strpos($class, $prefix)) {
412
+ foreach ($dirs as $dir) {
413
+ if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
414
+ return $file;
415
+ }
416
+ }
417
+ }
418
+ }
419
+ }
420
+
421
+ // PSR-0 fallback dirs
422
+ foreach ($this->fallbackDirsPsr0 as $dir) {
423
+ if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
424
+ return $file;
425
+ }
426
+ }
427
+
428
+ // PSR-0 include paths.
429
+ if ($this->useIncludePath && $file = stream_resolve_include_path($logicalPathPsr0)) {
430
+ return $file;
431
+ }
432
+
433
+ return false;
434
+ }
435
+ }
436
+
437
+ /**
438
+ * Scope isolated include.
439
+ *
440
+ * Prevents access to $this/self from included files.
441
+ */
442
+ function includeFile($file)
443
+ {
444
+ include $file;
445
+ }
vendor/composer/InstalledVersions.php ADDED
@@ -0,0 +1,219 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+
4
+
5
+
6
+
7
+
8
+
9
+
10
+
11
+
12
+
13
+ namespace Composer;
14
+
15
+ use Composer\Semver\VersionParser;
16
+
17
+
18
+
19
+
20
+
21
+
22
+ class InstalledVersions
23
+ {
24
+ private static $installed = array (
25
+ 'root' =>
26
+ array (
27
+ 'pretty_version' => 'dev-main',
28
+ 'version' => 'dev-main',
29
+ 'aliases' =>
30
+ array (
31
+ ),
32
+ 'reference' => 'a03b725c71daf735915144ede3563c2449c7b921',
33
+ 'name' => 'publishpress/post-expirator',
34
+ ),
35
+ 'versions' =>
36
+ array (
37
+ 'publishpress/post-expirator' =>
38
+ array (
39
+ 'pretty_version' => 'dev-main',
40
+ 'version' => 'dev-main',
41
+ 'aliases' =>
42
+ array (
43
+ ),
44
+ 'reference' => 'a03b725c71daf735915144ede3563c2449c7b921',
45
+ ),
46
+ ),
47
+ );
48
+
49
+
50
+
51
+
52
+
53
+
54
+
55
+ public static function getInstalledPackages()
56
+ {
57
+ return array_keys(self::$installed['versions']);
58
+ }
59
+
60
+
61
+
62
+
63
+
64
+
65
+
66
+
67
+
68
+ public static function isInstalled($packageName)
69
+ {
70
+ return isset(self::$installed['versions'][$packageName]);
71
+ }
72
+
73
+
74
+
75
+
76
+
77
+
78
+
79
+
80
+
81
+
82
+
83
+
84
+
85
+
86
+ public static function satisfies(VersionParser $parser, $packageName, $constraint)
87
+ {
88
+ $constraint = $parser->parseConstraints($constraint);
89
+ $provided = $parser->parseConstraints(self::getVersionRanges($packageName));
90
+
91
+ return $provided->matches($constraint);
92
+ }
93
+
94
+
95
+
96
+
97
+
98
+
99
+
100
+
101
+
102
+
103
+ public static function getVersionRanges($packageName)
104
+ {
105
+ if (!isset(self::$installed['versions'][$packageName])) {
106
+ throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
107
+ }
108
+
109
+ $ranges = array();
110
+ if (isset(self::$installed['versions'][$packageName]['pretty_version'])) {
111
+ $ranges[] = self::$installed['versions'][$packageName]['pretty_version'];
112
+ }
113
+ if (array_key_exists('aliases', self::$installed['versions'][$packageName])) {
114
+ $ranges = array_merge($ranges, self::$installed['versions'][$packageName]['aliases']);
115
+ }
116
+ if (array_key_exists('replaced', self::$installed['versions'][$packageName])) {
117
+ $ranges = array_merge($ranges, self::$installed['versions'][$packageName]['replaced']);
118
+ }
119
+ if (array_key_exists('provided', self::$installed['versions'][$packageName])) {
120
+ $ranges = array_merge($ranges, self::$installed['versions'][$packageName]['provided']);
121
+ }
122
+
123
+ return implode(' || ', $ranges);
124
+ }
125
+
126
+
127
+
128
+
129
+
130
+ public static function getVersion($packageName)
131
+ {
132
+ if (!isset(self::$installed['versions'][$packageName])) {
133
+ throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
134
+ }
135
+
136
+ if (!isset(self::$installed['versions'][$packageName]['version'])) {
137
+ return null;
138
+ }
139
+
140
+ return self::$installed['versions'][$packageName]['version'];
141
+ }
142
+
143
+
144
+
145
+
146
+
147
+ public static function getPrettyVersion($packageName)
148
+ {
149
+ if (!isset(self::$installed['versions'][$packageName])) {
150
+ throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
151
+ }
152
+
153
+ if (!isset(self::$installed['versions'][$packageName]['pretty_version'])) {
154
+ return null;
155
+ }
156
+
157
+ return self::$installed['versions'][$packageName]['pretty_version'];
158
+ }
159
+
160
+
161
+
162
+
163
+
164
+ public static function getReference($packageName)
165
+ {
166
+ if (!isset(self::$installed['versions'][$packageName])) {
167
+ throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
168
+ }
169
+
170
+ if (!isset(self::$installed['versions'][$packageName]['reference'])) {
171
+ return null;
172
+ }
173
+
174
+ return self::$installed['versions'][$packageName]['reference'];
175
+ }
176
+
177
+
178
+
179
+
180
+
181
+ public static function getRootPackage()
182
+ {
183
+ return self::$installed['root'];
184
+ }
185
+
186
+
187
+
188
+
189
+
190
+
191
+
192
+ public static function getRawData()
193
+ {
194
+ return self::$installed;
195
+ }
196
+
197
+
198
+
199
+
200
+
201
+
202
+
203
+
204
+
205
+
206
+
207
+
208
+
209
+
210
+
211
+
212
+
213
+
214
+
215
+ public static function reload($data)
216
+ {
217
+ self::$installed = $data;
218
+ }
219
+ }
vendor/composer/LICENSE ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ Copyright (c) Nils Adermann, Jordi Boggiano
3
+
4
+ Permission is hereby granted, free of charge, to any person obtaining a copy
5
+ of this software and associated documentation files (the "Software"), to deal
6
+ in the Software without restriction, including without limitation the rights
7
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8
+ copies of the Software, and to permit persons to whom the Software is furnished
9
+ to do so, subject to the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be included in all
12
+ copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20
+ THE SOFTWARE.
21
+
vendor/composer/autoload_classmap.php ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ // autoload_classmap.php @generated by Composer
4
+
5
+ $vendorDir = dirname(dirname(__FILE__));
6
+ $baseDir = dirname($vendorDir);
7
+
8
+ return array(
9
+ 'Composer\\InstalledVersions' => $vendorDir . '/composer/InstalledVersions.php',
10
+ );
vendor/composer/autoload_namespaces.php ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ // autoload_namespaces.php @generated by Composer
4
+
5
+ $vendorDir = dirname(dirname(__FILE__));
6
+ $baseDir = dirname($vendorDir);
7
+
8
+ return array(
9
+ );
vendor/composer/autoload_psr4.php ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ // autoload_psr4.php @generated by Composer
4
+
5
+ $vendorDir = dirname(dirname(__FILE__));
6
+ $baseDir = dirname($vendorDir);
7
+
8
+ return array(
9
+ );
vendor/composer/autoload_real.php ADDED
@@ -0,0 +1,55 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ // autoload_real.php @generated by Composer
4
+
5
+ class ComposerAutoloaderInit252d08f02d77dcc4a9b095ab08120c6d
6
+ {
7
+ private static $loader;
8
+
9
+ public static function loadClassLoader($class)
10
+ {
11
+ if ('Composer\Autoload\ClassLoader' === $class) {
12
+ require __DIR__ . '/ClassLoader.php';
13
+ }
14
+ }
15
+
16
+ /**
17
+ * @return \Composer\Autoload\ClassLoader
18
+ */
19
+ public static function getLoader()
20
+ {
21
+ if (null !== self::$loader) {
22
+ return self::$loader;
23
+ }
24
+
25
+ spl_autoload_register(array('ComposerAutoloaderInit252d08f02d77dcc4a9b095ab08120c6d', 'loadClassLoader'), true, true);
26
+ self::$loader = $loader = new \Composer\Autoload\ClassLoader();
27
+ spl_autoload_unregister(array('ComposerAutoloaderInit252d08f02d77dcc4a9b095ab08120c6d', 'loadClassLoader'));
28
+
29
+ $useStaticLoader = PHP_VERSION_ID >= 50600 && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded());
30
+ if ($useStaticLoader) {
31
+ require __DIR__ . '/autoload_static.php';
32
+
33
+ call_user_func(\Composer\Autoload\ComposerStaticInit252d08f02d77dcc4a9b095ab08120c6d::getInitializer($loader));
34
+ } else {
35
+ $map = require __DIR__ . '/autoload_namespaces.php';
36
+ foreach ($map as $namespace => $path) {
37
+ $loader->set($namespace, $path);
38
+ }
39
+
40
+ $map = require __DIR__ . '/autoload_psr4.php';
41
+ foreach ($map as $namespace => $path) {
42
+ $loader->setPsr4($namespace, $path);
43
+ }
44
+
45
+ $classMap = require __DIR__ . '/autoload_classmap.php';
46
+ if ($classMap) {
47
+ $loader->addClassMap($classMap);
48
+ }
49
+ }
50
+
51
+ $loader->register(true);
52
+
53
+ return $loader;
54
+ }
55
+ }
vendor/composer/autoload_static.php ADDED
@@ -0,0 +1,20 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ // autoload_static.php @generated by Composer
4
+
5
+ namespace Composer\Autoload;
6
+
7
+ class ComposerStaticInit252d08f02d77dcc4a9b095ab08120c6d
8
+ {
9
+ public static $classMap = array (
10
+ 'Composer\\InstalledVersions' => __DIR__ . '/..' . '/composer/InstalledVersions.php',
11
+ );
12
+
13
+ public static function getInitializer(ClassLoader $loader)
14
+ {
15
+ return \Closure::bind(function () use ($loader) {
16
+ $loader->classMap = ComposerStaticInit252d08f02d77dcc4a9b095ab08120c6d::$classMap;
17
+
18
+ }, null, ClassLoader::class);
19
+ }
20
+ }
vendor/composer/installed.json ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
1
+ {
2
+ "packages": [],
3
+ "dev": false,
4
+ "dev-package-names": []
5
+ }
vendor/composer/installed.php ADDED
@@ -0,0 +1,24 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php return array (
2
+ 'root' =>
3
+ array (
4
+ 'pretty_version' => 'dev-main',
5
+ 'version' => 'dev-main',
6
+ 'aliases' =>
7
+ array (
8
+ ),
9
+ 'reference' => 'a03b725c71daf735915144ede3563c2449c7b921',
10
+ 'name' => 'publishpress/post-expirator',
11
+ ),
12
+ 'versions' =>
13
+ array (
14
+ 'publishpress/post-expirator' =>
15
+ array (
16
+ 'pretty_version' => 'dev-main',
17
+ 'version' => 'dev-main',
18
+ 'aliases' =>
19
+ array (
20
+ ),
21
+ 'reference' => 'a03b725c71daf735915144ede3563c2449c7b921',
22
+ ),
23
+ ),
24
+ );
views/bulk-edit.php ADDED
@@ -0,0 +1,96 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ $defaults = PostExpirator_Facade::get_default_expiry( $post_type );
3
+
4
+ $year = $defaults['year'];
5
+ $month = $defaults['month'];
6
+ $day = $defaults['day'];
7
+ $hour = $defaults['hour'];
8
+ $minute = $defaults['minute'];
9
+ ?>
10
+ <div style="clear:both"></div>
11
+ <div class="inline-edit-col post-expirator-quickedit">
12
+ <div class="inline-edit-col">
13
+ <div class="inline-edit-group">
14
+ <legend class="inline-edit-legend"><?php _e( 'Post Expirator', 'post-expirator' ); ?></legend>
15
+ <fieldset class="inline-edit-date">
16
+ <div class="pe-qe-fields">
17
+ <div>
18
+ <legend><span class="title"><?php _e( 'Date', 'post-expirator' ); ?></span></legend>
19
+ <label>
20
+ <span class="screen-reader-text"><?php _e( 'Enable Post Expiration', 'post-expirator' ); ?></span>
21
+ <select name="expirationdate_status">
22
+ <option value="no-change" data-show-fields="false" selected>--<?php _e( 'No Change', 'post-expirator' ); ?>--</option>
23
+ <option value="change-only" data-show-fields="true" title="<?php _e( 'Change expiry date if enabled on posts', 'post-expirator' ); ?>"><?php _e( 'Change on posts', 'post-expirator' ); ?></option>
24
+ <option value="add-only" data-show-fields="true" title="<?php _e( 'Add expiry date if not enabled on posts', 'post-expirator' ); ?>"><?php _e( 'Add to posts', 'post-expirator' ); ?></option>
25
+ <option value="change-add" data-show-fields="true"><?php _e( 'Change & Add', 'post-expirator' ); ?></option>
26
+ <option value="remove-only" data-show-fields="false"><?php _e( 'Remove from posts', 'post-expirator' ); ?></option>
27
+ </select>
28
+ </label>
29
+ <span class="post-expirator-date-fields">
30
+ <label>
31
+ <span class="screen-reader-text"><?php _e( 'Month', 'post-expirator' ); ?></span>
32
+ <select name="expirationdate_month">
33
+ <?php
34
+ for ( $x = 1; $x <= 12; $x++ ) {
35
+ $now = mktime( 0, 0, 0, $x, 1, date_i18n( 'Y' ) );
36
+ $monthNumeric = date_i18n( 'm', $now );
37
+ $monthStr = date_i18n( 'M', $now );
38
+ // phpcs:ignore WordPress.PHP.StrictComparisons.LooseComparison
39
+ $selected = $monthNumeric == $defaults['month'] ? 'selected' : '';
40
+ ?>
41
+ <option value="<?php echo $monthNumeric; ?>" data-text="<?php echo $monthStr; ?>" <?php echo $selected; ?>><?php echo $monthNumeric; ?>-<?php echo $monthStr; ?></option>
42
+ <?php } ?>
43
+
44
+ </select>
45
+ </label>
46
+ <label>
47
+ <span class="screen-reader-text"><?php _e( 'Day', 'post-expirator' ); ?></span>
48
+ <input name="expirationdate_day" placeholder="<?php echo $day; ?>" value="" size="2" maxlength="2" autocomplete="off" type="text">
49
+ </label>,
50
+ <label>
51
+ <span class="screen-reader-text"><?php _e( 'Year', 'post-expirator' ); ?></span>
52
+ <input name="expirationdate_year" placeholder="<?php echo $year; ?>" value="" size="4" maxlength="4" autocomplete="off" type="text">
53
+ </label> @
54
+ <label>
55
+ <span class="screen-reader-text"><?php _e( 'Hour', 'post-expirator' ); ?></span>
56
+ <input name="expirationdate_hour" placeholder="<?php echo $hour; ?>" value="" size="2" maxlength="2" autocomplete="off" type="text">
57
+ </label> :
58
+ <label>
59
+ <span class="screen-reader-text"><?php _e( 'Minute', 'post-expirator' ); ?></span>
60
+ <input name="expirationdate_minute" placeholder="<?php echo $minute; ?>" value="" size="2" maxlength="2" autocomplete="off" type="text">
61
+ </label>
62
+ </span>
63
+ </div>
64
+ <div class="post-expirator-date-fields">
65
+ <legend>
66
+ <span class="title"><?php _e( 'Type', 'post-expirator' ); ?></span>
67
+ <span class="screen-reader-text"><?php _e( 'How to expire', 'post-expirator' ); ?></span>
68
+ </legend>
69
+ <label>
70
+ <?php
71
+ $defaults = get_option( 'expirationdateDefaults' . ucfirst( $post_type ) );
72
+ _postexpirator_expire_type( array('name' => 'expirationdate_expiretype', 'selected' => $defaults['expireType'], 'post_type' => $post_type ) );
73
+ ?>
74
+ </label>
75
+ </div>
76
+ <div class="pe-category-list">
77
+ <legend>
78
+ <span class="title"><?php echo $tax_label; ?></span>
79
+ <span class="screen-reader-text"><?php _e( 'Expiration Categories', 'post-expirator' ); ?></span>
80
+ </legend>
81
+ <ul id="categorychecklist" class="list:category categorychecklist cat-checklist category-checklist">
82
+ <?php
83
+ if ( ! empty( $taxonomy ) ) {
84
+ $walker = new Walker_PostExpirator_Category_Checklist();
85
+ wp_terms_checklist( 0, array( 'taxonomy' => $taxonomy, 'walker' => $walker, 'checked_ontop' => false ) );
86
+ }
87
+ ?>
88
+ </ul>
89
+ </div>
90
+ </span>
91
+ </div>
92
+ <input name="expirationdate_quickedit" value="true" type="hidden"/>
93
+ </fieldset>
94
+ </div>
95
+ </div>
96
+ </div>
views/expire-column.php ADDED
@@ -0,0 +1,55 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <div class="post-expire-col" data-id="<?php echo esc_attr( $id ); ?>" data-expire-attributes="<?php echo esc_attr( json_encode( $attributes ) ); ?>">
2
+ <?php
3
+ $display = __( 'Never', 'post-expirator' );
4
+ $ed = get_post_meta( $id, '_expiration-date', true );
5
+ if ( $ed ) {
6
+ $display = date_i18n( get_option( 'date_format' ) . ' ' . get_option( 'time_format' ), $ed + ( get_option( 'gmt_offset' ) * HOUR_IN_SECONDS ) );
7
+ }
8
+
9
+ $defaults = get_option( 'expirationdateDefaults' . ucfirst( $post_type ) );
10
+ $expireType = 'draft';
11
+ if ( isset( $defaults['expireType'] ) ) {
12
+ $expireType = $defaults['expireType'];
13
+ }
14
+
15
+ // these defaults will be used by quick edit
16
+ $defaults = PostExpirator_Facade::get_default_expiry( $post_type );
17
+
18
+ $year = $defaults['year'];
19
+ $month = $defaults['month'];
20
+ $day = $defaults['day'];
21
+ $hour = $defaults['hour'];
22
+ $minute = $defaults['minute'];
23
+ $enabled = 'false';
24
+ $categories = '';
25
+
26
+ // Values for Quick Edit
27
+ if ( $ed ) {
28
+ $enabled = 'true';
29
+ $date = gmdate( 'Y-m-d H:i:s', $ed );
30
+ $year = get_date_from_gmt( $date, 'Y' );
31
+ $month = get_date_from_gmt( $date, 'm' );
32
+ $day = get_date_from_gmt( $date, 'd' );
33
+ $hour = get_date_from_gmt( $date, 'H' );
34
+ $minute = get_date_from_gmt( $date, 'i' );
35
+ if ( isset( $attributes['expireType'] ) ) {
36
+ $expireType = $attributes['expireType'];
37
+ }
38
+ if ( isset( $attributes['category'] ) && ! empty( $attributes['category'] ) && in_array( $expireType, array( 'category', 'category-add', 'category-remove' ), true ) ) {
39
+ $categories = implode( ',', $attributes['category'] );
40
+ }
41
+ }
42
+
43
+ // the hidden fields will be used by quick edit
44
+
45
+ ?>
46
+ <?php echo esc_html( $display ); ?>
47
+ <span id="expirationdate_year-<?php echo $id; ?>" style="display: none;"><?php echo $year; ?></span>
48
+ <span id="expirationdate_month-<?php echo $id; ?>" style="display: none;"><?php echo $month; ?></span>
49
+ <span id="expirationdate_day-<?php echo $id; ?>" style="display: none;"><?php echo $day; ?></span>
50
+ <span id="expirationdate_hour-<?php echo $id; ?>" style="display: none;"><?php echo $hour; ?></span>
51
+ <span id="expirationdate_minute-<?php echo $id; ?>" style="display: none;"><?php echo $minute; ?></span>
52
+ <span id="expirationdate_enabled-<?php echo $id; ?>" style="display: none;"><?php echo $enabled; ?></span>
53
+ <span id="expirationdate_expireType-<?php echo $id; ?>" style="display: none;"><?php echo $expireType; ?></span>
54
+ <span id="expirationdate_categories-<?php echo $id; ?>" style="display: none;"><?php echo $categories; ?></span>
55
+ </div>
views/how-to-expire.php ADDED
@@ -0,0 +1,42 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ // @TODO remove extract
3
+ // phpcs:ignore WordPress.PHP.DontExtract.extract_extract
4
+ extract( $opts );
5
+
6
+ if ( ! isset( $name ) ) {
7
+ return false;
8
+ }
9
+ if ( ! isset( $id ) ) {
10
+ $id = $name;
11
+ }
12
+ if ( ! isset( $disabled ) ) {
13
+ $disabled = false;
14
+ }
15
+ if ( ! isset( $onchange ) ) {
16
+ $onchange = '';
17
+ }
18
+ if ( ! isset( $type ) ) {
19
+ $type = '';
20
+ }
21
+
22
+ // maybe settings have not been configured
23
+ if ( empty( $type ) && isset( $opts['post_type'] ) ) {
24
+ $type = $opts['post_type'];
25
+ }
26
+
27
+ $rv = array();
28
+ // phpcs:ignore WordPress.PHP.StrictComparisons.LooseComparison
29
+ $rv[] = '<select name="' . $name . '" id="' . $id . '"' . ( $disabled == true ? ' disabled="disabled"' : '' ) . ' onchange="' . $onchange . '">';
30
+ $rv[] = '<option value="draft" ' . ( $selected === 'draft' ? 'selected="selected"' : '' ) . '>' . __( 'Draft', 'post-expirator' ) . '</option>';
31
+ $rv[] = '<option value="delete" ' . ( $selected === 'delete' ? 'selected="selected"' : '' ) . '>' . __( 'Delete', 'post-expirator' ) . '</option>';
32
+ $rv[] = '<option value="trash" ' . ( $selected === 'trash' ? 'selected="selected"' : '' ) . '>' . __( 'Trash', 'post-expirator' ) . '</option>';
33
+ $rv[] = '<option value="private" ' . ( $selected === 'private' ? 'selected="selected"' : '' ) . '>' . __( 'Private', 'post-expirator' ) . '</option>';
34
+ $rv[] = '<option value="stick" ' . ( $selected === 'stick' ? 'selected="selected"' : '' ) . '>' . __( 'Stick', 'post-expirator' ) . '</option>';
35
+ $rv[] = '<option value="unstick" ' . ( $selected === 'unstick' ? 'selected="selected"' : '' ) . '>' . __( 'Unstick', 'post-expirator' ) . '</option>';
36
+ if ( $type !== 'page' ) {
37
+ $rv[] = '<option value="category" ' . ( $selected === 'category' ? 'selected="selected"' : '' ) . '>' . __( 'Category: Replace', 'post-expirator' ) . '</option>';
38
+ $rv[] = '<option value="category-add" ' . ( $selected === 'category-add' ? 'selected="selected"' : '' ) . '>' . __( 'Category: Add', 'post-expirator' ) . '</option>';
39
+ $rv[] = '<option value="category-remove" ' . ( $selected === 'category-remove' ? 'selected="selected"' : '' ) . '>' . __( 'Category: Remove', 'post-expirator' ) . '</option>';
40
+ }
41
+ $rv[] = '</select>';
42
+ echo implode( "<br/>\n", $rv );
views/menu-defaults.php ADDED
@@ -0,0 +1,131 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <form method="post">
2
+ <?php wp_nonce_field( 'postexpirator_menu_defaults', '_postExpiratorMenuDefaults_nonce' ); ?>
3
+ <h3><?php _e( 'Default Expiration Values', 'post-expirator' ); ?></h3>
4
+
5
+ <p><?php _e( 'Use the values below to set the default actions/values to be used for each for the corresponding post types. These values can all be overwritten when creating/editing the post/page.', 'post-expirator' ); ?></p>
6
+
7
+ <?php
8
+ foreach ( $types as $type ) {
9
+ $post_type_object = get_post_type_object( $type );
10
+ echo '<fieldset>';
11
+ echo "<legend>&nbsp;{$post_type_object->labels->singular_name}&nbsp;</legend>";
12
+ $defaults = get_option( 'expirationdateDefaults' . ucfirst( $type ) );
13
+
14
+ // phpcs:ignore WordPress.PHP.StrictComparisons.LooseComparison
15
+ if ( isset( $defaults['autoEnable'] ) && $defaults['autoEnable'] == 1 ) {
16
+ $expiredautoenabled = 'checked = "checked"';
17
+ $expiredautodisabled = '';
18
+ } else {
19
+ $expiredautoenabled = '';
20
+ $expiredautodisabled = 'checked = "checked"';
21
+ }
22
+
23
+ $expiredactivemetaenabled = '';
24
+ $expiredactivemetadisabled = 'checked = "checked"';
25
+
26
+ // if settings are not configured, show the metabox by default only for posts and pages
27
+ if ( ! isset( $defaults['activeMetaBox'] ) && in_array( $type, array( 'post', 'page' ), true ) ) {
28
+ $expiredactivemetaenabled = 'checked = "checked"';
29
+ $expiredactivemetadisabled = '';
30
+ } elseif ( isset( $defaults['activeMetaBox'] ) ) {
31
+ if ( $defaults['activeMetaBox'] === 'inactive' ) {
32
+ $expiredactivemetaenabled = '';
33
+ $expiredactivemetadisabled = 'checked = "checked"';
34
+ } else {
35
+ $expiredactivemetadisabled = '';
36
+ $expiredactivemetaenabled = 'checked = "checked"';
37
+ }
38
+ }
39
+ if ( ! isset( $defaults['taxonomy'] ) ) {
40
+ $defaults['taxonomy'] = false;
41
+ }
42
+ if ( ! isset( $defaults['emailnotification'] ) ) {
43
+ $defaults['emailnotification'] = '';
44
+ }
45
+ if ( ! isset( $defaults['default-expire-type'] ) ) {
46
+ $defaults['default-expire-type'] = '';
47
+ }
48
+ ?>
49
+ <table class="form-table">
50
+ <tr valign="top">
51
+ <th scope="row"><label for="expirationdate_activemeta-<?php echo $type; ?>"><?php _e( 'Active', 'post-expirator' ); ?></label></th>
52
+ <td>
53
+ <input type="radio" name="expirationdate_activemeta-<?php echo $type; ?>" id="expirationdate_activemeta-true-<?php echo $type; ?>" value="active" <?php echo $expiredactivemetaenabled; ?>/> <label for="expirationdate_activemeta-true-<?php echo $type; ?>"><?php _e( 'Active', 'post-expirator' ); ?></label>
54
+ &nbsp;&nbsp;
55
+ <input type="radio" name="expirationdate_activemeta-<?php echo $type; ?>" id="expirationdate_activemeta-false-<?php echo $type; ?>" value="inactive" <?php echo $expiredactivemetadisabled; ?>/> <label for="expirationdate_activemeta-false-<?php echo $type; ?>"><?php _e( 'Inactive', 'post-expirator' ); ?></label>
56
+ <p class="description"><?php _e( 'Select whether the post expirator meta box is active for this post type.', 'post-expirator' ); ?></p>
57
+ </td>
58
+ </tr>
59
+ <tr valign="top">
60
+ <th scope="row"><label for="expirationdate_expiretype-<?php echo $type; ?>"><?php _e( 'How to expire', 'post-expirator' ); ?></label></th>
61
+ <td>
62
+ <?php _postexpirator_expire_type( array('name' => 'expirationdate_expiretype-' . $type, 'selected' => ( isset( $defaults['expireType'] ) ? $defaults['expireType'] : '' ) ) ); ?>
63
+ <p class="description"><?php _e( 'Select the default expire action for the post type.', 'post-expirator' ); ?></p>
64
+ </td>
65
+ </tr>
66
+ <tr valign="top">
67
+ <th scope="row"><label for="expirationdate_autoenable-<?php echo $type; ?>"><?php _e( 'Auto-Enable?', 'post-expirator' ); ?></label></th>
68
+ <td>
69
+ <input type="radio" name="expirationdate_autoenable-<?php echo $type; ?>" id="expirationdate_autoenable-true-<?php echo $type; ?>" value="1" <?php echo $expiredautoenabled; ?>/> <label for="expirationdate_autoenable-true-<?php echo $type; ?>"><?php _e( 'Enabled', 'post-expirator' ); ?></label>
70
+ &nbsp;&nbsp;
71
+ <input type="radio" name="expirationdate_autoenable-<?php echo $type; ?>" id="expirationdate_autoenable-false-<?php echo $type; ?>" value="0" <?php echo $expiredautodisabled; ?>/> <label for="expirationdate_autoenable-false-<?php echo $type; ?>"><?php _e( 'Disabled', 'post-expirator' ); ?></label>
72
+ <p class="description"><?php _e( 'Select whether the post expirator is enabled for all new posts.', 'post-expirator' ); ?></p>
73
+ </td>
74
+ </tr>
75
+ <tr valign="top">
76
+ <th scope="row"><label for="expirationdate_taxonomy-<?php echo $type; ?>"><?php _e( 'Taxonomy (hierarchical)', 'post-expirator' ); ?></label></th>
77
+ <td>
78
+ <?php echo _postexpirator_taxonomy( array('type' => $type, 'name' => 'expirationdate_taxonomy-' . $type, 'selected' => $defaults['taxonomy']) ); ?>
79
+ </td>
80
+ </tr>
81
+ <tr valign="top">
82
+ <th scope="row"><label for="expirationdate_emailnotification-<?php echo $type; ?>"><?php _e( 'Who to notify', 'post-expirator' ); ?></label></th>
83
+ <td>
84
+ <input class="large-text" type="text" name="expirationdate_emailnotification-<?php echo $type; ?>" id="expirationdate_emailnotification-<?php echo $type; ?>" value="<?php echo $defaults['emailnotification']; ?>" />
85
+ <p class="description"><?php _e( 'Enter a comma separate list of emails that you would like to be notified when the post expires.', 'post-expirator' ); ?></p>
86
+ </td>
87
+ </tr>
88
+ <?php
89
+ $values = array(
90
+ '' => __( 'None', 'post-expirator' ),
91
+ 'inherit' => __( 'Inherit from General Settings', 'post-expirator' ),
92
+ 'custom' => __( 'Custom', 'post-expirator' ),
93
+ 'publish' => __( 'Publish Time', 'post-expirator' ),
94
+ );
95
+
96
+ $show = 'none';
97
+ $customDate = '';
98
+ if ( $defaults['default-expire-type'] === 'custom' ) {
99
+ $show = 'block';
100
+ $customDate = $defaults['default-custom-date'];
101
+ }
102
+
103
+ ?>
104
+
105
+ <tr valign="top">
106
+ <th scope="row"><label for="expired-default-date-<?php echo $type; ?>"><?php _e( 'Default Date/Time Duration', 'post-expirator' ); ?></label></th>
107
+ <td>
108
+ <select name="expired-default-date-<?php echo $type; ?>" id="expired-default-date-<?php echo $type; ?>" class="pe-custom-date-toggle">
109
+ <?php foreach ( $values as $value => $label ) { ?>
110
+ <option value="<?php echo $value; ?>" <?php selected( $value, $defaults['default-expire-type'] ); ?>><?php echo $label; ?></option>
111
+ <?php } ?>
112
+ </select>
113
+ <p class="description"><?php _e( 'Set the default expiration date to be used when creating a new post of this type.' ); ?></p>
114
+ <div id="expired-custom-container-<?php echo $type; ?>" class="pe-custom-date-container" style="display: <?php echo $show; ?>;">
115
+ <br/>
116
+ <label for="expired-custom-date-<?php echo $type; ?>"><?php _e( 'Custom', 'post-expirator' ); ?>:</label>
117
+ <input type="text" value="<?php echo $customDate; ?>" name="expired-custom-date-<?php echo $type; ?>" id="expired-custom-date-<?php echo $type; ?>" />
118
+ <p class="description"><?php echo sprintf( __( 'Set the custom value to use for the default expiration date. For information on formatting, see %1$s. For example, you could enter %2$s+1 month%3$s or %4$s+1 week 2 days 4 hours 2 seconds%5$s or %6$snext Thursday%7$s.', 'post-expirator' ), '<a href="http://php.net/manual/en/function.strtotime.php" target="_new">PHP strtotime function</a>', '<code>', '</code>', '<code>', '</code>', '<code>', '</code>' ); ?></p>
119
+ </div>
120
+
121
+ </td>
122
+ </tr>
123
+ </table>
124
+ </fieldset>
125
+ <?php
126
+ }
127
+ ?>
128
+ <p class="submit">
129
+ <input type="submit" name="expirationdateSaveDefaults" class="button-primary" value="<?php _e( 'Save Changes', 'post-expirator' ); ?>" />
130
+ </p>
131
+ </form>
views/menu-diagnostics.php ADDED
@@ -0,0 +1,89 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <form method="post" id="postExpiratorMenuUpgrade">
2
+ <?php wp_nonce_field( 'postexpirator_menu_diagnostics', '_postExpiratorMenuDiagnostics_nonce' ); ?>
3
+ <h3><?php _e( 'Advanced Diagnostics', 'post-expirator' ); ?></h3>
4
+ <table class="form-table">
5
+ <tr valign="top">
6
+ <th scope="row"><label for="postexpirator-log"><?php _e( 'Debug Logging', 'post-expirator' ); ?></label></th>
7
+ <td>
8
+ <?php
9
+ if ( POSTEXPIRATOR_DEBUG ) {
10
+ echo '
11
+ <input type="submit" class="button" name="debugging-disable" id="debugging-disable" value="(' . __( 'Status: Enabled', 'post-expirator' ) . ') ' . __( 'Disable Debugging', 'post-expirator' ) . '" />
12
+ <br/><a href="' . admin_url( 'options-general.php?page=post-expirator.php&tab=viewdebug' ) . '">' . __( 'View Debug Logs', 'post-expirator' ) . '</a>';
13
+ } else {
14
+ echo '<input type="submit" class="button" name="debugging-enable" id="debugging-enable" value="(' . __( 'Status: Disabled', 'post-expirator' ) . ') ' . __( 'Enable Debugging', 'post-expirator' ) . '" />';
15
+ }
16
+ ?>
17
+ </td>
18
+ </tr>
19
+ <tr valign="top">
20
+ <th scope="row"><?php _e( 'Purge Debug Log', 'post-expirator' ); ?></th>
21
+ <td>
22
+ <input type="submit" class="button" name="purge-debug" id="purge-debug" value="<?php _e( 'Purge Debug Log', 'post-expirator' ); ?>" />
23
+ </td>
24
+ </tr/>
25
+ <tr valign="top">
26
+ <th scope="row"><?php _e( 'WP-Cron Status', 'post-expirator' ); ?></th>
27
+ <td>
28
+ <?php
29
+ if ( defined( 'DISABLE_WP_CRON' ) && DISABLE_WP_CRON === true ) {
30
+ _e( 'DISABLED', 'post-expirator' );
31
+ } else {
32
+ _e( 'ENABLED - OK', 'post-expirator' );
33
+ }
34
+ ?>
35
+ </td>
36
+ </tr/>
37
+ <tr valign="top">
38
+ <th scope="row"><label for="cron-schedule"><?php _e( 'Current Cron Schedule', 'post-expirator' ); ?></label></th>
39
+ <td>
40
+ <p><?php _e( 'The below table will show all currently scheduled cron events with the next run time.', 'post-expirator' ); ?></p>
41
+
42
+ <div class="pe-scroll">
43
+ <table cellspacing="0" class="striped">
44
+ <tr>
45
+ <th style="width: 30%"><?php _e( 'Date', 'post-expirator' ); ?></th>
46
+ <th style="width: 30%;"><?php _e( 'Event', 'post-expirator' ); ?></th>
47
+ <th style="width: 30%;"><?php _e( 'Arguments / Schedule', 'post-expirator' ); ?></th>
48
+ </tr>
49
+ <?php
50
+ $cron = _get_cron_array();
51
+ foreach ( $cron as $key => $value ) {
52
+ foreach ( $value as $eventkey => $eventvalue ) {
53
+ $class = $eventkey === 'postExpiratorExpire' ? 'pe-event' : '';
54
+ print '<tr class="' . $class . '">';
55
+ print '<td>' . date_i18n( 'r', $key ) . '</td>';
56
+ print '<td>' . $eventkey . '</td>';
57
+ $arrkey = array_keys( $eventvalue );
58
+ print '<td>';
59
+ foreach ( $arrkey as $eventguid ) {
60
+ print '<table><tr>';
61
+ if ( empty( $eventvalue[ $eventguid ]['args'] ) ) {
62
+ print '<td>' . __( 'No Arguments', 'post-expirator' ) . '</td>';
63
+ } else {
64
+ print '<td>';
65
+ $args = array();
66
+ foreach ( $eventvalue[ $eventguid ]['args'] as $key => $value ) {
67
+ $args[] = "$key => $value";
68
+ }
69
+ print implode( "<br/>\n", $args );
70
+ print '</td>';
71
+ }
72
+ if ( empty( $eventvalue[ $eventguid ]['schedule'] ) ) {
73
+ print '<td>' . __( 'Single Event', 'post-expirator' ) . '</td>';
74
+ } else {
75
+ print '<td>' . $eventvalue[ $eventguid ]['schedule'] . ' (' . $eventvalue[ $eventguid ]['interval'] . ')</td>';
76
+ }
77
+ print '</tr></table>';
78
+ }
79
+ print '</td>';
80
+ print '</tr>';
81
+ }
82
+ }
83
+ ?>
84
+ </table>
85
+ </div>
86
+ </td>
87
+ </tr>
88
+ </table>
89
+ </form>
views/menu-general.php ADDED
@@ -0,0 +1,194 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ // phpcs:disable WordPress.NamingConventions.ValidVariableName.InterpolatedVariableNotSnakeCase
3
+ // phpcs:disable WordPress.PHP.StrictComparisons.LooseComparison
4
+
5
+ // Get Option
6
+ $expirationdateDefaultDateFormat = get_option( 'expirationdateDefaultDateFormat', POSTEXPIRATOR_DATEFORMAT );
7
+ $expirationdateDefaultTimeFormat = get_option( 'expirationdateDefaultTimeFormat', POSTEXPIRATOR_TIMEFORMAT );
8
+ $expireddisplayfooter = get_option( 'expirationdateDisplayFooter', POSTEXPIRATOR_FOOTERDISPLAY );
9
+ $expiredemailnotification = get_option( 'expirationdateEmailNotification', POSTEXPIRATOR_EMAILNOTIFICATION );
10
+ $expiredemailnotificationadmins = get_option( 'expirationdateEmailNotificationAdmins', POSTEXPIRATOR_EMAILNOTIFICATIONADMINS );
11
+ $expiredemailnotificationlist = get_option( 'expirationdateEmailNotificationList', '' );
12
+ $expirationdateFooterContents = get_option( 'expirationdateFooterContents', POSTEXPIRATOR_FOOTERCONTENTS );
13
+ $expirationdateFooterStyle = get_option( 'expirationdateFooterStyle', POSTEXPIRATOR_FOOTERSTYLE );
14
+ $expirationdateDefaultDate = get_option( 'expirationdateDefaultDate', POSTEXPIRATOR_EXPIREDEFAULT );
15
+ $expirationdateDefaultDateCustom = get_option( 'expirationdateDefaultDateCustom' );
16
+
17
+ $categories = get_option( 'expirationdateCategoryDefaults' );
18
+
19
+ $expireddisplayfooterenabled = '';
20
+ $expireddisplayfooterdisabled = '';
21
+ if ( $expireddisplayfooter == 0 ) {
22
+ $expireddisplayfooterdisabled = 'checked="checked"';
23
+ } elseif ( $expireddisplayfooter == 1 ) {
24
+ $expireddisplayfooterenabled = 'checked="checked"';
25
+ }
26
+
27
+ $expiredemailnotificationenabled = '';
28
+ $expiredemailnotificationdisabled = '';
29
+ if ( $expiredemailnotification == 0 ) {
30
+ $expiredemailnotificationdisabled = 'checked="checked"';
31
+ } elseif ( $expiredemailnotification == 1 ) {
32
+ $expiredemailnotificationenabled = 'checked="checked"';
33
+ }
34
+
35
+ $expiredemailnotificationadminsenabled = '';
36
+ $expiredemailnotificationadminsdisabled = '';
37
+ if ( $expiredemailnotificationadmins == 0 ) {
38
+ $expiredemailnotificationadminsdisabled = 'checked="checked"';
39
+ } elseif ( $expiredemailnotificationadmins == 1 ) {
40
+ $expiredemailnotificationadminsenabled = 'checked="checked"';
41
+ }
42
+
43
+ ?>
44
+ <p><?php _e( 'The post expirator plugin sets a custom meta value, and then optionally allows you to select if you want the post changed to a draft status or deleted when it expires.', 'post-expirator' ); ?></p>
45
+
46
+ <h3><?php _e( 'Shortcode', 'post-expirator' ); ?></h3>
47
+ <p><?php echo sprintf( __( 'Valid %s attributes:', 'post-expirator' ), '<code>[postexpirator]</code>' ); ?></p>
48
+ <ul class="pe-list">
49
+ <li><p><?php echo sprintf( __( '%1$s - valid options are %2$sfull%3$s (default), %4$sdate%5$s, %6$stime%7$s', 'post-expirator' ), '<code>type</code>', '<code>', '</code>', '<code>', '</code>', '<code>', '</code>' ); ?></p></li>
50
+ <li><p><?php echo sprintf( __( '%s - format set here will override the value set on the settings page', 'post-expirator' ), '<code>dateformat</code>' ); ?></p></li>
51
+ <li><p><?php echo sprintf( __( '%s - format set here will override the value set on the settings page', 'post-expirator' ), '<code>timeformat</code>' ); ?></p></li>
52
+ </ul>
53
+ <hr/>
54
+
55
+ <form method="post" id="expirationdate_save_options">
56
+ <?php wp_nonce_field( 'postexpirator_menu_general', '_postExpiratorMenuGeneral_nonce' ); ?>
57
+ <h3><?php _e( 'Defaults', 'post-expirator' ); ?></h3>
58
+ <table class="form-table">
59
+ <tr valign="top">
60
+ <th scope="row"><label for="expired-default-date-format"><?php _e( 'Date Format', 'post-expirator' ); ?></label></th>
61
+ <td>
62
+ <input type="text" name="expired-default-date-format" id="expired-default-date-format" value="<?php echo $expirationdateDefaultDateFormat; ?>" size="25" /> <span class="description">(<?php echo date_i18n( "$expirationdateDefaultDateFormat" ); ?>)</span>
63
+ <p class="description"><?php echo sprintf( __( 'The default format to use when displaying the expiration date within a post using the shortcode or within the footer. For information on valid formatting options, see: %s.', 'post-expirator' ), '<a href="http://us2.php.net/manual/en/function.date.php" target="_blank">PHP Date Function</a>' ); ?></p>
64
+ </td>
65
+ </tr>
66
+ <tr valign="top">
67
+ <th scope="row"><label for="expired-default-time-format"><?php _e( 'Time Format', 'post-expirator' ); ?></label></th>
68
+ <td>
69
+ <input type="text" name="expired-default-time-format" id="expired-default-time-format" value="<?php echo $expirationdateDefaultTimeFormat; ?>" size="25" /> <span class="description">(<?php echo date_i18n( "$expirationdateDefaultTimeFormat" ); ?>)</span>
70
+ <p class="description"><?php echo sprintf( __( 'The default format to use when displaying the expiration time within a post using the shortcode or within the footer. For information on valid formatting options, see: %s.', 'post-expirator' ), '<a href="http://us2.php.net/manual/en/function.date.php" target="_blank">PHP Date Function</a>' ); ?>
71
+ </td>
72
+ </tr>
73
+ <tr valign="top">
74
+ <th scope="row"><label for="expired-default-expiration-date"><?php _e( 'Default Date/Time Duration', 'post-expirator' ); ?></label></th>
75
+ <td>
76
+ <select name="expired-default-expiration-date" id="expired-default-expiration-date" class="pe-custom-date-toggle">
77
+ <option value="null" <?php echo ( $expirationdateDefaultDate == 'null' ) ? ' selected="selected"' : ''; ?>><?php _e( 'None', 'post-expirator' ); ?></option>
78
+ <option value="custom" <?php echo ( $expirationdateDefaultDate == 'custom' ) ? ' selected="selected"' : ''; ?>><?php _e( 'Custom', 'post-expirator' ); ?></option>
79
+ <option value="publish" <?php echo ( $expirationdateDefaultDate == 'publish' ) ? ' selected="selected"' : ''; ?>><?php _e( 'Post/Page Publish Time', 'post-expirator' ); ?></option>
80
+ </select>
81
+ <p class="description"><?php _e( 'Set the default expiration date to be used when creating new posts and pages. Defaults to none.', 'post-expirator' ); ?></p>
82
+ <?php $show = ( $expirationdateDefaultDate == 'custom' ) ? 'block' : 'none'; ?>
83
+ <div id="expired-custom-container" style="display: <?php echo $show; ?>;" class="pe-custom-date-container">
84
+ <br/>
85
+ <label for="expired-custom-expiration-date"><?php _e( 'Custom', 'post-expirator' ); ?>:</label>
86
+ <input type="text" value="<?php echo $expirationdateDefaultDateCustom; ?>" name="expired-custom-expiration-date" id="expired-custom-expiration-date" />
87
+ <p class="description"><?php echo sprintf( __( 'Set the custom value to use for the default expiration date. For information on formatting, see %1$s. For example, you could enter %2$s+1 month%3$s or %4$s+1 week 2 days 4 hours 2 seconds%5$s or %6$snext Thursday%7$s.', 'post-expirator' ), '<a href="http://php.net/manual/en/function.strtotime.php" target="_new">PHP strtotime function</a>', '<code>', '</code>', '<code>', '</code>', '<code>', '</code>' ); ?></p>
88
+ </div>
89
+ </td>
90
+ </tr>
91
+ <tr valign="top">
92
+ <th scope="row"><?php _e( 'Default Expiration Category', 'post-expirator' ); ?></th>
93
+ <td>
94
+ <?php
95
+ echo '<div class="wp-tab-panel" id="post-expirator-cat-list">';
96
+ echo '<ul id="categorychecklist" class="list:category categorychecklist form-no-clear">';
97
+ $walker = new Walker_PostExpirator_Category_Checklist();
98
+ wp_terms_checklist( 0, array( 'taxonomy' => 'category', 'walker' => $walker, 'selected_cats' => $categories, 'checked_ontop' => false ) );
99
+ echo '</ul>';
100
+ echo '</div>';
101
+ ?>
102
+ <p class="description"><?php _e( 'Sets the default expiration category for the post.', 'post-expirator' ); ?></p>
103
+ </td>
104
+ </tr>
105
+ </table>
106
+
107
+ <h3><?php _e( 'Expiration Email Notification', 'post-expirator' ); ?></h3>
108
+ <p class="description"><?php _e( 'Whenever a post expires, an email can be sent to alert users of the expiration.', 'post-expirator' ); ?></p>
109
+ <table class="form-table">
110
+ <tr valign="top">
111
+ <th scope="row"><?php _e( 'Enable Email Notification?', 'post-expirator' ); ?></th>
112
+ <td>
113
+ <input type="radio" name="expired-email-notification" id="expired-email-notification-true" value="1" <?php echo $expiredemailnotificationenabled; ?>/> <label for="expired-email-notification-true"><?php _e( 'Enabled', 'post-expirator' ); ?></label>
114
+ &nbsp;&nbsp;
115
+ <input type="radio" name="expired-email-notification" id="expired-email-notification-false" value="0" <?php echo $expiredemailnotificationdisabled; ?>/> <label for="expired-email-notification-false"><?php _e( 'Disabled', 'post-expirator' ); ?></label>
116
+ <p class="description"><?php _e( 'This will enable or disable the send of email notification on post expiration.', 'post-expirator' ); ?></p>
117
+ </td>
118
+ </tr>
119
+ <tr valign="top">
120
+ <th scope="row"><?php _e( 'Include Blog Administrators?', 'post-expirator' ); ?></th>
121
+ <td>
122
+ <input type="radio" name="expired-email-notification-admins" id="expired-email-notification-admins-true" value="1" <?php echo $expiredemailnotificationadminsenabled; ?>/> <label for="expired-email-notification-admins-true"><?php _e( 'Enabled', 'post-expirator' ); ?></label>
123
+ &nbsp;&nbsp;
124
+ <input type="radio" name="expired-email-notification-admins" id="expired-email-notification-admins-false" value="0" <?php echo $expiredemailnotificationadminsdisabled; ?>/> <label for="expired-email-notification-admins-false"><?php _e( 'Disabled', 'post-expirator' ); ?></label>
125
+ <p class="description"><?php _e( 'This will include all users with the role of "Administrator" in the post expiration email.', 'post-expirator' ); ?></p>
126
+ </td>
127
+ </tr>
128
+ <tr valign="top">
129
+ <th scope="row"><label for="expired-email-notification-list"><?php _e( 'Who to notify', 'post-expirator' ); ?></label></th>
130
+ <td>
131
+ <input class="large-text" type="text" name="expired-email-notification-list" id="expired-email-notification-list" value="<?php echo $expiredemailnotificationlist; ?>" />
132
+ <p class="description"><?php _e( 'Enter a comma separate list of emails that you would like to be notified when the post expires. This will be applied to ALL post types. You can set post type specific emails on the Defaults tab.', 'post-expirator' ); ?></p>
133
+ </td>
134
+ </tr>
135
+ </table>
136
+
137
+ <h3><?php _e( 'Post Footer Display', 'post-expirator' ); ?></h3>
138
+ <p class="description"><?php _e( 'Enabling this below will display the expiration date automatically at the end of any post which is set to expire.', 'post-expirator' ); ?></p>
139
+ <table class="form-table">
140
+ <tr valign="top">
141
+ <th scope="row"><?php _e( 'Show in post footer?', 'post-expirator' ); ?></th>
142
+ <td>
143
+ <input type="radio" name="expired-display-footer" id="expired-display-footer-true" value="1" <?php echo $expireddisplayfooterenabled; ?>/> <label for="expired-display-footer-true"><?php _e( 'Enabled', 'post-expirator' ); ?></label>
144
+ &nbsp;&nbsp;
145
+ <input type="radio" name="expired-display-footer" id="expired-display-footer-false" value="0" <?php echo $expireddisplayfooterdisabled; ?>/> <label for="expired-display-footer-false"><?php _e( 'Disabled', 'post-expirator' ); ?></label>
146
+ <p class="description"><?php _e( 'This will enable or disable displaying the post expiration date in the post footer.', 'post-expirator' ); ?></p>
147
+ </td>
148
+ </tr>
149
+ <tr valign="top">
150
+ <th scope="row"><label for="expired-footer-contents"><?php _e( 'Footer Contents', 'post-expirator' ); ?></label></th>
151
+ <td>
152
+ <textarea id="expired-footer-contents" name="expired-footer-contents" rows="3" cols="50"><?php echo $expirationdateFooterContents; ?></textarea>
153
+ <p class="description"><?php _e( 'Enter the text you would like to appear at the bottom of every post that will expire. The following placeholders will be replaced with the post expiration date in the following format:', 'post-expirator' ); ?></p>
154
+ <ul class="pe-list">
155
+ <li><p class="description">EXPIRATIONFULL -> <?php echo date_i18n( "$expirationdateDefaultDateFormat $expirationdateDefaultTimeFormat" ); ?></p></li>
156
+ <li><p class="description">EXPIRATIONDATE -> <?php echo date_i18n( "$expirationdateDefaultDateFormat" ); ?></p></li>
157
+ <li><p class="description">EXPIRATIONTIME -> <?php echo date_i18n( "$expirationdateDefaultTimeFormat" ); ?></p></li>
158
+ </ul>
159
+ </td>
160
+ </tr>
161
+ <tr valign="top">
162
+ <th scope="row"><label for="expired-footer-style"><?php _e( 'Footer Style', 'post-expirator' ); ?></label></th>
163
+ <td>
164
+ <input type="text" name="expired-footer-style" id="expired-footer-style" value="<?php echo $expirationdateFooterStyle; ?>" size="25" />
165
+ (<span style="<?php echo $expirationdateFooterStyle; ?>"><?php _e( 'This post will expire on', 'post-expirator' ); ?> <?php echo date_i18n( "$expirationdateDefaultDateFormat $expirationdateDefaultTimeFormat" ); ?></span>)
166
+ <p class="description"><?php _e( 'The inline css which will be used to style the footer text.', 'post-expirator' ); ?></p>
167
+ </td>
168
+ </tr>
169
+ </table>
170
+
171
+ <h3><?php _e( 'Advanced Options', 'post-expirator' ); ?></h3>
172
+ <p class="description"><?php _e( 'Please do not update anything here unless you know what it entails. For advanced users only.', 'post-expirator' ); ?></p>
173
+ <?php
174
+ $gutenberg = get_option( 'expirationdateGutenbergSupport', 1 );
175
+ ?>
176
+ <table class="form-table">
177
+ <tr valign="top">
178
+ <th scope="row"><?php _e( 'Block Editor Support', 'post-expirator' ); ?></th>
179
+ <td>
180
+ <input type="radio" name="gutenberg-support" id="gutenberg-support-enabled" value="1" <?php echo intval( $gutenberg ) === 1 ? 'checked' : ''; ?>/> <label for="gutenberg-support-enabled"><?php _e( 'Show Gutenberg style box', 'post-expirator' ); ?></label>
181
+ &nbsp;&nbsp;
182
+ <input type="radio" name="gutenberg-support" id="gutenberg-support-disabled" value="0" <?php echo intval( $gutenberg ) === 0 ? 'checked' : ''; ?>/> <label for="gutenberg-support-disabled"><?php _e( 'Show Classic Editor style box', 'post-expirator' ); ?></label>
183
+ <p class="description"><?php _e( 'Toggle between native support for the Block Editor or the backward compatible Classic Editor style metabox.', 'post-expirator' ); ?></p>
184
+ </td>
185
+ </tr>
186
+ </table>
187
+
188
+ <p class="submit">
189
+ <input type="submit" name="expirationdateSave" class="button-primary" value="<?php _e( 'Save Changes', 'post-expirator' ); ?>" />
190
+ </p>
191
+ </form>
192
+
193
+ <?php
194
+ // phpcs:enable
views/quick-edit.php ADDED
@@ -0,0 +1,74 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <div style="clear:both"></div>
2
+ <fieldset class="inline-edit-col-left post-expirator-quickedit">
3
+ <div class="inline-edit-col">
4
+ <div class="inline-edit-group">
5
+ <label >
6
+ <input name="enable-expirationdate" type="checkbox" />
7
+ <span class=""><?php _e( 'Enable Post Expiration', 'post-expirator' ); ?></span>
8
+ </label>
9
+ <fieldset class="inline-edit-date">
10
+ <div class="pe-qe-fields" style="display: none">
11
+ <div>
12
+ <legend><span class="title"><?php _e( 'Date', 'post-expirator' ); ?></span></legend>
13
+ <label>
14
+ <span class="screen-reader-text"><?php _e( 'Month', 'post-expirator' ); ?></span>
15
+ <select name="expirationdate_month">
16
+ <?php
17
+ for ( $x = 1; $x <= 12; $x++ ) {
18
+ $now = mktime( 0, 0, 0, $x, 1, date_i18n( 'Y' ) );
19
+ $monthNumeric = date_i18n( 'm', $now );
20
+ $monthStr = date_i18n( 'M', $now );
21
+ ?>
22
+ <option value="<?php echo $monthNumeric; ?>" data-text="<?php echo $monthStr; ?>"><?php echo $monthNumeric; ?>-<?php echo $monthStr; ?></option>
23
+ <?php } ?>
24
+
25
+ </select>
26
+ </label>
27
+ <label>
28
+ <span class="screen-reader-text"><?php _e( 'Day', 'post-expirator' ); ?></span>
29
+ <input name="expirationdate_day" value="" size="2" maxlength="2" autocomplete="off" type="text" placeholder="<?php echo date( 'd' ); ?>">
30
+ </label>,
31
+ <label>
32
+ <span class="screen-reader-text"><?php _e( 'Year', 'post-expirator' ); ?></span>
33
+ <input name="expirationdate_year" value="" size="4" maxlength="4" autocomplete="off" type="text" placeholder="<?php echo date( 'Y' ); ?>">
34
+ </label> @
35
+ <label>
36
+ <span class="screen-reader-text"><?php _e( 'Hour', 'post-expirator' ); ?></span>
37
+ <input name="expirationdate_hour" value="" size="2" maxlength="2" autocomplete="off" type="text" placeholder="00">
38
+ </label> :
39
+ <label>
40
+ <span class="screen-reader-text"><?php _e( 'Minute', 'post-expirator' ); ?></span>
41
+ <input name="expirationdate_minute" value="" size="2" maxlength="2" autocomplete="off" type="text" placeholder="00">
42
+ </label>
43
+ </div>
44
+ <div>
45
+ <legend>
46
+ <span class="title"><?php _e( 'Type', 'post-expirator' ); ?></span>
47
+ <span class="screen-reader-text"><?php _e( 'How to expire', 'post-expirator' ); ?></span>
48
+ </legend>
49
+ <?php
50
+ $defaults = get_option( 'expirationdateDefaults' . ucfirst( $post_type ) );
51
+ _postexpirator_expire_type( array( 'name' => 'expirationdate_expiretype', 'selected' => $defaults['expireType'], 'post_type' => $post_type ) );
52
+ ?>
53
+ </div>
54
+ <div class="pe-category-list">
55
+ <legend>
56
+ <span class="title"><?php echo $tax_label; ?></span>
57
+ <span class="screen-reader-text"><?php _e( 'Expiration Categories', 'post-expirator' ); ?></span>
58
+ </legend>
59
+ <ul id="categorychecklist" class="list:category categorychecklist cat-checklist category-checklist">
60
+ <?php
61
+ if ( ! empty( $taxonomy ) ) {
62
+ $walker = new Walker_PostExpirator_Category_Checklist();
63
+ wp_terms_checklist( 0, array( 'taxonomy' => $taxonomy, 'walker' => $walker, 'checked_ontop' => false ) );
64
+ }
65
+ ?>
66
+ </ul>
67
+ </div>
68
+
69
+ </div>
70
+ <input name="expirationdate_quickedit" value="true" type="hidden"/>
71
+ </fieldset>
72
+ </div>
73
+ </div>
74
+ </fieldset>
views/tabs.php ADDED
@@ -0,0 +1,20 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ $current_tab = empty( $_GET['tab'] ) ? 'general' : sanitize_title( wp_unslash( $_GET['tab'] ) );
3
+ ?>
4
+
5
+ <div class="wrap">
6
+ <h2><?php __( 'Post Expirator Options', 'post-expirator' ); ?></h2>
7
+ <div id="pe-settings-tabs">
8
+ <nav class="nav-tab-wrapper postexpirator-nav-tab-wrapper">
9
+ <a href="<?php echo admin_url( 'options-general.php?page=post-expirator.php&tab=general' ); ?>" class="pe-tab nav-tab <?php echo ( $current_tab === 'general' ? 'nav-tab-active' : '' ); ?>"><?php _e( 'General Settings', 'post-expirator' ); ?></a>
10
+ <a href="<?php echo admin_url( 'options-general.php?page=post-expirator.php&tab=defaults' ); ?>" class="pe-tab nav-tab <?php echo ( $current_tab === 'defaults' ? 'nav-tab-active' : '' ); ?>"><?php _e( 'Post Types', 'post-expirator' ); ?></a>
11
+ <a href="<?php echo admin_url( 'options-general.php?page=post-expirator.php&tab=diagnostics' ); ?>" class="pe-tab nav-tab <?php echo ( $current_tab === 'diagnostics' ? 'nav-tab-active' : '' ); ?>"><?php _e( 'Diagnostics', 'post-expirator' ); ?></a>
12
+ <?php if ( POSTEXPIRATOR_DEBUG ) { ?>
13
+ <a href="<?php echo admin_url( 'options-general.php?page=post-expirator.php&tab=viewdebug' ); ?>" class="pe-tab nav-tab <?php echo ( $current_tab === 'viewdebug' ? 'nav-tab-active' : '' ); ?>"><?php _e( 'View Debug Logs', 'post-expirator' ); ?></a>
14
+ <?php } ?>
15
+ </nav>
16
+
17
+ <?php echo $html; ?>
18
+
19
+ </div>
20
+ </div>