Bulk Delete - Version 5.5

Version Description

Added the ability to delete users based on user meta and lot of UI improvement

Download this release

Release Info

Developer sudar
Plugin Icon 128x128 Bulk Delete
Version 5.5
Comparing to
See all releases

Code changes from version 5.4.1 to 5.5

Files changed (70) hide show
  1. assets/css/bulk-delete.css +13 -0
  2. assets/css/bulk-delete.css.map +1 -0
  3. assets/css/bulk-delete.min.css +3 -0
  4. assets/css/jquery-ui-timepicker-addon.min.css +5 -0
  5. assets/css/select2.min.css +1 -0
  6. assets/js/bulk-delete.js +160 -0
  7. assets/js/bulk-delete.js.map +1 -0
  8. assets/js/bulk-delete.min.js +4 -0
  9. assets/js/jquery-ui-timepicker-addon.min.js +5 -0
  10. assets/js/select2.min.js +2 -0
  11. bulk-delete.php +585 -631
  12. include/addons/addon-list.php +146 -0
  13. include/addons/base/class-bd-addon.php +135 -0
  14. include/addons/base/class-bd-base-addon.php +61 -0
  15. include/addons/base/class-bd-scheduler-addon.php +180 -0
  16. include/addons/pages.php +56 -0
  17. include/addons/posts.php +171 -0
  18. include/addons/util.php +71 -0
  19. include/admin-ui.php +0 -90
  20. include/base/class-bd-meta-box-module.php +358 -0
  21. include/base/class-bd-page.php +273 -0
  22. include/class-bd-edd-api-wrapper.php +0 -154
  23. include/class-bd-license-handler.php +0 -187
  24. include/class-bd-license.php +0 -478
  25. include/class-bd-settings.php +0 -58
  26. include/class-bulk-delete-by-days.php +9 -28
  27. include/class-bulk-delete-help-screen.php +0 -122
  28. include/class-bulk-delete-pages.php +0 -302
  29. include/class-bulk-delete-posts.php +0 -1692
  30. include/class-bulk-delete-users.php +0 -248
  31. include/class-bulk-delete-util.php +0 -232
  32. include/class-cron-list-table.php +0 -141
  33. include/class-license-list-table.php +0 -165
  34. include/compatibility/simple-login-log.php +40 -0
  35. include/cron/class-cron-list-table.php +161 -0
  36. include/deprecated/class-bulk-delete-users.php +24 -0
  37. include/deprecated/deprecated.php +62 -0
  38. include/libraries/EDD_SL_Plugin_Updater.php +324 -162
  39. include/libraries/browser.php +0 -1082
  40. include/license/class-bd-edd-api-wrapper.php +156 -0
  41. include/license/class-bd-license-handler.php +300 -0
  42. include/license/class-bd-license.php +355 -0
  43. include/license/class-license-list-table.php +171 -0
  44. include/meta/class-bulk-delete-comment-meta.php +188 -186
  45. include/meta/class-bulk-delete-meta.php +131 -126
  46. include/meta/class-bulk-delete-post-meta.php +189 -188
  47. include/meta/class-bulk-delete-user-meta.php +165 -163
  48. include/misc/class-bulk-delete-jetpack-contact-form-messages.php +208 -208
  49. include/misc/class-bulk-delete-misc.php +129 -126
  50. include/pages/class-bulk-delete-pages.php +207 -0
  51. include/posts/class-bulk-delete-posts.php +1043 -0
  52. include/settings/class-bd-settings-page.php +95 -90
  53. include/settings/class-bd-settings.php +64 -0
  54. include/settings/setting-helpers.php +20 -17
  55. include/{class-bulk-delete-system-info.php → system-info/class-bulk-delete-system-info.php} +121 -111
  56. include/ui/admin-ui.php +87 -0
  57. include/ui/class-bulk-delete-help-screen.php +112 -0
  58. include/ui/form.php +179 -0
  59. include/users/class-bd-users-page.php +95 -0
  60. include/users/modules/class-bulk-delete-users-by-user-meta.php +207 -0
  61. include/users/modules/class-bulk-delete-users-by-user-role.php +184 -0
  62. include/util.php +0 -26
  63. include/util/class-bd-util.php +264 -0
  64. include/util/class-bulk-delete-by-days.php +55 -0
  65. include/util/query.php +79 -0
  66. js/bulk-delete.js +0 -144
  67. js/jquery-ui-timepicker.js +0 -2134
  68. languages/bulk-delete.pot +873 -819
  69. readme.txt +43 -5
  70. style/jquery-ui-timepicker.css +0 -10
assets/css/bulk-delete.css ADDED
@@ -0,0 +1,13 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /*! Bulk Delete - v5.5.0 %>
2
+ * http://bulkwp.com
3
+ * Copyright (c) 2015; * Licensed GPLv2+ */
4
+ select[multiple].select2 {
5
+ width: 60%;
6
+ }
7
+
8
+ #post-body .select2-search__field {
9
+ -webkit-box-shadow: none;
10
+ box-shadow: none;
11
+ }
12
+
13
+ /*# sourceMappingURL=bulk-delete.css.map */
assets/css/bulk-delete.css.map ADDED
@@ -0,0 +1 @@
 
1
+ {"version":3,"sources":["src/select2-compat.css"],"names":[],"mappings":";;;AAAA,MAAM,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;AAC1B,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE;AACZ,CAAC;AACD;AACA,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,aAAa,CAAC,CAAC;AACnC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC;AAC1B,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC;AAClB,CAAC","file":"bulk-delete.css","sourcesContent":["select[multiple].select2 {\n\twidth: 60%;\n}\n\n#post-body .select2-search__field {\n\t-webkit-box-shadow: none;\n\tbox-shadow: none;\n}\n"]}
assets/css/bulk-delete.min.css ADDED
@@ -0,0 +1,3 @@
 
 
 
1
+ /*! Bulk Delete - v5.5.0 %>
2
+ * http://bulkwp.com
3
+ * Copyright (c) 2015; * Licensed GPLv2+ */select[multiple].select2{width:60%}#post-body .select2-search__field{-webkit-box-shadow:none;box-shadow:none}
assets/css/jquery-ui-timepicker-addon.min.css ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
1
+ /*! jQuery Timepicker Addon - v1.5.4 - 2015-05-11
2
+ * http://trentrichardson.com/examples/timepicker
3
+ * Copyright (c) 2015 Trent Richardson; Licensed MIT */
4
+
5
+ .ui-timepicker-div .ui-widget-header{margin-bottom:8px}.ui-timepicker-div dl{text-align:left}.ui-timepicker-div dl dt{float:left;clear:left;padding:0 0 0 5px}.ui-timepicker-div dl dd{margin:0 10px 10px 40%}.ui-timepicker-div td{font-size:90%}.ui-tpicker-grid-label{background:0 0;border:0;margin:0;padding:0}.ui-timepicker-div .ui_tpicker_unit_hide{display:none}.ui-timepicker-rtl{direction:rtl}.ui-timepicker-rtl dl{text-align:right;padding:0 5px 0 0}.ui-timepicker-rtl dl dt{float:right;clear:right}.ui-timepicker-rtl dl dd{margin:0 40% 10px 10px}.ui-timepicker-div.ui-timepicker-oneLine{padding-right:2px}.ui-timepicker-div.ui-timepicker-oneLine .ui_tpicker_time,.ui-timepicker-div.ui-timepicker-oneLine dt{display:none}.ui-timepicker-div.ui-timepicker-oneLine .ui_tpicker_time_label{display:block;padding-top:2px}.ui-timepicker-div.ui-timepicker-oneLine dl{text-align:right}.ui-timepicker-div.ui-timepicker-oneLine dl dd,.ui-timepicker-div.ui-timepicker-oneLine dl dd>div{display:inline-block;margin:0}.ui-timepicker-div.ui-timepicker-oneLine dl dd.ui_tpicker_minute:before,.ui-timepicker-div.ui-timepicker-oneLine dl dd.ui_tpicker_second:before{content:':';display:inline-block}.ui-timepicker-div.ui-timepicker-oneLine dl dd.ui_tpicker_millisec:before,.ui-timepicker-div.ui-timepicker-oneLine dl dd.ui_tpicker_microsec:before{content:'.';display:inline-block}.ui-timepicker-div.ui-timepicker-oneLine .ui_tpicker_unit_hide,.ui-timepicker-div.ui-timepicker-oneLine .ui_tpicker_unit_hide:before{display:none}
assets/css/select2.min.css ADDED
@@ -0,0 +1 @@
 
1
+ .select2-container{box-sizing:border-box;display:inline-block;margin:0;position:relative;vertical-align:middle;}.select2-container .select2-selection--single{box-sizing:border-box;cursor:pointer;display:block;height:28px;user-select:none;-webkit-user-select:none;}.select2-container .select2-selection--single .select2-selection__rendered{display:block;padding-left:8px;padding-right:20px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}.select2-container[dir="rtl"] .select2-selection--single .select2-selection__rendered{padding-right:8px;padding-left:20px;}.select2-container .select2-selection--multiple{box-sizing:border-box;cursor:pointer;display:block;min-height:32px;user-select:none;-webkit-user-select:none;}.select2-container .select2-selection--multiple .select2-selection__rendered{display:inline-block;overflow:hidden;padding-left:8px;text-overflow:ellipsis;white-space:nowrap;}.select2-container .select2-search--inline{float:left;}.select2-container .select2-search--inline .select2-search__field{box-sizing:border-box;border:none;font-size:100%;margin-top:5px;}.select2-container .select2-search--inline .select2-search__field::-webkit-search-cancel-button{-webkit-appearance:none;}.select2-dropdown{background-color:white;border:1px solid #aaa;border-radius:4px;box-sizing:border-box;display:block;position:absolute;left:-100000px;width:100%;z-index:1051;}.select2-results{display:block;}.select2-results__options{list-style:none;margin:0;padding:0;}.select2-results__option{padding:6px;user-select:none;-webkit-user-select:none;}.select2-results__option[aria-selected]{cursor:pointer;}.select2-container--open .select2-dropdown{left:0;}.select2-container--open .select2-dropdown--above{border-bottom:none;border-bottom-left-radius:0;border-bottom-right-radius:0;}.select2-container--open .select2-dropdown--below{border-top:none;border-top-left-radius:0;border-top-right-radius:0;}.select2-search--dropdown{display:block;padding:4px;}.select2-search--dropdown .select2-search__field{padding:4px;width:100%;box-sizing:border-box;}.select2-search--dropdown .select2-search__field::-webkit-search-cancel-button{-webkit-appearance:none;}.select2-search--dropdown.select2-search--hide{display:none;}.select2-close-mask{border:0;margin:0;padding:0;display:block;position:fixed;left:0;top:0;min-height:100%;min-width:100%;height:auto;width:auto;opacity:0;z-index:99;background-color:#fff;filter:alpha(opacity=0);}.select2-hidden-accessible{border:0;clip:rect(0 0 0 0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px;}.select2-container--default .select2-selection--single{background-color:#fff;border:1px solid #aaa;border-radius:4px;}.select2-container--default .select2-selection--single .select2-selection__rendered{color:#444;line-height:28px;}.select2-container--default .select2-selection--single .select2-selection__clear{cursor:pointer;float:right;font-weight:bold;}.select2-container--default .select2-selection--single .select2-selection__placeholder{color:#999;}.select2-container--default .select2-selection--single .select2-selection__arrow{height:26px;position:absolute;top:1px;right:1px;width:20px;}.select2-container--default .select2-selection--single .select2-selection__arrow b{border-color:#888 transparent transparent transparent;border-style:solid;border-width:5px 4px 0 4px;height:0;left:50%;margin-left:-4px;margin-top:-2px;position:absolute;top:50%;width:0;}.select2-container--default[dir="rtl"] .select2-selection--single .select2-selection__clear{float:left;}.select2-container--default[dir="rtl"] .select2-selection--single .select2-selection__arrow{left:1px;right:auto;}.select2-container--default.select2-container--disabled .select2-selection--single{background-color:#eee;cursor:default;}.select2-container--default.select2-container--disabled .select2-selection--single .select2-selection__clear{display:none;}.select2-container--default.select2-container--open .select2-selection--single .select2-selection__arrow b{border-color:transparent transparent #888 transparent;border-width:0 4px 5px 4px;}.select2-container--default .select2-selection--multiple{background-color:white;border:1px solid #aaa;border-radius:4px;cursor:text;}.select2-container--default .select2-selection--multiple .select2-selection__rendered{box-sizing:border-box;list-style:none;margin:0;padding:0 5px;width:100%;}.select2-container--default .select2-selection--multiple .select2-selection__placeholder{color:#999;margin-top:5px;float:left;}.select2-container--default .select2-selection--multiple .select2-selection__clear{cursor:pointer;float:right;font-weight:bold;margin-top:5px;margin-right:10px;}.select2-container--default .select2-selection--multiple .select2-selection__choice{background-color:#e4e4e4;border:1px solid #aaa;border-radius:4px;cursor:default;float:left;margin-right:5px;margin-top:5px;padding:0 5px;}.select2-container--default .select2-selection--multiple .select2-selection__choice__remove{color:#999;cursor:pointer;display:inline-block;font-weight:bold;margin-right:2px;}.select2-container--default .select2-selection--multiple .select2-selection__choice__remove:hover{color:#333;}.select2-container--default[dir="rtl"] .select2-selection--multiple .select2-selection__choice,.select2-container--default[dir="rtl"] .select2-selection--multiple .select2-selection__placeholder{float:right;}.select2-container--default[dir="rtl"] .select2-selection--multiple .select2-selection__choice{margin-left:5px;margin-right:auto;}.select2-container--default[dir="rtl"] .select2-selection--multiple .select2-selection__choice__remove{margin-left:2px;margin-right:auto;}.select2-container--default.select2-container--focus .select2-selection--multiple{border:solid black 1px;outline:0;}.select2-container--default.select2-container--disabled .select2-selection--multiple{background-color:#eee;cursor:default;}.select2-container--default.select2-container--disabled .select2-selection__choice__remove{display:none;}.select2-container--default.select2-container--open.select2-container--above .select2-selection--single,.select2-container--default.select2-container--open.select2-container--above .select2-selection--multiple{border-top-left-radius:0;border-top-right-radius:0;}.select2-container--default.select2-container--open.select2-container--below .select2-selection--single,.select2-container--default.select2-container--open.select2-container--below .select2-selection--multiple{border-bottom-left-radius:0;border-bottom-right-radius:0;}.select2-container--default .select2-search--dropdown .select2-search__field{border:1px solid #aaa;}.select2-container--default .select2-search--inline .select2-search__field{background:transparent;border:none;outline:0;}.select2-container--default .select2-results>.select2-results__options{max-height:200px;overflow-y:auto;}.select2-container--default .select2-results__option[role=group]{padding:0;}.select2-container--default .select2-results__option[aria-disabled=true]{color:#999;}.select2-container--default .select2-results__option[aria-selected=true]{background-color:#ddd;}.select2-container--default .select2-results__option .select2-results__option{padding-left:1em;}.select2-container--default .select2-results__option .select2-results__option .select2-results__group{padding-left:0;}.select2-container--default .select2-results__option .select2-results__option .select2-results__option{margin-left:-1em;padding-left:2em;}.select2-container--default .select2-results__option .select2-results__option .select2-results__option .select2-results__option{margin-left:-2em;padding-left:3em;}.select2-container--default .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option{margin-left:-3em;padding-left:4em;}.select2-container--default .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option{margin-left:-4em;padding-left:5em;}.select2-container--default .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option{margin-left:-5em;padding-left:6em;}.select2-container--default .select2-results__option--highlighted[aria-selected]{background-color:#5897fb;color:white;}.select2-container--default .select2-results__group{cursor:default;display:block;padding:6px;}.select2-container--classic .select2-selection--single{background-color:#f6f6f6;border:1px solid #aaa;border-radius:4px;outline:0;background-image:-webkit-linear-gradient(top, #ffffff 50%, #eeeeee 100%);background-image:-o-linear-gradient(top, #ffffff 50%, #eeeeee 100%);background-image:linear-gradient(to bottom, #ffffff 50%, #eeeeee 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffff', endColorstr='#eeeeee', GradientType=0);}.select2-container--classic .select2-selection--single:focus{border:1px solid #5897fb;}.select2-container--classic .select2-selection--single .select2-selection__rendered{color:#444;line-height:28px;}.select2-container--classic .select2-selection--single .select2-selection__clear{cursor:pointer;float:right;font-weight:bold;margin-right:10px;}.select2-container--classic .select2-selection--single .select2-selection__placeholder{color:#999;}.select2-container--classic .select2-selection--single .select2-selection__arrow{background-color:#ddd;border:none;border-left:1px solid #aaa;border-top-right-radius:4px;border-bottom-right-radius:4px;height:26px;position:absolute;top:1px;right:1px;width:20px;background-image:-webkit-linear-gradient(top, #eeeeee 50%, #cccccc 100%);background-image:-o-linear-gradient(top, #eeeeee 50%, #cccccc 100%);background-image:linear-gradient(to bottom, #eeeeee 50%, #cccccc 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#eeeeee', endColorstr='#cccccc', GradientType=0);}.select2-container--classic .select2-selection--single .select2-selection__arrow b{border-color:#888 transparent transparent transparent;border-style:solid;border-width:5px 4px 0 4px;height:0;left:50%;margin-left:-4px;margin-top:-2px;position:absolute;top:50%;width:0;}.select2-container--classic[dir="rtl"] .select2-selection--single .select2-selection__clear{float:left;}.select2-container--classic[dir="rtl"] .select2-selection--single .select2-selection__arrow{border:none;border-right:1px solid #aaa;border-radius:0;border-top-left-radius:4px;border-bottom-left-radius:4px;left:1px;right:auto;}.select2-container--classic.select2-container--open .select2-selection--single{border:1px solid #5897fb;}.select2-container--classic.select2-container--open .select2-selection--single .select2-selection__arrow{background:transparent;border:none;}.select2-container--classic.select2-container--open .select2-selection--single .select2-selection__arrow b{border-color:transparent transparent #888 transparent;border-width:0 4px 5px 4px;}.select2-container--classic.select2-container--open.select2-container--above .select2-selection--single{border-top:none;border-top-left-radius:0;border-top-right-radius:0;background-image:-webkit-linear-gradient(top, #ffffff 0%, #eeeeee 50%);background-image:-o-linear-gradient(top, #ffffff 0%, #eeeeee 50%);background-image:linear-gradient(to bottom, #ffffff 0%, #eeeeee 50%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffff', endColorstr='#eeeeee', GradientType=0);}.select2-container--classic.select2-container--open.select2-container--below .select2-selection--single{border-bottom:none;border-bottom-left-radius:0;border-bottom-right-radius:0;background-image:-webkit-linear-gradient(top, #eeeeee 50%, #ffffff 100%);background-image:-o-linear-gradient(top, #eeeeee 50%, #ffffff 100%);background-image:linear-gradient(to bottom, #eeeeee 50%, #ffffff 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#eeeeee', endColorstr='#ffffff', GradientType=0);}.select2-container--classic .select2-selection--multiple{background-color:white;border:1px solid #aaa;border-radius:4px;cursor:text;outline:0;}.select2-container--classic .select2-selection--multiple:focus{border:1px solid #5897fb;}.select2-container--classic .select2-selection--multiple .select2-selection__rendered{list-style:none;margin:0;padding:0 5px;}.select2-container--classic .select2-selection--multiple .select2-selection__clear{display:none;}.select2-container--classic .select2-selection--multiple .select2-selection__choice{background-color:#e4e4e4;border:1px solid #aaa;border-radius:4px;cursor:default;float:left;margin-right:5px;margin-top:5px;padding:0 5px;}.select2-container--classic .select2-selection--multiple .select2-selection__choice__remove{color:#888;cursor:pointer;display:inline-block;font-weight:bold;margin-right:2px;}.select2-container--classic .select2-selection--multiple .select2-selection__choice__remove:hover{color:#555;}.select2-container--classic[dir="rtl"] .select2-selection--multiple .select2-selection__choice{float:right;}.select2-container--classic[dir="rtl"] .select2-selection--multiple .select2-selection__choice{margin-left:5px;margin-right:auto;}.select2-container--classic[dir="rtl"] .select2-selection--multiple .select2-selection__choice__remove{margin-left:2px;margin-right:auto;}.select2-container--classic.select2-container--open .select2-selection--multiple{border:1px solid #5897fb;}.select2-container--classic.select2-container--open.select2-container--above .select2-selection--multiple{border-top:none;border-top-left-radius:0;border-top-right-radius:0;}.select2-container--classic.select2-container--open.select2-container--below .select2-selection--multiple{border-bottom:none;border-bottom-left-radius:0;border-bottom-right-radius:0;}.select2-container--classic .select2-search--dropdown .select2-search__field{border:1px solid #aaa;outline:0;}.select2-container--classic .select2-search--inline .select2-search__field{outline:0;}.select2-container--classic .select2-dropdown{background-color:white;border:1px solid transparent;}.select2-container--classic .select2-dropdown--above{border-bottom:none;}.select2-container--classic .select2-dropdown--below{border-top:none;}.select2-container--classic .select2-results>.select2-results__options{max-height:200px;overflow-y:auto;}.select2-container--classic .select2-results__option[role=group]{padding:0;}.select2-container--classic .select2-results__option[aria-disabled=true]{color:grey;}.select2-container--classic .select2-results__option--highlighted[aria-selected]{background-color:#3875d7;color:white;}.select2-container--classic .select2-results__group{cursor:default;display:block;padding:6px;}.select2-container--classic.select2-container--open .select2-dropdown{border-color:#5897fb;}
assets/js/bulk-delete.js ADDED
@@ -0,0 +1,160 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /*! Bulk Delete - v5.5.0 %>
2
+ * http://bulkwp.com
3
+ * Copyright (c) 2015; * Licensed GPLv2+ */
4
+ /*global BulkWP, postboxes, pagenow*/
5
+ jQuery(document).ready(function () {
6
+ /**
7
+ * Enable select2
8
+ */
9
+ jQuery( '.select2' ).select2();
10
+
11
+ /**
12
+ * Enable Postbox handling
13
+ */
14
+ postboxes.add_postbox_toggles(pagenow);
15
+
16
+ /**
17
+ * Toggle the date restrict fields
18
+ */
19
+ function toggle_date_restrict(el) {
20
+ if (jQuery("#smbd" + el + "_restrict").is(":checked")) {
21
+ jQuery("#smbd" + el + "_op").removeAttr('disabled');
22
+ jQuery("#smbd" + el + "_days").removeAttr('disabled');
23
+ } else {
24
+ jQuery("#smbd" + el + "_op").attr('disabled', 'true');
25
+ jQuery("#smbd" + el + "_days").attr('disabled', 'true');
26
+ }
27
+ }
28
+
29
+ /**
30
+ * Toggle limit restrict fields
31
+ */
32
+ function toggle_limit_restrict(el) {
33
+ if (jQuery("#smbd" + el + "_limit").is(":checked")) {
34
+ jQuery("#smbd" + el + "_limit_to").removeAttr('disabled');
35
+ } else {
36
+ jQuery("#smbd" + el + "_limit_to").attr('disabled', 'true');
37
+ }
38
+ }
39
+
40
+ /**
41
+ * Toggle user login restrict fields
42
+ */
43
+ function toggle_login_restrict(el) {
44
+ if (jQuery("#smbd" + el + "_login_restrict").is(":checked")) {
45
+ jQuery("#smbd" + el + "_login_days").removeAttr('disabled');
46
+ } else {
47
+ jQuery("#smbd" + el + "_login_days").attr('disabled', 'true');
48
+ }
49
+ }
50
+
51
+ // hide all terms
52
+ function hideAllTerms() {
53
+ jQuery('table.terms').hide();
54
+ jQuery('input.terms').attr('checked', false);
55
+ }
56
+ // call it for the first time
57
+ hideAllTerms();
58
+
59
+ // taxonomy click handling
60
+ jQuery('.custom-tax').change(function () {
61
+ var $this = jQuery(this),
62
+ $tax = $this.val(),
63
+ $terms = jQuery('table.terms_' + $tax);
64
+
65
+ if ($this.is(':checked')) {
66
+ hideAllTerms();
67
+ $terms.show('slow');
68
+ }
69
+ });
70
+
71
+ // date time picker
72
+ jQuery.each(BulkWP.dt_iterators, function (index, value) {
73
+ // invoke the date time picker
74
+ jQuery('#smbd' + value + '_cron_start').datetimepicker({
75
+ timeFormat: 'HH:mm:ss'
76
+ });
77
+
78
+ jQuery('#smbd' + value + '_restrict').change(function () {
79
+ toggle_date_restrict(value);
80
+ });
81
+
82
+ jQuery('#smbd' + value + '_limit').change(function () {
83
+ toggle_limit_restrict(value);
84
+ });
85
+
86
+ jQuery('#smbd' + value + '_login_restrict').change(function () {
87
+ toggle_login_restrict(value);
88
+ });
89
+ });
90
+
91
+ jQuery.each( BulkWP.pro_iterators, function ( index, value) {
92
+ jQuery('.bd-' + value.replace( '_', '-' ) + '-pro').hide();
93
+ jQuery('#smbd_' + value + '_cron_freq, #smbd_' + value + '_cron_start, #smbd_' + value + '_cron').removeAttr('disabled');
94
+ } );
95
+
96
+ // Validate user action
97
+ jQuery('button[name="bd_action"]').click(function () {
98
+ var currentButton = jQuery(this).val(),
99
+ valid = false,
100
+ msg_key = "deletePostsWarning",
101
+ error_key = "selectPostOption";
102
+
103
+ if (currentButton in BulkWP.validators) {
104
+ valid = BulkWP[BulkWP.validators[currentButton]](this);
105
+ } else {
106
+ if (jQuery(this).parent().prev().children('table').find(":checkbox:checked[value!='true']").size() > 0) { // monstrous selector
107
+ valid = true;
108
+ }
109
+ }
110
+
111
+ if (valid) {
112
+ if (currentButton in BulkWP.pre_action_msg) {
113
+ msg_key = BulkWP.pre_action_msg[currentButton];
114
+ }
115
+
116
+ return confirm(BulkWP.msg[msg_key]);
117
+ } else {
118
+ if (currentButton in BulkWP.error_msg) {
119
+ error_key = BulkWP.error_msg[currentButton];
120
+ }
121
+
122
+ alert(BulkWP.msg[error_key]);
123
+ }
124
+
125
+ return false;
126
+ });
127
+
128
+ /**
129
+ * Validation functions
130
+ */
131
+ BulkWP.noValidation = function() {
132
+ return true;
133
+ };
134
+
135
+ BulkWP.validateSelect2 = function(that) {
136
+ if (null !== jQuery(that).parent().prev().children().find(".select2[multiple]").val()) {
137
+ return true;
138
+ } else {
139
+ return false;
140
+ }
141
+ };
142
+
143
+ BulkWP.validateUrl = function(that) {
144
+ if (jQuery(that).parent().prev().children('table').find("textarea").val() !== '') {
145
+ return true;
146
+ } else {
147
+ return false;
148
+ }
149
+ };
150
+
151
+ BulkWP.validateUserMeta = function() {
152
+ if (jQuery('#smbd_u_meta_value').val() !== '') {
153
+ return true;
154
+ } else {
155
+ return false;
156
+ }
157
+ };
158
+ });
159
+
160
+ //# sourceMappingURL=bulk-delete.js.map
assets/js/bulk-delete.js.map ADDED
@@ -0,0 +1 @@
 
1
+ {"version":3,"sources":["src/bulk-delete.js"],"names":[],"mappings":";;;AAAA,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,CAAC,OAAO,EAAE;AACrC,MAAM,CAAC,QAAQ,EAAE,KAAK,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;AACpC,CAAC,GAAG;AACJ,EAAE,CAAC,CAAC,MAAM,CAAC,OAAO;AAClB,EAAE,EAAE;AACJ,CAAC,MAAM,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC,EAAE,OAAO,GAAG;AAChC;AACA,CAAC,GAAG;AACJ,EAAE,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,QAAQ;AAC3B,EAAE,EAAE;AACJ,CAAC,SAAS,CAAC,mBAAmB,CAAC,OAAO,EAAE;AACxC;AACA,CAAC,GAAG;AACJ,EAAE,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,MAAM;AACnC,EAAE,EAAE;AACJ,CAAC,QAAQ,CAAC,oBAAoB,CAAC,EAAE,CAAC,CAAC,CAAC;AACpC,EAAE,EAAE,CAAC,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,SAAS,GAAG,EAAE,GAAG,OAAO,GAAG,CAAC,CAAC;AAC1D,GAAG,MAAM,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,UAAU,EAAE,QAAQ,GAAG;AACvD,GAAG,MAAM,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,KAAK,GAAG,UAAU,EAAE,QAAQ,GAAG;AACzD,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC;AACV,GAAG,MAAM,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,IAAI,EAAE,QAAQ,EAAE,CAAC,CAAC,IAAI,GAAG;AACzD,GAAG,MAAM,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,KAAK,GAAG,IAAI,EAAE,QAAQ,EAAE,CAAC,CAAC,IAAI,GAAG;AAC3D,EAAE,CAAC;AACH,CAAC,CAAC;AACF;AACA,CAAC,GAAG;AACJ,EAAE,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,MAAM;AAChC,EAAE,EAAE;AACJ,CAAC,QAAQ,CAAC,qBAAqB,CAAC,EAAE,CAAC,CAAC,CAAC;AACrC,EAAE,EAAE,CAAC,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,MAAM,GAAG,EAAE,GAAG,OAAO,GAAG,CAAC,CAAC;AACvD,GAAG,MAAM,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,SAAS,GAAG,UAAU,EAAE,QAAQ,GAAG;AAC7D,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC;AACV,GAAG,MAAM,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,SAAS,GAAG,IAAI,EAAE,QAAQ,EAAE,CAAC,CAAC,IAAI,GAAG;AAC/D,EAAE,CAAC;AACH,CAAC,CAAC;AACF;AACA,CAAC,GAAG;AACJ,EAAE,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,MAAM;AACrC,EAAE,EAAE;AACJ,CAAC,QAAQ,CAAC,qBAAqB,CAAC,EAAE,CAAC,CAAC,CAAC;AACrC,EAAE,EAAE,CAAC,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,eAAe,GAAG,EAAE,GAAG,OAAO,GAAG,CAAC,CAAC;AAChE,GAAG,MAAM,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,WAAW,GAAG,UAAU,EAAE,QAAQ,GAAG;AAC/D,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC;AACV,GAAG,MAAM,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,WAAW,GAAG,IAAI,EAAE,QAAQ,EAAE,CAAC,CAAC,IAAI,GAAG;AACjE,EAAE,CAAC;AACH,CAAC,CAAC;AACF;AACA,CAAC,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK;AAClB,CAAC,QAAQ,CAAC,YAAY,EAAE,CAAC,CAAC;AAC1B,EAAE,MAAM,EAAE,KAAK,CAAC,KAAK,GAAG,IAAI,GAAG;AAC/B,EAAE,MAAM,EAAE,KAAK,CAAC,KAAK,GAAG,IAAI,EAAE,OAAO,EAAE,CAAC,KAAK,EAAE;AAC/C,CAAC,CAAC;AACF,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI;AAC9B,CAAC,YAAY,GAAG;AAChB;AACA,CAAC,EAAE,CAAC,QAAQ,CAAC,KAAK,CAAC,QAAQ;AAC3B,CAAC,MAAM,GAAG,MAAM,CAAC,GAAG,GAAG,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;AAC3C,EAAE,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,EAAE;AAC3B,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,GAAG;AACrB,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,EAAE;AACzC;AACA,EAAE,EAAE,CAAC,EAAE,IAAI,CAAC,EAAE,GAAG,OAAO,GAAG,CAAC,CAAC;AAC7B,GAAG,YAAY,GAAG;AAClB,GAAG,CAAC,KAAK,CAAC,IAAI,EAAE,IAAI,GAAG;AACvB,EAAE,CAAC;AACH,CAAC,GAAG;AACJ;AACA,CAAC,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM;AACpB,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC,QAAQ,CAAC,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC;AAC3D,EAAE,EAAE,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM;AAChC,EAAE,MAAM,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,WAAW,GAAG,cAAc,EAAE;AAC1D,GAAG,UAAU,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC;AACzB,EAAE,GAAG;AACL;AACA,EAAE,MAAM,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,SAAS,GAAG,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;AAC5D,GAAG,oBAAoB,CAAC,KAAK,EAAE;AAC/B,EAAE,GAAG;AACL;AACA,EAAE,MAAM,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,GAAG,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;AACzD,GAAG,qBAAqB,CAAC,KAAK,EAAE;AAChC,EAAE,GAAG;AACL;AACA,EAAE,MAAM,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,eAAe,GAAG,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;AAClE,GAAG,qBAAqB,CAAC,KAAK,EAAE;AAChC,EAAE,GAAG;AACL,CAAC,GAAG;AACJ;AACA,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC;AAC9D,EAAE,MAAM,GAAG,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,GAAG,GAAG,IAAI,GAAG;AAC7D,EAAE,MAAM,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,GAAG,UAAU,EAAE,QAAQ,GAAG;AAC3H,CAAC,CAAC,CAAC,EAAE;AACL;AACA,CAAC,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,MAAM;AACxB,CAAC,MAAM,EAAE,MAAM,CAAC,IAAI,EAAE,SAAS,KAAK,KAAK,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;AACvD,EAAE,GAAG,CAAC,aAAa,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,EAAE,GAAG,GAAG;AACzC,EAAE,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC;AAChB,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC,kBAAkB,EAAE;AACjC,GAAG,SAAS,CAAC,CAAC,CAAC,CAAC,gBAAgB,EAAE;AAClC;AACA,EAAE,EAAE,CAAC,CAAC,aAAa,CAAC,EAAE,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,CAAC;AAC3C,GAAG,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,UAAU,CAAC,aAAa,GAAG,IAAI,EAAE;AAC1D,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC;AACV,GAAG,EAAE,CAAC,CAAC,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,GAAG,QAAQ,EAAE,KAAK,GAAG,IAAI,GAAG,QAAQ,CAAC,OAAO,CAAC,KAAK,GAAG,IAAI,KAAK,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,SAAS,CAAC,QAAQ;AAClI,IAAI,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC;AACjB,GAAG,CAAC;AACJ,EAAE,CAAC;AACH;AACA,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC;AACd,GAAG,EAAE,CAAC,CAAC,aAAa,CAAC,EAAE,CAAC,MAAM,CAAC,cAAc,CAAC,CAAC,CAAC;AAChD,IAAI,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,cAAc,CAAC,aAAa,EAAE;AACnD,GAAG,CAAC;AACJ;AACA,GAAG,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,OAAO,GAAG;AACvC,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC;AACV,GAAG,EAAE,CAAC,CAAC,aAAa,CAAC,EAAE,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC;AAC3C,IAAI,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,SAAS,CAAC,aAAa,EAAE;AAChD,GAAG,CAAC;AACJ;AACA,GAAG,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,SAAS,GAAG;AAChC,EAAE,CAAC;AACH;AACA,EAAE,MAAM,CAAC,KAAK,CAAC;AACf,CAAC,GAAG;AACJ;AACA,CAAC,GAAG;AACJ,EAAE,CAAC,CAAC,UAAU,CAAC,SAAS;AACxB,EAAE,EAAE;AACJ,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC,CAAC;AACnC,EAAE,MAAM,CAAC,IAAI,CAAC;AACd,CAAC,EAAE;AACH;AACA,CAAC,MAAM,CAAC,eAAe,CAAC,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC;AAC1C,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,GAAG,QAAQ,GAAG,IAAI,GAAG,OAAO,CAAC,QAAQ,IAAI,GAAG,GAAG,CAAC,CAAC;AAC1F,GAAG,MAAM,CAAC,IAAI,CAAC;AACf,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC;AACV,GAAG,MAAM,CAAC,KAAK,CAAC;AAChB,EAAE,CAAC;AACH,CAAC,EAAE;AACH;AACA,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC;AACtC,EAAE,EAAE,CAAC,CAAC,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,GAAG,QAAQ,EAAE,KAAK,GAAG,IAAI,EAAE,QAAQ,GAAG,GAAG,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;AACrF,GAAG,MAAM,CAAC,IAAI,CAAC;AACf,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC;AACV,GAAG,MAAM,CAAC,KAAK,CAAC;AAChB,EAAE,CAAC;AACH,CAAC,EAAE;AACH;AACA,IAAI,MAAM,CAAC,gBAAgB,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC,CAAC;AAC1C,QAAQ,EAAE,CAAC,CAAC,MAAM,GAAG,iBAAiB,GAAG,GAAG,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;AACxD,YAAY,MAAM,CAAC,IAAI,CAAC;AACxB,QAAQ,CAAC,CAAC,IAAI,CAAC,CAAC;AAChB,YAAY,MAAM,CAAC,KAAK,CAAC;AACzB,QAAQ,CAAC;AACT,IAAI,EAAE;AACN,GAAG","file":"bulk-delete.js","sourcesContent":["/*global BulkWP, postboxes, pagenow*/\njQuery(document).ready(function () {\n\t/**\n\t * Enable select2\n\t */\n\tjQuery( '.select2' ).select2();\n\n\t/**\n\t * Enable Postbox handling\n\t */\n\tpostboxes.add_postbox_toggles(pagenow);\n\n\t/**\n\t * Toggle the date restrict fields\n\t */\n\tfunction toggle_date_restrict(el) {\n\t\tif (jQuery(\"#smbd\" + el + \"_restrict\").is(\":checked\")) {\n\t\t\tjQuery(\"#smbd\" + el + \"_op\").removeAttr('disabled');\n\t\t\tjQuery(\"#smbd\" + el + \"_days\").removeAttr('disabled');\n\t\t} else {\n\t\t\tjQuery(\"#smbd\" + el + \"_op\").attr('disabled', 'true');\n\t\t\tjQuery(\"#smbd\" + el + \"_days\").attr('disabled', 'true');\n\t\t}\n\t}\n\n\t/**\n\t * Toggle limit restrict fields\n\t */\n\tfunction toggle_limit_restrict(el) {\n\t\tif (jQuery(\"#smbd\" + el + \"_limit\").is(\":checked\")) {\n\t\t\tjQuery(\"#smbd\" + el + \"_limit_to\").removeAttr('disabled');\n\t\t} else {\n\t\t\tjQuery(\"#smbd\" + el + \"_limit_to\").attr('disabled', 'true');\n\t\t}\n\t}\n\n\t/**\n\t * Toggle user login restrict fields\n\t */\n\tfunction toggle_login_restrict(el) {\n\t\tif (jQuery(\"#smbd\" + el + \"_login_restrict\").is(\":checked\")) {\n\t\t\tjQuery(\"#smbd\" + el + \"_login_days\").removeAttr('disabled');\n\t\t} else {\n\t\t\tjQuery(\"#smbd\" + el + \"_login_days\").attr('disabled', 'true');\n\t\t}\n\t}\n\n\t// hide all terms\n\tfunction hideAllTerms() {\n\t\tjQuery('table.terms').hide();\n\t\tjQuery('input.terms').attr('checked', false);\n\t}\n\t// call it for the first time\n\thideAllTerms();\n\n\t// taxonomy click handling\n\tjQuery('.custom-tax').change(function () {\n\t\tvar $this = jQuery(this),\n\t\t$tax = $this.val(),\n\t\t$terms = jQuery('table.terms_' + $tax);\n\n\t\tif ($this.is(':checked')) {\n\t\t\thideAllTerms();\n\t\t\t$terms.show('slow');\n\t\t}\n\t});\n\n\t// date time picker\n\tjQuery.each(BulkWP.dt_iterators, function (index, value) {\n\t\t// invoke the date time picker\n\t\tjQuery('#smbd' + value + '_cron_start').datetimepicker({\n\t\t\ttimeFormat: 'HH:mm:ss'\n\t\t});\n\n\t\tjQuery('#smbd' + value + '_restrict').change(function () {\n\t\t\ttoggle_date_restrict(value);\n\t\t});\n\n\t\tjQuery('#smbd' + value + '_limit').change(function () {\n\t\t\ttoggle_limit_restrict(value);\n\t\t});\n\n\t\tjQuery('#smbd' + value + '_login_restrict').change(function () {\n\t\t\ttoggle_login_restrict(value);\n\t\t});\n\t});\n\n\tjQuery.each( BulkWP.pro_iterators, function ( index, value) {\n\t\tjQuery('.bd-' + value.replace( '_', '-' ) + '-pro').hide();\n\t\tjQuery('#smbd_' + value + '_cron_freq, #smbd_' + value + '_cron_start, #smbd_' + value + '_cron').removeAttr('disabled');\n\t} );\n\n\t// Validate user action\n\tjQuery('button[name=\"bd_action\"]').click(function () {\n\t\tvar currentButton = jQuery(this).val(),\n\t\tvalid = false,\n\t\tmsg_key = \"deletePostsWarning\",\n\t\t\terror_key = \"selectPostOption\";\n\n\t\tif (currentButton in BulkWP.validators) {\n\t\t\tvalid = BulkWP[BulkWP.validators[currentButton]](this);\n\t\t} else {\n\t\t\tif (jQuery(this).parent().prev().children('table').find(\":checkbox:checked[value!='true']\").size() > 0) { // monstrous selector\n\t\t\t\tvalid = true;\n\t\t\t}\n\t\t}\n\n\t\tif (valid) {\n\t\t\tif (currentButton in BulkWP.pre_action_msg) {\n\t\t\t\tmsg_key = BulkWP.pre_action_msg[currentButton];\n\t\t\t}\n\n\t\t\treturn confirm(BulkWP.msg[msg_key]);\n\t\t} else {\n\t\t\tif (currentButton in BulkWP.error_msg) {\n\t\t\t\terror_key = BulkWP.error_msg[currentButton];\n\t\t\t}\n\n\t\t\talert(BulkWP.msg[error_key]);\n\t\t}\n\n\t\treturn false;\n\t});\n\n\t/**\n\t * Validation functions\n\t */\n\tBulkWP.noValidation = function() {\n\t\treturn true;\n\t};\n\n\tBulkWP.validateSelect2 = function(that) {\n\t\tif (null !== jQuery(that).parent().prev().children().find(\".select2[multiple]\").val()) {\n\t\t\treturn true;\n\t\t} else {\n\t\t\treturn false;\n\t\t}\n\t};\n\n\tBulkWP.validateUrl = function(that) {\n\t\tif (jQuery(that).parent().prev().children('table').find(\"textarea\").val() !== '') {\n\t\t\treturn true;\n\t\t} else {\n\t\t\treturn false;\n\t\t}\n\t};\n\n BulkWP.validateUserMeta = function() {\n if (jQuery('#smbd_u_meta_value').val() !== '') {\n return true;\n } else {\n return false;\n }\n };\n});\n"]}
assets/js/bulk-delete.min.js ADDED
@@ -0,0 +1,4 @@
 
 
 
 
1
+ /*! Bulk Delete - v5.5.0
2
+ * http://bulkwp.com
3
+ * Copyright (c) 2015; * Licensed GPLv2+ */
4
+ jQuery(document).ready(function(){function a(a){jQuery("#smbd"+a+"_restrict").is(":checked")?(jQuery("#smbd"+a+"_op").removeAttr("disabled"),jQuery("#smbd"+a+"_days").removeAttr("disabled")):(jQuery("#smbd"+a+"_op").attr("disabled","true"),jQuery("#smbd"+a+"_days").attr("disabled","true"))}function b(a){jQuery("#smbd"+a+"_limit").is(":checked")?jQuery("#smbd"+a+"_limit_to").removeAttr("disabled"):jQuery("#smbd"+a+"_limit_to").attr("disabled","true")}function c(a){jQuery("#smbd"+a+"_login_restrict").is(":checked")?jQuery("#smbd"+a+"_login_days").removeAttr("disabled"):jQuery("#smbd"+a+"_login_days").attr("disabled","true")}function d(){jQuery("table.terms").hide(),jQuery("input.terms").attr("checked",!1)}jQuery(".select2").select2(),postboxes.add_postbox_toggles(pagenow),d(),jQuery(".custom-tax").change(function(){var a=jQuery(this),b=a.val(),c=jQuery("table.terms_"+b);a.is(":checked")&&(d(),c.show("slow"))}),jQuery.each(BulkWP.dt_iterators,function(d,e){jQuery("#smbd"+e+"_cron_start").datetimepicker({timeFormat:"HH:mm:ss"}),jQuery("#smbd"+e+"_restrict").change(function(){a(e)}),jQuery("#smbd"+e+"_limit").change(function(){b(e)}),jQuery("#smbd"+e+"_login_restrict").change(function(){c(e)})}),jQuery.each(BulkWP.pro_iterators,function(a,b){jQuery(".bd-"+b.replace("_","-")+"-pro").hide(),jQuery("#smbd_"+b+"_cron_freq, #smbd_"+b+"_cron_start, #smbd_"+b+"_cron").removeAttr("disabled")}),jQuery('button[name="bd_action"]').click(function(){var a=jQuery(this).val(),b=!1,c="deletePostsWarning",d="selectPostOption";return a in BulkWP.validators?b=BulkWP[BulkWP.validators[a]](this):jQuery(this).parent().prev().children("table").find(":checkbox:checked[value!='true']").size()>0&&(b=!0),b?(a in BulkWP.pre_action_msg&&(c=BulkWP.pre_action_msg[a]),confirm(BulkWP.msg[c])):(a in BulkWP.error_msg&&(d=BulkWP.error_msg[a]),alert(BulkWP.msg[d]),!1)}),BulkWP.noValidation=function(){return!0},BulkWP.validateSelect2=function(a){return null!==jQuery(a).parent().prev().children().find(".select2[multiple]").val()?!0:!1},BulkWP.validateUrl=function(a){return""!==jQuery(a).parent().prev().children("table").find("textarea").val()?!0:!1},BulkWP.validateUserMeta=function(){return""!==jQuery("#smbd_u_meta_value").val()?!0:!1}});
assets/js/jquery-ui-timepicker-addon.min.js ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
1
+ /*! jQuery Timepicker Addon - v1.5.4 - 2015-05-11
2
+ * http://trentrichardson.com/examples/timepicker
3
+ * Copyright (c) 2015 Trent Richardson; Licensed MIT */
4
+ !function(a){"function"==typeof define&&define.amd?define(["jquery","jquery.ui"],a):a(jQuery)}(function($){if($.ui.timepicker=$.ui.timepicker||{},!$.ui.timepicker.version){$.extend($.ui,{timepicker:{version:"1.5.4"}});var Timepicker=function(){this.regional=[],this.regional[""]={currentText:"Now",closeText:"Done",amNames:["AM","A"],pmNames:["PM","P"],timeFormat:"HH:mm",timeSuffix:"",timeOnlyTitle:"Choose Time",timeText:"Time",hourText:"Hour",minuteText:"Minute",secondText:"Second",millisecText:"Millisecond",microsecText:"Microsecond",timezoneText:"Time Zone",isRTL:!1},this._defaults={showButtonPanel:!0,timeOnly:!1,timeOnlyShowDate:!1,showHour:null,showMinute:null,showSecond:null,showMillisec:null,showMicrosec:null,showTimezone:null,showTime:!0,stepHour:1,stepMinute:1,stepSecond:1,stepMillisec:1,stepMicrosec:1,hour:0,minute:0,second:0,millisec:0,microsec:0,timezone:null,hourMin:0,minuteMin:0,secondMin:0,millisecMin:0,microsecMin:0,hourMax:23,minuteMax:59,secondMax:59,millisecMax:999,microsecMax:999,minDateTime:null,maxDateTime:null,maxTime:null,minTime:null,onSelect:null,hourGrid:0,minuteGrid:0,secondGrid:0,millisecGrid:0,microsecGrid:0,alwaysSetTime:!0,separator:" ",altFieldTimeOnly:!0,altTimeFormat:null,altSeparator:null,altTimeSuffix:null,altRedirectFocus:!0,pickerTimeFormat:null,pickerTimeSuffix:null,showTimepicker:!0,timezoneList:null,addSliderAccess:!1,sliderAccessArgs:null,controlType:"slider",oneLine:!1,defaultValue:null,parse:"strict",afterInject:null},$.extend(this._defaults,this.regional[""])};$.extend(Timepicker.prototype,{$input:null,$altInput:null,$timeObj:null,inst:null,hour_slider:null,minute_slider:null,second_slider:null,millisec_slider:null,microsec_slider:null,timezone_select:null,maxTime:null,minTime:null,hour:0,minute:0,second:0,millisec:0,microsec:0,timezone:null,hourMinOriginal:null,minuteMinOriginal:null,secondMinOriginal:null,millisecMinOriginal:null,microsecMinOriginal:null,hourMaxOriginal:null,minuteMaxOriginal:null,secondMaxOriginal:null,millisecMaxOriginal:null,microsecMaxOriginal:null,ampm:"",formattedDate:"",formattedTime:"",formattedDateTime:"",timezoneList:null,units:["hour","minute","second","millisec","microsec"],support:{},control:null,setDefaults:function(a){return extendRemove(this._defaults,a||{}),this},_newInst:function($input,opts){var tp_inst=new Timepicker,inlineSettings={},fns={},overrides,i;for(var attrName in this._defaults)if(this._defaults.hasOwnProperty(attrName)){var attrValue=$input.attr("time:"+attrName);if(attrValue)try{inlineSettings[attrName]=eval(attrValue)}catch(err){inlineSettings[attrName]=attrValue}}overrides={beforeShow:function(a,b){return $.isFunction(tp_inst._defaults.evnts.beforeShow)?tp_inst._defaults.evnts.beforeShow.call($input[0],a,b,tp_inst):void 0},onChangeMonthYear:function(a,b,c){$.isFunction(tp_inst._defaults.evnts.onChangeMonthYear)&&tp_inst._defaults.evnts.onChangeMonthYear.call($input[0],a,b,c,tp_inst)},onClose:function(a,b){tp_inst.timeDefined===!0&&""!==$input.val()&&tp_inst._updateDateTime(b),$.isFunction(tp_inst._defaults.evnts.onClose)&&tp_inst._defaults.evnts.onClose.call($input[0],a,b,tp_inst)}};for(i in overrides)overrides.hasOwnProperty(i)&&(fns[i]=opts[i]||this._defaults[i]||null);tp_inst._defaults=$.extend({},this._defaults,inlineSettings,opts,overrides,{evnts:fns,timepicker:tp_inst}),tp_inst.amNames=$.map(tp_inst._defaults.amNames,function(a){return a.toUpperCase()}),tp_inst.pmNames=$.map(tp_inst._defaults.pmNames,function(a){return a.toUpperCase()}),tp_inst.support=detectSupport(tp_inst._defaults.timeFormat+(tp_inst._defaults.pickerTimeFormat?tp_inst._defaults.pickerTimeFormat:"")+(tp_inst._defaults.altTimeFormat?tp_inst._defaults.altTimeFormat:"")),"string"==typeof tp_inst._defaults.controlType?("slider"===tp_inst._defaults.controlType&&"undefined"==typeof $.ui.slider&&(tp_inst._defaults.controlType="select"),tp_inst.control=tp_inst._controls[tp_inst._defaults.controlType]):tp_inst.control=tp_inst._defaults.controlType;var timezoneList=[-720,-660,-600,-570,-540,-480,-420,-360,-300,-270,-240,-210,-180,-120,-60,0,60,120,180,210,240,270,300,330,345,360,390,420,480,525,540,570,600,630,660,690,720,765,780,840];null!==tp_inst._defaults.timezoneList&&(timezoneList=tp_inst._defaults.timezoneList);var tzl=timezoneList.length,tzi=0,tzv=null;if(tzl>0&&"object"!=typeof timezoneList[0])for(;tzl>tzi;tzi++)tzv=timezoneList[tzi],timezoneList[tzi]={value:tzv,label:$.timepicker.timezoneOffsetString(tzv,tp_inst.support.iso8601)};return tp_inst._defaults.timezoneList=timezoneList,tp_inst.timezone=null!==tp_inst._defaults.timezone?$.timepicker.timezoneOffsetNumber(tp_inst._defaults.timezone):-1*(new Date).getTimezoneOffset(),tp_inst.hour=tp_inst._defaults.hour<tp_inst._defaults.hourMin?tp_inst._defaults.hourMin:tp_inst._defaults.hour>tp_inst._defaults.hourMax?tp_inst._defaults.hourMax:tp_inst._defaults.hour,tp_inst.minute=tp_inst._defaults.minute<tp_inst._defaults.minuteMin?tp_inst._defaults.minuteMin:tp_inst._defaults.minute>tp_inst._defaults.minuteMax?tp_inst._defaults.minuteMax:tp_inst._defaults.minute,tp_inst.second=tp_inst._defaults.second<tp_inst._defaults.secondMin?tp_inst._defaults.secondMin:tp_inst._defaults.second>tp_inst._defaults.secondMax?tp_inst._defaults.secondMax:tp_inst._defaults.second,tp_inst.millisec=tp_inst._defaults.millisec<tp_inst._defaults.millisecMin?tp_inst._defaults.millisecMin:tp_inst._defaults.millisec>tp_inst._defaults.millisecMax?tp_inst._defaults.millisecMax:tp_inst._defaults.millisec,tp_inst.microsec=tp_inst._defaults.microsec<tp_inst._defaults.microsecMin?tp_inst._defaults.microsecMin:tp_inst._defaults.microsec>tp_inst._defaults.microsecMax?tp_inst._defaults.microsecMax:tp_inst._defaults.microsec,tp_inst.ampm="",tp_inst.$input=$input,tp_inst._defaults.altField&&(tp_inst.$altInput=$(tp_inst._defaults.altField),tp_inst._defaults.altRedirectFocus===!0&&tp_inst.$altInput.css({cursor:"pointer"}).focus(function(){$input.trigger("focus")})),(0===tp_inst._defaults.minDate||0===tp_inst._defaults.minDateTime)&&(tp_inst._defaults.minDate=new Date),(0===tp_inst._defaults.maxDate||0===tp_inst._defaults.maxDateTime)&&(tp_inst._defaults.maxDate=new Date),void 0!==tp_inst._defaults.minDate&&tp_inst._defaults.minDate instanceof Date&&(tp_inst._defaults.minDateTime=new Date(tp_inst._defaults.minDate.getTime())),void 0!==tp_inst._defaults.minDateTime&&tp_inst._defaults.minDateTime instanceof Date&&(tp_inst._defaults.minDate=new Date(tp_inst._defaults.minDateTime.getTime())),void 0!==tp_inst._defaults.maxDate&&tp_inst._defaults.maxDate instanceof Date&&(tp_inst._defaults.maxDateTime=new Date(tp_inst._defaults.maxDate.getTime())),void 0!==tp_inst._defaults.maxDateTime&&tp_inst._defaults.maxDateTime instanceof Date&&(tp_inst._defaults.maxDate=new Date(tp_inst._defaults.maxDateTime.getTime())),tp_inst.$input.bind("focus",function(){tp_inst._onFocus()}),tp_inst},_addTimePicker:function(a){var b=$.trim(this.$altInput&&this._defaults.altFieldTimeOnly?this.$input.val()+" "+this.$altInput.val():this.$input.val());this.timeDefined=this._parseTime(b),this._limitMinMaxDateTime(a,!1),this._injectTimePicker(),this._afterInject()},_parseTime:function(a,b){if(this.inst||(this.inst=$.datepicker._getInst(this.$input[0])),b||!this._defaults.timeOnly){var c=$.datepicker._get(this.inst,"dateFormat");try{var d=parseDateTimeInternal(c,this._defaults.timeFormat,a,$.datepicker._getFormatConfig(this.inst),this._defaults);if(!d.timeObj)return!1;$.extend(this,d.timeObj)}catch(e){return $.timepicker.log("Error parsing the date/time string: "+e+"\ndate/time string = "+a+"\ntimeFormat = "+this._defaults.timeFormat+"\ndateFormat = "+c),!1}return!0}var f=$.datepicker.parseTime(this._defaults.timeFormat,a,this._defaults);return f?($.extend(this,f),!0):!1},_afterInject:function(){var a=this.inst.settings;$.isFunction(a.afterInject)&&a.afterInject.call(this)},_injectTimePicker:function(){var a=this.inst.dpDiv,b=this.inst.settings,c=this,d="",e="",f=null,g={},h={},i=null,j=0,k=0;if(0===a.find("div.ui-timepicker-div").length&&b.showTimepicker){var l=" ui_tpicker_unit_hide",m='<div class="ui-timepicker-div'+(b.isRTL?" ui-timepicker-rtl":"")+(b.oneLine&&"select"===b.controlType?" ui-timepicker-oneLine":"")+'"><dl><dt class="ui_tpicker_time_label'+(b.showTime?"":l)+'">'+b.timeText+'</dt><dd class="ui_tpicker_time '+(b.showTime?"":l)+'"></dd>';for(j=0,k=this.units.length;k>j;j++){if(d=this.units[j],e=d.substr(0,1).toUpperCase()+d.substr(1),f=null!==b["show"+e]?b["show"+e]:this.support[d],g[d]=parseInt(b[d+"Max"]-(b[d+"Max"]-b[d+"Min"])%b["step"+e],10),h[d]=0,m+='<dt class="ui_tpicker_'+d+"_label"+(f?"":l)+'">'+b[d+"Text"]+'</dt><dd class="ui_tpicker_'+d+(f?"":l)+'"><div class="ui_tpicker_'+d+"_slider"+(f?"":l)+'"></div>',f&&b[d+"Grid"]>0){if(m+='<div style="padding-left: 1px"><table class="ui-tpicker-grid-label"><tr>',"hour"===d)for(var n=b[d+"Min"];n<=g[d];n+=parseInt(b[d+"Grid"],10)){h[d]++;var o=$.datepicker.formatTime(this.support.ampm?"hht":"HH",{hour:n},b);m+='<td data-for="'+d+'">'+o+"</td>"}else for(var p=b[d+"Min"];p<=g[d];p+=parseInt(b[d+"Grid"],10))h[d]++,m+='<td data-for="'+d+'">'+(10>p?"0":"")+p+"</td>";m+="</tr></table></div>"}m+="</dd>"}var q=null!==b.showTimezone?b.showTimezone:this.support.timezone;m+='<dt class="ui_tpicker_timezone_label'+(q?"":l)+'">'+b.timezoneText+"</dt>",m+='<dd class="ui_tpicker_timezone'+(q?"":l)+'"></dd>',m+="</dl></div>";var r=$(m);for(b.timeOnly===!0&&(r.prepend('<div class="ui-widget-header ui-helper-clearfix ui-corner-all"><div class="ui-datepicker-title">'+b.timeOnlyTitle+"</div></div>"),a.find(".ui-datepicker-header, .ui-datepicker-calendar").hide()),j=0,k=c.units.length;k>j;j++)d=c.units[j],e=d.substr(0,1).toUpperCase()+d.substr(1),f=null!==b["show"+e]?b["show"+e]:this.support[d],c[d+"_slider"]=c.control.create(c,r.find(".ui_tpicker_"+d+"_slider"),d,c[d],b[d+"Min"],g[d],b["step"+e]),f&&b[d+"Grid"]>0&&(i=100*h[d]*b[d+"Grid"]/(g[d]-b[d+"Min"]),r.find(".ui_tpicker_"+d+" table").css({width:i+"%",marginLeft:b.isRTL?"0":i/(-2*h[d])+"%",marginRight:b.isRTL?i/(-2*h[d])+"%":"0",borderCollapse:"collapse"}).find("td").click(function(a){var b=$(this),e=b.html(),f=parseInt(e.replace(/[^0-9]/g),10),g=e.replace(/[^apm]/gi),h=b.data("for");"hour"===h&&(-1!==g.indexOf("p")&&12>f?f+=12:-1!==g.indexOf("a")&&12===f&&(f=0)),c.control.value(c,c[h+"_slider"],d,f),c._onTimeChange(),c._onSelectHandler()}).css({cursor:"pointer",width:100/h[d]+"%",textAlign:"center",overflow:"hidden"}));if(this.timezone_select=r.find(".ui_tpicker_timezone").append("<select></select>").find("select"),$.fn.append.apply(this.timezone_select,$.map(b.timezoneList,function(a,b){return $("<option />").val("object"==typeof a?a.value:a).text("object"==typeof a?a.label:a)})),"undefined"!=typeof this.timezone&&null!==this.timezone&&""!==this.timezone){var s=-1*new Date(this.inst.selectedYear,this.inst.selectedMonth,this.inst.selectedDay,12).getTimezoneOffset();s===this.timezone?selectLocalTimezone(c):this.timezone_select.val(this.timezone)}else"undefined"!=typeof this.hour&&null!==this.hour&&""!==this.hour?this.timezone_select.val(b.timezone):selectLocalTimezone(c);this.timezone_select.change(function(){c._onTimeChange(),c._onSelectHandler(),c._afterInject()});var t=a.find(".ui-datepicker-buttonpane");if(t.length?t.before(r):a.append(r),this.$timeObj=r.find(".ui_tpicker_time"),null!==this.inst){var u=this.timeDefined;this._onTimeChange(),this.timeDefined=u}if(this._defaults.addSliderAccess){var v=this._defaults.sliderAccessArgs,w=this._defaults.isRTL;v.isRTL=w,setTimeout(function(){if(0===r.find(".ui-slider-access").length){r.find(".ui-slider:visible").sliderAccess(v);var a=r.find(".ui-slider-access:eq(0)").outerWidth(!0);a&&r.find("table:visible").each(function(){var b=$(this),c=b.outerWidth(),d=b.css(w?"marginRight":"marginLeft").toString().replace("%",""),e=c-a,f=d*e/c+"%",g={width:e,marginRight:0,marginLeft:0};g[w?"marginRight":"marginLeft"]=f,b.css(g)})}},10)}c._limitMinMaxDateTime(this.inst,!0)}},_limitMinMaxDateTime:function(a,b){var c=this._defaults,d=new Date(a.selectedYear,a.selectedMonth,a.selectedDay);if(this._defaults.showTimepicker){if(null!==$.datepicker._get(a,"minDateTime")&&void 0!==$.datepicker._get(a,"minDateTime")&&d){var e=$.datepicker._get(a,"minDateTime"),f=new Date(e.getFullYear(),e.getMonth(),e.getDate(),0,0,0,0);(null===this.hourMinOriginal||null===this.minuteMinOriginal||null===this.secondMinOriginal||null===this.millisecMinOriginal||null===this.microsecMinOriginal)&&(this.hourMinOriginal=c.hourMin,this.minuteMinOriginal=c.minuteMin,this.secondMinOriginal=c.secondMin,this.millisecMinOriginal=c.millisecMin,this.microsecMinOriginal=c.microsecMin),a.settings.timeOnly||f.getTime()===d.getTime()?(this._defaults.hourMin=e.getHours(),this.hour<=this._defaults.hourMin?(this.hour=this._defaults.hourMin,this._defaults.minuteMin=e.getMinutes(),this.minute<=this._defaults.minuteMin?(this.minute=this._defaults.minuteMin,this._defaults.secondMin=e.getSeconds(),this.second<=this._defaults.secondMin?(this.second=this._defaults.secondMin,this._defaults.millisecMin=e.getMilliseconds(),this.millisec<=this._defaults.millisecMin?(this.millisec=this._defaults.millisecMin,this._defaults.microsecMin=e.getMicroseconds()):(this.microsec<this._defaults.microsecMin&&(this.microsec=this._defaults.microsecMin),this._defaults.microsecMin=this.microsecMinOriginal)):(this._defaults.millisecMin=this.millisecMinOriginal,this._defaults.microsecMin=this.microsecMinOriginal)):(this._defaults.secondMin=this.secondMinOriginal,this._defaults.millisecMin=this.millisecMinOriginal,this._defaults.microsecMin=this.microsecMinOriginal)):(this._defaults.minuteMin=this.minuteMinOriginal,this._defaults.secondMin=this.secondMinOriginal,this._defaults.millisecMin=this.millisecMinOriginal,this._defaults.microsecMin=this.microsecMinOriginal)):(this._defaults.hourMin=this.hourMinOriginal,this._defaults.minuteMin=this.minuteMinOriginal,this._defaults.secondMin=this.secondMinOriginal,this._defaults.millisecMin=this.millisecMinOriginal,this._defaults.microsecMin=this.microsecMinOriginal)}if(null!==$.datepicker._get(a,"maxDateTime")&&void 0!==$.datepicker._get(a,"maxDateTime")&&d){var g=$.datepicker._get(a,"maxDateTime"),h=new Date(g.getFullYear(),g.getMonth(),g.getDate(),0,0,0,0);(null===this.hourMaxOriginal||null===this.minuteMaxOriginal||null===this.secondMaxOriginal||null===this.millisecMaxOriginal)&&(this.hourMaxOriginal=c.hourMax,this.minuteMaxOriginal=c.minuteMax,this.secondMaxOriginal=c.secondMax,this.millisecMaxOriginal=c.millisecMax,this.microsecMaxOriginal=c.microsecMax),a.settings.timeOnly||h.getTime()===d.getTime()?(this._defaults.hourMax=g.getHours(),this.hour>=this._defaults.hourMax?(this.hour=this._defaults.hourMax,this._defaults.minuteMax=g.getMinutes(),this.minute>=this._defaults.minuteMax?(this.minute=this._defaults.minuteMax,this._defaults.secondMax=g.getSeconds(),this.second>=this._defaults.secondMax?(this.second=this._defaults.secondMax,this._defaults.millisecMax=g.getMilliseconds(),this.millisec>=this._defaults.millisecMax?(this.millisec=this._defaults.millisecMax,this._defaults.microsecMax=g.getMicroseconds()):(this.microsec>this._defaults.microsecMax&&(this.microsec=this._defaults.microsecMax),this._defaults.microsecMax=this.microsecMaxOriginal)):(this._defaults.millisecMax=this.millisecMaxOriginal,this._defaults.microsecMax=this.microsecMaxOriginal)):(this._defaults.secondMax=this.secondMaxOriginal,this._defaults.millisecMax=this.millisecMaxOriginal,this._defaults.microsecMax=this.microsecMaxOriginal)):(this._defaults.minuteMax=this.minuteMaxOriginal,this._defaults.secondMax=this.secondMaxOriginal,this._defaults.millisecMax=this.millisecMaxOriginal,this._defaults.microsecMax=this.microsecMaxOriginal)):(this._defaults.hourMax=this.hourMaxOriginal,this._defaults.minuteMax=this.minuteMaxOriginal,this._defaults.secondMax=this.secondMaxOriginal,this._defaults.millisecMax=this.millisecMaxOriginal,this._defaults.microsecMax=this.microsecMaxOriginal)}if(null!==a.settings.minTime){var i=new Date("01/01/1970 "+a.settings.minTime);this.hour<i.getHours()?(this.hour=this._defaults.hourMin=i.getHours(),this.minute=this._defaults.minuteMin=i.getMinutes()):this.hour===i.getHours()&&this.minute<i.getMinutes()?this.minute=this._defaults.minuteMin=i.getMinutes():this._defaults.hourMin<i.getHours()?(this._defaults.hourMin=i.getHours(),this._defaults.minuteMin=i.getMinutes()):this._defaults.hourMin===i.getHours()===this.hour&&this._defaults.minuteMin<i.getMinutes()?this._defaults.minuteMin=i.getMinutes():this._defaults.minuteMin=0}if(null!==a.settings.maxTime){var j=new Date("01/01/1970 "+a.settings.maxTime);this.hour>j.getHours()?(this.hour=this._defaults.hourMax=j.getHours(),this.minute=this._defaults.minuteMax=j.getMinutes()):this.hour===j.getHours()&&this.minute>j.getMinutes()?this.minute=this._defaults.minuteMax=j.getMinutes():this._defaults.hourMax>j.getHours()?(this._defaults.hourMax=j.getHours(),this._defaults.minuteMax=j.getMinutes()):this._defaults.hourMax===j.getHours()===this.hour&&this._defaults.minuteMax>j.getMinutes()?this._defaults.minuteMax=j.getMinutes():this._defaults.minuteMax=59}if(void 0!==b&&b===!0){var k=parseInt(this._defaults.hourMax-(this._defaults.hourMax-this._defaults.hourMin)%this._defaults.stepHour,10),l=parseInt(this._defaults.minuteMax-(this._defaults.minuteMax-this._defaults.minuteMin)%this._defaults.stepMinute,10),m=parseInt(this._defaults.secondMax-(this._defaults.secondMax-this._defaults.secondMin)%this._defaults.stepSecond,10),n=parseInt(this._defaults.millisecMax-(this._defaults.millisecMax-this._defaults.millisecMin)%this._defaults.stepMillisec,10),o=parseInt(this._defaults.microsecMax-(this._defaults.microsecMax-this._defaults.microsecMin)%this._defaults.stepMicrosec,10);this.hour_slider&&(this.control.options(this,this.hour_slider,"hour",{min:this._defaults.hourMin,max:k,step:this._defaults.stepHour}),this.control.value(this,this.hour_slider,"hour",this.hour-this.hour%this._defaults.stepHour)),this.minute_slider&&(this.control.options(this,this.minute_slider,"minute",{min:this._defaults.minuteMin,max:l,step:this._defaults.stepMinute}),this.control.value(this,this.minute_slider,"minute",this.minute-this.minute%this._defaults.stepMinute)),this.second_slider&&(this.control.options(this,this.second_slider,"second",{min:this._defaults.secondMin,max:m,step:this._defaults.stepSecond}),this.control.value(this,this.second_slider,"second",this.second-this.second%this._defaults.stepSecond)),this.millisec_slider&&(this.control.options(this,this.millisec_slider,"millisec",{min:this._defaults.millisecMin,max:n,step:this._defaults.stepMillisec}),this.control.value(this,this.millisec_slider,"millisec",this.millisec-this.millisec%this._defaults.stepMillisec)),this.microsec_slider&&(this.control.options(this,this.microsec_slider,"microsec",{min:this._defaults.microsecMin,max:o,step:this._defaults.stepMicrosec}),this.control.value(this,this.microsec_slider,"microsec",this.microsec-this.microsec%this._defaults.stepMicrosec))}}},_onTimeChange:function(){if(this._defaults.showTimepicker){var a=this.hour_slider?this.control.value(this,this.hour_slider,"hour"):!1,b=this.minute_slider?this.control.value(this,this.minute_slider,"minute"):!1,c=this.second_slider?this.control.value(this,this.second_slider,"second"):!1,d=this.millisec_slider?this.control.value(this,this.millisec_slider,"millisec"):!1,e=this.microsec_slider?this.control.value(this,this.microsec_slider,"microsec"):!1,f=this.timezone_select?this.timezone_select.val():!1,g=this._defaults,h=g.pickerTimeFormat||g.timeFormat,i=g.pickerTimeSuffix||g.timeSuffix;"object"==typeof a&&(a=!1),"object"==typeof b&&(b=!1),"object"==typeof c&&(c=!1),"object"==typeof d&&(d=!1),"object"==typeof e&&(e=!1),"object"==typeof f&&(f=!1),a!==!1&&(a=parseInt(a,10)),b!==!1&&(b=parseInt(b,10)),c!==!1&&(c=parseInt(c,10)),d!==!1&&(d=parseInt(d,10)),e!==!1&&(e=parseInt(e,10)),f!==!1&&(f=f.toString());var j=g[12>a?"amNames":"pmNames"][0],k=a!==parseInt(this.hour,10)||b!==parseInt(this.minute,10)||c!==parseInt(this.second,10)||d!==parseInt(this.millisec,10)||e!==parseInt(this.microsec,10)||this.ampm.length>0&&12>a!=(-1!==$.inArray(this.ampm.toUpperCase(),this.amNames))||null!==this.timezone&&f!==this.timezone.toString();k&&(a!==!1&&(this.hour=a),b!==!1&&(this.minute=b),c!==!1&&(this.second=c),d!==!1&&(this.millisec=d),e!==!1&&(this.microsec=e),f!==!1&&(this.timezone=f),this.inst||(this.inst=$.datepicker._getInst(this.$input[0])),this._limitMinMaxDateTime(this.inst,!0)),this.support.ampm&&(this.ampm=j),this.formattedTime=$.datepicker.formatTime(g.timeFormat,this,g),this.$timeObj&&this.$timeObj.text(h===g.timeFormat?this.formattedTime+i:$.datepicker.formatTime(h,this,g)+i),this.timeDefined=!0,k&&this._updateDateTime()}},_onSelectHandler:function(){var a=this._defaults.onSelect||this.inst.settings.onSelect,b=this.$input?this.$input[0]:null;a&&b&&a.apply(b,[this.formattedDateTime,this])},_updateDateTime:function(a){a=this.inst||a;var b=a.currentYear>0?new Date(a.currentYear,a.currentMonth,a.currentDay):new Date(a.selectedYear,a.selectedMonth,a.selectedDay),c=$.datepicker._daylightSavingAdjust(b),d=$.datepicker._get(a,"dateFormat"),e=$.datepicker._getFormatConfig(a),f=null!==c&&this.timeDefined;this.formattedDate=$.datepicker.formatDate(d,null===c?new Date:c,e);var g=this.formattedDate;if(""===a.lastVal&&(a.currentYear=a.selectedYear,a.currentMonth=a.selectedMonth,a.currentDay=a.selectedDay),this._defaults.timeOnly===!0&&this._defaults.timeOnlyShowDate===!1?g=this.formattedTime:(this._defaults.timeOnly!==!0&&(this._defaults.alwaysSetTime||f)||this._defaults.timeOnly===!0&&this._defaults.timeOnlyShowDate===!0)&&(g+=this._defaults.separator+this.formattedTime+this._defaults.timeSuffix),this.formattedDateTime=g,this._defaults.showTimepicker)if(this.$altInput&&this._defaults.timeOnly===!1&&this._defaults.altFieldTimeOnly===!0)this.$altInput.val(this.formattedTime),this.$input.val(this.formattedDate);else if(this.$altInput){this.$input.val(g);var h="",i=null!==this._defaults.altSeparator?this._defaults.altSeparator:this._defaults.separator,j=null!==this._defaults.altTimeSuffix?this._defaults.altTimeSuffix:this._defaults.timeSuffix;this._defaults.timeOnly||(h=this._defaults.altFormat?$.datepicker.formatDate(this._defaults.altFormat,null===c?new Date:c,e):this.formattedDate,h&&(h+=i)),h+=null!==this._defaults.altTimeFormat?$.datepicker.formatTime(this._defaults.altTimeFormat,this,this._defaults)+j:this.formattedTime+j,this.$altInput.val(h)}else this.$input.val(g);else this.$input.val(this.formattedDate);this.$input.trigger("change")},_onFocus:function(){if(!this.$input.val()&&this._defaults.defaultValue){this.$input.val(this._defaults.defaultValue);var a=$.datepicker._getInst(this.$input.get(0)),b=$.datepicker._get(a,"timepicker");if(b&&b._defaults.timeOnly&&a.input.val()!==a.lastVal)try{$.datepicker._updateDatepicker(a)}catch(c){$.timepicker.log(c)}}},_controls:{slider:{create:function(a,b,c,d,e,f,g){var h=a._defaults.isRTL;return b.prop("slide",null).slider({orientation:"horizontal",value:h?-1*d:d,min:h?-1*f:e,max:h?-1*e:f,step:g,slide:function(b,d){a.control.value(a,$(this),c,h?-1*d.value:d.value),a._onTimeChange()},stop:function(b,c){a._onSelectHandler()}})},options:function(a,b,c,d,e){if(a._defaults.isRTL){if("string"==typeof d)return"min"===d||"max"===d?void 0!==e?b.slider(d,-1*e):Math.abs(b.slider(d)):b.slider(d);var f=d.min,g=d.max;return d.min=d.max=null,void 0!==f&&(d.max=-1*f),void 0!==g&&(d.min=-1*g),b.slider(d)}return"string"==typeof d&&void 0!==e?b.slider(d,e):b.slider(d)},value:function(a,b,c,d){return a._defaults.isRTL?void 0!==d?b.slider("value",-1*d):Math.abs(b.slider("value")):void 0!==d?b.slider("value",d):b.slider("value")}},select:{create:function(a,b,c,d,e,f,g){for(var h='<select class="ui-timepicker-select ui-state-default ui-corner-all" data-unit="'+c+'" data-min="'+e+'" data-max="'+f+'" data-step="'+g+'">',i=a._defaults.pickerTimeFormat||a._defaults.timeFormat,j=e;f>=j;j+=g)h+='<option value="'+j+'"'+(j===d?" selected":"")+">",h+="hour"===c?$.datepicker.formatTime($.trim(i.replace(/[^ht ]/gi,"")),{hour:j},a._defaults):"millisec"===c||"microsec"===c||j>=10?j:"0"+j.toString(),h+="</option>";return h+="</select>",b.children("select").remove(),$(h).appendTo(b).change(function(b){a._onTimeChange(),a._onSelectHandler(),a._afterInject()}),b},options:function(a,b,c,d,e){var f={},g=b.children("select");if("string"==typeof d){if(void 0===e)return g.data(d);f[d]=e}else f=d;return a.control.create(a,b,g.data("unit"),g.val(),f.min>=0?f.min:g.data("min"),f.max||g.data("max"),f.step||g.data("step"))},value:function(a,b,c,d){var e=b.children("select");return void 0!==d?e.val(d):e.val()}}}}),$.fn.extend({timepicker:function(a){a=a||{};var b=Array.prototype.slice.call(arguments);return"object"==typeof a&&(b[0]=$.extend(a,{timeOnly:!0})),$(this).each(function(){$.fn.datetimepicker.apply($(this),b)})},datetimepicker:function(a){a=a||{};var b=arguments;return"string"==typeof a?"getDate"===a||"option"===a&&2===b.length&&"string"==typeof b[1]?$.fn.datepicker.apply($(this[0]),b):this.each(function(){var a=$(this);a.datepicker.apply(a,b)}):this.each(function(){var b=$(this);b.datepicker($.timepicker._newInst(b,a)._defaults)})}}),$.datepicker.parseDateTime=function(a,b,c,d,e){var f=parseDateTimeInternal(a,b,c,d,e);if(f.timeObj){var g=f.timeObj;f.date.setHours(g.hour,g.minute,g.second,g.millisec),f.date.setMicroseconds(g.microsec)}return f.date},$.datepicker.parseTime=function(a,b,c){var d=extendRemove(extendRemove({},$.timepicker._defaults),c||{}),e=(-1!==a.replace(/\'.*?\'/g,"").indexOf("Z"),function(a,b,c){var d,e=function(a,b){var c=[];return a&&$.merge(c,a),b&&$.merge(c,b),c=$.map(c,function(a){return a.replace(/[.*+?|()\[\]{}\\]/g,"\\$&")}),"("+c.join("|")+")?"},f=function(a){var b=a.toLowerCase().match(/(h{1,2}|m{1,2}|s{1,2}|l{1}|c{1}|t{1,2}|z|'.*?')/g),c={h:-1,m:-1,s:-1,l:-1,c:-1,t:-1,z:-1};if(b)for(var d=0;d<b.length;d++)-1===c[b[d].toString().charAt(0)]&&(c[b[d].toString().charAt(0)]=d+1);return c},g="^"+a.toString().replace(/([hH]{1,2}|mm?|ss?|[tT]{1,2}|[zZ]|[lc]|'.*?')/g,function(a){var b=a.length;switch(a.charAt(0).toLowerCase()){case"h":return 1===b?"(\\d?\\d)":"(\\d{"+b+"})";case"m":return 1===b?"(\\d?\\d)":"(\\d{"+b+"})";case"s":return 1===b?"(\\d?\\d)":"(\\d{"+b+"})";case"l":return"(\\d?\\d?\\d)";case"c":return"(\\d?\\d?\\d)";case"z":return"(z|[-+]\\d\\d:?\\d\\d|\\S+)?";case"t":return e(c.amNames,c.pmNames);default:return"("+a.replace(/\'/g,"").replace(/(\.|\$|\^|\\|\/|\(|\)|\[|\]|\?|\+|\*)/g,function(a){return"\\"+a})+")?"}}).replace(/\s/g,"\\s?")+c.timeSuffix+"$",h=f(a),i="";d=b.match(new RegExp(g,"i"));var j={hour:0,minute:0,second:0,millisec:0,microsec:0};return d?(-1!==h.t&&(void 0===d[h.t]||0===d[h.t].length?(i="",j.ampm=""):(i=-1!==$.inArray(d[h.t].toUpperCase(),$.map(c.amNames,function(a,b){return a.toUpperCase()}))?"AM":"PM",j.ampm=c["AM"===i?"amNames":"pmNames"][0])),-1!==h.h&&("AM"===i&&"12"===d[h.h]?j.hour=0:"PM"===i&&"12"!==d[h.h]?j.hour=parseInt(d[h.h],10)+12:j.hour=Number(d[h.h])),-1!==h.m&&(j.minute=Number(d[h.m])),-1!==h.s&&(j.second=Number(d[h.s])),-1!==h.l&&(j.millisec=Number(d[h.l])),-1!==h.c&&(j.microsec=Number(d[h.c])),-1!==h.z&&void 0!==d[h.z]&&(j.timezone=$.timepicker.timezoneOffsetNumber(d[h.z])),j):!1}),f=function(a,b,c){try{var d=new Date("2012-01-01 "+b);if(isNaN(d.getTime())&&(d=new Date("2012-01-01T"+b),isNaN(d.getTime())&&(d=new Date("01/01/2012 "+b),isNaN(d.getTime()))))throw"Unable to parse time with native Date: "+b;return{hour:d.getHours(),minute:d.getMinutes(),second:d.getSeconds(),millisec:d.getMilliseconds(),microsec:d.getMicroseconds(),timezone:-1*d.getTimezoneOffset()}}catch(f){try{return e(a,b,c)}catch(g){$.timepicker.log("Unable to parse \ntimeString: "+b+"\ntimeFormat: "+a)}}return!1};return"function"==typeof d.parse?d.parse(a,b,d):"loose"===d.parse?f(a,b,d):e(a,b,d)},$.datepicker.formatTime=function(a,b,c){c=c||{},c=$.extend({},$.timepicker._defaults,c),b=$.extend({hour:0,minute:0,second:0,millisec:0,microsec:0,timezone:null},b);var d=a,e=c.amNames[0],f=parseInt(b.hour,10);return f>11&&(e=c.pmNames[0]),d=d.replace(/(?:HH?|hh?|mm?|ss?|[tT]{1,2}|[zZ]|[lc]|'.*?')/g,function(a){switch(a){case"HH":return("0"+f).slice(-2);case"H":return f;case"hh":return("0"+convert24to12(f)).slice(-2);case"h":return convert24to12(f);case"mm":return("0"+b.minute).slice(-2);case"m":return b.minute;case"ss":return("0"+b.second).slice(-2);case"s":return b.second;case"l":return("00"+b.millisec).slice(-3);case"c":return("00"+b.microsec).slice(-3);case"z":return $.timepicker.timezoneOffsetString(null===b.timezone?c.timezone:b.timezone,!1);case"Z":return $.timepicker.timezoneOffsetString(null===b.timezone?c.timezone:b.timezone,!0);case"T":return e.charAt(0).toUpperCase();case"TT":return e.toUpperCase();case"t":return e.charAt(0).toLowerCase();case"tt":return e.toLowerCase();default:return a.replace(/'/g,"")}})},$.datepicker._base_selectDate=$.datepicker._selectDate,$.datepicker._selectDate=function(a,b){var c,d=this._getInst($(a)[0]),e=this._get(d,"timepicker");e&&d.settings.showTimepicker?(e._limitMinMaxDateTime(d,!0),c=d.inline,d.inline=d.stay_open=!0,this._base_selectDate(a,b),d.inline=c,d.stay_open=!1,this._notifyChange(d),this._updateDatepicker(d)):this._base_selectDate(a,b)},$.datepicker._base_updateDatepicker=$.datepicker._updateDatepicker,$.datepicker._updateDatepicker=function(a){var b=a.input[0];if(!($.datepicker._curInst&&$.datepicker._curInst!==a&&$.datepicker._datepickerShowing&&$.datepicker._lastInput!==b||"boolean"==typeof a.stay_open&&a.stay_open!==!1)){this._base_updateDatepicker(a);var c=this._get(a,"timepicker");c&&c._addTimePicker(a)}},$.datepicker._base_doKeyPress=$.datepicker._doKeyPress,$.datepicker._doKeyPress=function(a){var b=$.datepicker._getInst(a.target),c=$.datepicker._get(b,"timepicker");if(c&&$.datepicker._get(b,"constrainInput")){var d=c.support.ampm,e=null!==c._defaults.showTimezone?c._defaults.showTimezone:c.support.timezone,f=$.datepicker._possibleChars($.datepicker._get(b,"dateFormat")),g=c._defaults.timeFormat.toString().replace(/[hms]/g,"").replace(/TT/g,d?"APM":"").replace(/Tt/g,d?"AaPpMm":"").replace(/tT/g,d?"AaPpMm":"").replace(/T/g,d?"AP":"").replace(/tt/g,d?"apm":"").replace(/t/g,d?"ap":"")+" "+c._defaults.separator+c._defaults.timeSuffix+(e?c._defaults.timezoneList.join(""):"")+c._defaults.amNames.join("")+c._defaults.pmNames.join("")+f,h=String.fromCharCode(void 0===a.charCode?a.keyCode:a.charCode);return a.ctrlKey||" ">h||!f||g.indexOf(h)>-1}return $.datepicker._base_doKeyPress(a)},$.datepicker._base_updateAlternate=$.datepicker._updateAlternate,$.datepicker._updateAlternate=function(a){var b=this._get(a,"timepicker");if(b){var c=b._defaults.altField;if(c){var d=(b._defaults.altFormat||b._defaults.dateFormat,this._getDate(a)),e=$.datepicker._getFormatConfig(a),f="",g=b._defaults.altSeparator?b._defaults.altSeparator:b._defaults.separator,h=b._defaults.altTimeSuffix?b._defaults.altTimeSuffix:b._defaults.timeSuffix,i=null!==b._defaults.altTimeFormat?b._defaults.altTimeFormat:b._defaults.timeFormat;f+=$.datepicker.formatTime(i,b,b._defaults)+h,b._defaults.timeOnly||b._defaults.altFieldTimeOnly||null===d||(f=b._defaults.altFormat?$.datepicker.formatDate(b._defaults.altFormat,d,e)+g+f:b.formattedDate+g+f),$(c).val(a.input.val()?f:"")}}else $.datepicker._base_updateAlternate(a)},$.datepicker._base_doKeyUp=$.datepicker._doKeyUp,$.datepicker._doKeyUp=function(a){var b=$.datepicker._getInst(a.target),c=$.datepicker._get(b,"timepicker");if(c&&c._defaults.timeOnly&&b.input.val()!==b.lastVal)try{$.datepicker._updateDatepicker(b)}catch(d){$.timepicker.log(d)}return $.datepicker._base_doKeyUp(a)},$.datepicker._base_gotoToday=$.datepicker._gotoToday,$.datepicker._gotoToday=function(a){var b=this._getInst($(a)[0]),c=(b.dpDiv,this._get(b,"timepicker"));selectLocalTimezone(c);var d=new Date;this._setTime(b,d),this._setDate(b,d),this._base_gotoToday(a)},$.datepicker._disableTimepickerDatepicker=function(a){
5
+ var b=this._getInst(a);if(b){var c=this._get(b,"timepicker");$(a).datepicker("getDate"),c&&(b.settings.showTimepicker=!1,c._defaults.showTimepicker=!1,c._updateDateTime(b))}},$.datepicker._enableTimepickerDatepicker=function(a){var b=this._getInst(a);if(b){var c=this._get(b,"timepicker");$(a).datepicker("getDate"),c&&(b.settings.showTimepicker=!0,c._defaults.showTimepicker=!0,c._addTimePicker(b),c._updateDateTime(b))}},$.datepicker._setTime=function(a,b){var c=this._get(a,"timepicker");if(c){var d=c._defaults;c.hour=b?b.getHours():d.hour,c.minute=b?b.getMinutes():d.minute,c.second=b?b.getSeconds():d.second,c.millisec=b?b.getMilliseconds():d.millisec,c.microsec=b?b.getMicroseconds():d.microsec,c._limitMinMaxDateTime(a,!0),c._onTimeChange(),c._updateDateTime(a)}},$.datepicker._setTimeDatepicker=function(a,b,c){var d=this._getInst(a);if(d){var e=this._get(d,"timepicker");if(e){this._setDateFromField(d);var f;b&&("string"==typeof b?(e._parseTime(b,c),f=new Date,f.setHours(e.hour,e.minute,e.second,e.millisec),f.setMicroseconds(e.microsec)):(f=new Date(b.getTime()),f.setMicroseconds(b.getMicroseconds())),"Invalid Date"===f.toString()&&(f=void 0),this._setTime(d,f))}}},$.datepicker._base_setDateDatepicker=$.datepicker._setDateDatepicker,$.datepicker._setDateDatepicker=function(a,b){var c=this._getInst(a),d=b;if(c){"string"==typeof b&&(d=new Date(b),d.getTime()||(this._base_setDateDatepicker.apply(this,arguments),d=$(a).datepicker("getDate")));var e,f=this._get(c,"timepicker");d instanceof Date?(e=new Date(d.getTime()),e.setMicroseconds(d.getMicroseconds())):e=d,f&&e&&(f.support.timezone||null!==f._defaults.timezone||(f.timezone=-1*e.getTimezoneOffset()),d=$.timepicker.timezoneAdjust(d,f.timezone),e=$.timepicker.timezoneAdjust(e,f.timezone)),this._updateDatepicker(c),this._base_setDateDatepicker.apply(this,arguments),this._setTimeDatepicker(a,e,!0)}},$.datepicker._base_getDateDatepicker=$.datepicker._getDateDatepicker,$.datepicker._getDateDatepicker=function(a,b){var c=this._getInst(a);if(c){var d=this._get(c,"timepicker");if(d){void 0===c.lastVal&&this._setDateFromField(c,b);var e=this._getDate(c),f=$.trim(d.$altInput&&d._defaults.altFieldTimeOnly?d.$input.val()+" "+d.$altInput.val():d.$input.val());return e&&d._parseTime(f,!c.settings.timeOnly)&&(e.setHours(d.hour,d.minute,d.second,d.millisec),e.setMicroseconds(d.microsec),null!=d.timezone&&(d.support.timezone||null!==d._defaults.timezone||(d.timezone=-1*e.getTimezoneOffset()),e=$.timepicker.timezoneAdjust(e,d.timezone))),e}return this._base_getDateDatepicker(a,b)}},$.datepicker._base_parseDate=$.datepicker.parseDate,$.datepicker.parseDate=function(a,b,c){var d;try{d=this._base_parseDate(a,b,c)}catch(e){if(!(e.indexOf(":")>=0))throw e;d=this._base_parseDate(a,b.substring(0,b.length-(e.length-e.indexOf(":")-2)),c),$.timepicker.log("Error parsing the date string: "+e+"\ndate string = "+b+"\ndate format = "+a)}return d},$.datepicker._base_formatDate=$.datepicker._formatDate,$.datepicker._formatDate=function(a,b,c,d){var e=this._get(a,"timepicker");return e?(e._updateDateTime(a),e.$input.val()):this._base_formatDate(a)},$.datepicker._base_optionDatepicker=$.datepicker._optionDatepicker,$.datepicker._optionDatepicker=function(a,b,c){var d,e=this._getInst(a);if(!e)return null;var f=this._get(e,"timepicker");if(f){var g,h,i,j,k=null,l=null,m=null,n=f._defaults.evnts,o={};if("string"==typeof b){if("minDate"===b||"minDateTime"===b)k=c;else if("maxDate"===b||"maxDateTime"===b)l=c;else if("onSelect"===b)m=c;else if(n.hasOwnProperty(b)){if("undefined"==typeof c)return n[b];o[b]=c,d={}}}else if("object"==typeof b){b.minDate?k=b.minDate:b.minDateTime?k=b.minDateTime:b.maxDate?l=b.maxDate:b.maxDateTime&&(l=b.maxDateTime);for(g in n)n.hasOwnProperty(g)&&b[g]&&(o[g]=b[g])}for(g in o)o.hasOwnProperty(g)&&(n[g]=o[g],d||(d=$.extend({},b)),delete d[g]);if(d&&isEmptyObject(d))return;if(k?(k=0===k?new Date:new Date(k),f._defaults.minDate=k,f._defaults.minDateTime=k):l?(l=0===l?new Date:new Date(l),f._defaults.maxDate=l,f._defaults.maxDateTime=l):m&&(f._defaults.onSelect=m),k||l)return j=$(a),i=j.datetimepicker("getDate"),h=this._base_optionDatepicker.call($.datepicker,a,d||b,c),j.datetimepicker("setDate",i),h}return void 0===c?this._base_optionDatepicker.call($.datepicker,a,b):this._base_optionDatepicker.call($.datepicker,a,d||b,c)};var isEmptyObject=function(a){var b;for(b in a)if(a.hasOwnProperty(b))return!1;return!0},extendRemove=function(a,b){$.extend(a,b);for(var c in b)(null===b[c]||void 0===b[c])&&(a[c]=b[c]);return a},detectSupport=function(a){var b=a.replace(/'.*?'/g,"").toLowerCase(),c=function(a,b){return-1!==a.indexOf(b)?!0:!1};return{hour:c(b,"h"),minute:c(b,"m"),second:c(b,"s"),millisec:c(b,"l"),microsec:c(b,"c"),timezone:c(b,"z"),ampm:c(b,"t")&&c(a,"h"),iso8601:c(a,"Z")}},convert24to12=function(a){return a%=12,0===a&&(a=12),String(a)},computeEffectiveSetting=function(a,b){return a&&a[b]?a[b]:$.timepicker._defaults[b]},splitDateTime=function(a,b){var c=computeEffectiveSetting(b,"separator"),d=computeEffectiveSetting(b,"timeFormat"),e=d.split(c),f=e.length,g=a.split(c),h=g.length;return h>1?{dateString:g.splice(0,h-f).join(c),timeString:g.splice(0,f).join(c)}:{dateString:a,timeString:""}},parseDateTimeInternal=function(a,b,c,d,e){var f,g,h;if(g=splitDateTime(c,e),f=$.datepicker._base_parseDate(a,g.dateString,d),""===g.timeString)return{date:f};if(h=$.datepicker.parseTime(b,g.timeString,e),!h)throw"Wrong time format";return{date:f,timeObj:h}},selectLocalTimezone=function(a,b){if(a&&a.timezone_select){var c=b||new Date;a.timezone_select.val(-c.getTimezoneOffset())}};$.timepicker=new Timepicker,$.timepicker.timezoneOffsetString=function(a,b){if(isNaN(a)||a>840||-720>a)return a;var c=a,d=c%60,e=(c-d)/60,f=b?":":"",g=(c>=0?"+":"-")+("0"+Math.abs(e)).slice(-2)+f+("0"+Math.abs(d)).slice(-2);return"+00:00"===g?"Z":g},$.timepicker.timezoneOffsetNumber=function(a){var b=a.toString().replace(":","");return"Z"===b.toUpperCase()?0:/^(\-|\+)\d{4}$/.test(b)?("-"===b.substr(0,1)?-1:1)*(60*parseInt(b.substr(1,2),10)+parseInt(b.substr(3,2),10)):a},$.timepicker.timezoneAdjust=function(a,b){var c=$.timepicker.timezoneOffsetNumber(b);return isNaN(c)||a.setMinutes(a.getMinutes()+-a.getTimezoneOffset()-c),a},$.timepicker.timeRange=function(a,b,c){return $.timepicker.handleRange("timepicker",a,b,c)},$.timepicker.datetimeRange=function(a,b,c){$.timepicker.handleRange("datetimepicker",a,b,c)},$.timepicker.dateRange=function(a,b,c){$.timepicker.handleRange("datepicker",a,b,c)},$.timepicker.handleRange=function(a,b,c,d){function e(e,f){var g=b[a]("getDate"),h=c[a]("getDate"),i=e[a]("getDate");if(null!==g){var j=new Date(g.getTime()),k=new Date(g.getTime());j.setMilliseconds(j.getMilliseconds()+d.minInterval),k.setMilliseconds(k.getMilliseconds()+d.maxInterval),d.minInterval>0&&j>h?c[a]("setDate",j):d.maxInterval>0&&h>k?c[a]("setDate",k):g>h&&f[a]("setDate",i)}}function f(b,c,e){if(b.val()){var f=b[a].call(b,"getDate");null!==f&&d.minInterval>0&&("minDate"===e&&f.setMilliseconds(f.getMilliseconds()+d.minInterval),"maxDate"===e&&f.setMilliseconds(f.getMilliseconds()-d.minInterval)),f.getTime&&c[a].call(c,"option",e,f)}}d=$.extend({},{minInterval:0,maxInterval:0,start:{},end:{}},d);var g=!1;return"timepicker"===a&&(g=!0,a="datetimepicker"),$.fn[a].call(b,$.extend({timeOnly:g,onClose:function(a,b){e($(this),c)},onSelect:function(a){f($(this),c,"minDate")}},d,d.start)),$.fn[a].call(c,$.extend({timeOnly:g,onClose:function(a,c){e($(this),b)},onSelect:function(a){f($(this),b,"maxDate")}},d,d.end)),e(b,c),f(b,c,"minDate"),f(c,b,"maxDate"),$([b.get(0),c.get(0)])},$.timepicker.log=function(){window.console&&window.console.log.apply(window.console,Array.prototype.slice.call(arguments))},$.timepicker._util={_extendRemove:extendRemove,_isEmptyObject:isEmptyObject,_convert24to12:convert24to12,_detectSupport:detectSupport,_selectLocalTimezone:selectLocalTimezone,_computeEffectiveSetting:computeEffectiveSetting,_splitDateTime:splitDateTime,_parseDateTimeInternal:parseDateTimeInternal},Date.prototype.getMicroseconds||(Date.prototype.microseconds=0,Date.prototype.getMicroseconds=function(){return this.microseconds},Date.prototype.setMicroseconds=function(a){return this.setMilliseconds(this.getMilliseconds()+Math.floor(a/1e3)),this.microseconds=a%1e3,this}),$.timepicker.version="1.5.4"}});
assets/js/select2.min.js ADDED
@@ -0,0 +1,2 @@
 
 
1
+ /*! Select2 4.0.0 | https://github.com/select2/select2/blob/master/LICENSE.md */!function(a){"function"==typeof define&&define.amd?define(["jquery"],a):a("object"==typeof exports?require("jquery"):jQuery)}(function(a){var b=function(){if(a&&a.fn&&a.fn.select2&&a.fn.select2.amd)var b=a.fn.select2.amd;var b;return function(){if(!b||!b.requirejs){b?c=b:b={};var a,c,d;!function(b){function e(a,b){return u.call(a,b)}function f(a,b){var c,d,e,f,g,h,i,j,k,l,m,n=b&&b.split("/"),o=s.map,p=o&&o["*"]||{};if(a&&"."===a.charAt(0))if(b){for(n=n.slice(0,n.length-1),a=a.split("/"),g=a.length-1,s.nodeIdCompat&&w.test(a[g])&&(a[g]=a[g].replace(w,"")),a=n.concat(a),k=0;k<a.length;k+=1)if(m=a[k],"."===m)a.splice(k,1),k-=1;else if(".."===m){if(1===k&&(".."===a[2]||".."===a[0]))break;k>0&&(a.splice(k-1,2),k-=2)}a=a.join("/")}else 0===a.indexOf("./")&&(a=a.substring(2));if((n||p)&&o){for(c=a.split("/"),k=c.length;k>0;k-=1){if(d=c.slice(0,k).join("/"),n)for(l=n.length;l>0;l-=1)if(e=o[n.slice(0,l).join("/")],e&&(e=e[d])){f=e,h=k;break}if(f)break;!i&&p&&p[d]&&(i=p[d],j=k)}!f&&i&&(f=i,h=j),f&&(c.splice(0,h,f),a=c.join("/"))}return a}function g(a,c){return function(){return n.apply(b,v.call(arguments,0).concat([a,c]))}}function h(a){return function(b){return f(b,a)}}function i(a){return function(b){q[a]=b}}function j(a){if(e(r,a)){var c=r[a];delete r[a],t[a]=!0,m.apply(b,c)}if(!e(q,a)&&!e(t,a))throw new Error("No "+a);return q[a]}function k(a){var b,c=a?a.indexOf("!"):-1;return c>-1&&(b=a.substring(0,c),a=a.substring(c+1,a.length)),[b,a]}function l(a){return function(){return s&&s.config&&s.config[a]||{}}}var m,n,o,p,q={},r={},s={},t={},u=Object.prototype.hasOwnProperty,v=[].slice,w=/\.js$/;o=function(a,b){var c,d=k(a),e=d[0];return a=d[1],e&&(e=f(e,b),c=j(e)),e?a=c&&c.normalize?c.normalize(a,h(b)):f(a,b):(a=f(a,b),d=k(a),e=d[0],a=d[1],e&&(c=j(e))),{f:e?e+"!"+a:a,n:a,pr:e,p:c}},p={require:function(a){return g(a)},exports:function(a){var b=q[a];return"undefined"!=typeof b?b:q[a]={}},module:function(a){return{id:a,uri:"",exports:q[a],config:l(a)}}},m=function(a,c,d,f){var h,k,l,m,n,s,u=[],v=typeof d;if(f=f||a,"undefined"===v||"function"===v){for(c=!c.length&&d.length?["require","exports","module"]:c,n=0;n<c.length;n+=1)if(m=o(c[n],f),k=m.f,"require"===k)u[n]=p.require(a);else if("exports"===k)u[n]=p.exports(a),s=!0;else if("module"===k)h=u[n]=p.module(a);else if(e(q,k)||e(r,k)||e(t,k))u[n]=j(k);else{if(!m.p)throw new Error(a+" missing "+k);m.p.load(m.n,g(f,!0),i(k),{}),u[n]=q[k]}l=d?d.apply(q[a],u):void 0,a&&(h&&h.exports!==b&&h.exports!==q[a]?q[a]=h.exports:l===b&&s||(q[a]=l))}else a&&(q[a]=d)},a=c=n=function(a,c,d,e,f){if("string"==typeof a)return p[a]?p[a](c):j(o(a,c).f);if(!a.splice){if(s=a,s.deps&&n(s.deps,s.callback),!c)return;c.splice?(a=c,c=d,d=null):a=b}return c=c||function(){},"function"==typeof d&&(d=e,e=f),e?m(b,a,c,d):setTimeout(function(){m(b,a,c,d)},4),n},n.config=function(a){return n(a)},a._defined=q,d=function(a,b,c){b.splice||(c=b,b=[]),e(q,a)||e(r,a)||(r[a]=[a,b,c])},d.amd={jQuery:!0}}(),b.requirejs=a,b.require=c,b.define=d}}(),b.define("almond",function(){}),b.define("jquery",[],function(){var b=a||$;return null==b&&console&&console.error&&console.error("Select2: An instance of jQuery or a jQuery-compatible library was not found. Make sure that you are including jQuery before Select2 on your web page."),b}),b.define("select2/utils",["jquery"],function(a){function b(a){var b=a.prototype,c=[];for(var d in b){var e=b[d];"function"==typeof e&&"constructor"!==d&&c.push(d)}return c}var c={};c.Extend=function(a,b){function c(){this.constructor=a}var d={}.hasOwnProperty;for(var e in b)d.call(b,e)&&(a[e]=b[e]);return c.prototype=b.prototype,a.prototype=new c,a.__super__=b.prototype,a},c.Decorate=function(a,c){function d(){var b=Array.prototype.unshift,d=c.prototype.constructor.length,e=a.prototype.constructor;d>0&&(b.call(arguments,a.prototype.constructor),e=c.prototype.constructor),e.apply(this,arguments)}function e(){this.constructor=d}var f=b(c),g=b(a);c.displayName=a.displayName,d.prototype=new e;for(var h=0;h<g.length;h++){var i=g[h];d.prototype[i]=a.prototype[i]}for(var j=(function(a){var b=function(){};a in d.prototype&&(b=d.prototype[a]);var e=c.prototype[a];return function(){var a=Array.prototype.unshift;return a.call(arguments,b),e.apply(this,arguments)}}),k=0;k<f.length;k++){var l=f[k];d.prototype[l]=j(l)}return d};var d=function(){this.listeners={}};return d.prototype.on=function(a,b){this.listeners=this.listeners||{},a in this.listeners?this.listeners[a].push(b):this.listeners[a]=[b]},d.prototype.trigger=function(a){var b=Array.prototype.slice;this.listeners=this.listeners||{},a in this.listeners&&this.invoke(this.listeners[a],b.call(arguments,1)),"*"in this.listeners&&this.invoke(this.listeners["*"],arguments)},d.prototype.invoke=function(a,b){for(var c=0,d=a.length;d>c;c++)a[c].apply(this,b)},c.Observable=d,c.generateChars=function(a){for(var b="",c=0;a>c;c++){var d=Math.floor(36*Math.random());b+=d.toString(36)}return b},c.bind=function(a,b){return function(){a.apply(b,arguments)}},c._convertData=function(a){for(var b in a){var c=b.split("-"),d=a;if(1!==c.length){for(var e=0;e<c.length;e++){var f=c[e];f=f.substring(0,1).toLowerCase()+f.substring(1),f in d||(d[f]={}),e==c.length-1&&(d[f]=a[b]),d=d[f]}delete a[b]}}return a},c.hasScroll=function(b,c){var d=a(c),e=c.style.overflowX,f=c.style.overflowY;return e!==f||"hidden"!==f&&"visible"!==f?"scroll"===e||"scroll"===f?!0:d.innerHeight()<c.scrollHeight||d.innerWidth()<c.scrollWidth:!1},c.escapeMarkup=function(a){var b={"\\":"&#92;","&":"&amp;","<":"&lt;",">":"&gt;",'"':"&quot;","'":"&#39;","/":"&#47;"};return"string"!=typeof a?a:String(a).replace(/[&<>"'\/\\]/g,function(a){return b[a]})},c.appendMany=function(b,c){if("1.7"===a.fn.jquery.substr(0,3)){var d=a();a.map(c,function(a){d=d.add(a)}),c=d}b.append(c)},c}),b.define("select2/results",["jquery","./utils"],function(a,b){function c(a,b,d){this.$element=a,this.data=d,this.options=b,c.__super__.constructor.call(this)}return b.Extend(c,b.Observable),c.prototype.render=function(){var b=a('<ul class="select2-results__options" role="tree"></ul>');return this.options.get("multiple")&&b.attr("aria-multiselectable","true"),this.$results=b,b},c.prototype.clear=function(){this.$results.empty()},c.prototype.displayMessage=function(b){var c=this.options.get("escapeMarkup");this.clear(),this.hideLoading();var d=a('<li role="treeitem" class="select2-results__option"></li>'),e=this.options.get("translations").get(b.message);d.append(c(e(b.args))),this.$results.append(d)},c.prototype.append=function(a){this.hideLoading();var b=[];if(null==a.results||0===a.results.length)return void(0===this.$results.children().length&&this.trigger("results:message",{message:"noResults"}));a.results=this.sort(a.results);for(var c=0;c<a.results.length;c++){var d=a.results[c],e=this.option(d);b.push(e)}this.$results.append(b)},c.prototype.position=function(a,b){var c=b.find(".select2-results");c.append(a)},c.prototype.sort=function(a){var b=this.options.get("sorter");return b(a)},c.prototype.setClasses=function(){var b=this;this.data.current(function(c){var d=a.map(c,function(a){return a.id.toString()}),e=b.$results.find(".select2-results__option[aria-selected]");e.each(function(){var b=a(this),c=a.data(this,"data"),e=""+c.id;null!=c.element&&c.element.selected||null==c.element&&a.inArray(e,d)>-1?b.attr("aria-selected","true"):b.attr("aria-selected","false")});var f=e.filter("[aria-selected=true]");f.length>0?f.first().trigger("mouseenter"):e.first().trigger("mouseenter")})},c.prototype.showLoading=function(a){this.hideLoading();var b=this.options.get("translations").get("searching"),c={disabled:!0,loading:!0,text:b(a)},d=this.option(c);d.className+=" loading-results",this.$results.prepend(d)},c.prototype.hideLoading=function(){this.$results.find(".loading-results").remove()},c.prototype.option=function(b){var c=document.createElement("li");c.className="select2-results__option";var d={role:"treeitem","aria-selected":"false"};b.disabled&&(delete d["aria-selected"],d["aria-disabled"]="true"),null==b.id&&delete d["aria-selected"],null!=b._resultId&&(c.id=b._resultId),b.title&&(c.title=b.title),b.children&&(d.role="group",d["aria-label"]=b.text,delete d["aria-selected"]);for(var e in d){var f=d[e];c.setAttribute(e,f)}if(b.children){var g=a(c),h=document.createElement("strong");h.className="select2-results__group";{a(h)}this.template(b,h);for(var i=[],j=0;j<b.children.length;j++){var k=b.children[j],l=this.option(k);i.push(l)}var m=a("<ul></ul>",{"class":"select2-results__options select2-results__options--nested"});m.append(i),g.append(h),g.append(m)}else this.template(b,c);return a.data(c,"data",b),c},c.prototype.bind=function(b){var c=this,d=b.id+"-results";this.$results.attr("id",d),b.on("results:all",function(a){c.clear(),c.append(a.data),b.isOpen()&&c.setClasses()}),b.on("results:append",function(a){c.append(a.data),b.isOpen()&&c.setClasses()}),b.on("query",function(a){c.showLoading(a)}),b.on("select",function(){b.isOpen()&&c.setClasses()}),b.on("unselect",function(){b.isOpen()&&c.setClasses()}),b.on("open",function(){c.$results.attr("aria-expanded","true"),c.$results.attr("aria-hidden","false"),c.setClasses(),c.ensureHighlightVisible()}),b.on("close",function(){c.$results.attr("aria-expanded","false"),c.$results.attr("aria-hidden","true"),c.$results.removeAttr("aria-activedescendant")}),b.on("results:toggle",function(){var a=c.getHighlightedResults();0!==a.length&&a.trigger("mouseup")}),b.on("results:select",function(){var a=c.getHighlightedResults();if(0!==a.length){var b=a.data("data");"true"==a.attr("aria-selected")?c.trigger("close"):c.trigger("select",{data:b})}}),b.on("results:previous",function(){var a=c.getHighlightedResults(),b=c.$results.find("[aria-selected]"),d=b.index(a);if(0!==d){var e=d-1;0===a.length&&(e=0);var f=b.eq(e);f.trigger("mouseenter");var g=c.$results.offset().top,h=f.offset().top,i=c.$results.scrollTop()+(h-g);0===e?c.$results.scrollTop(0):0>h-g&&c.$results.scrollTop(i)}}),b.on("results:next",function(){var a=c.getHighlightedResults(),b=c.$results.find("[aria-selected]"),d=b.index(a),e=d+1;if(!(e>=b.length)){var f=b.eq(e);f.trigger("mouseenter");var g=c.$results.offset().top+c.$results.outerHeight(!1),h=f.offset().top+f.outerHeight(!1),i=c.$results.scrollTop()+h-g;0===e?c.$results.scrollTop(0):h>g&&c.$results.scrollTop(i)}}),b.on("results:focus",function(a){a.element.addClass("select2-results__option--highlighted")}),b.on("results:message",function(a){c.displayMessage(a)}),a.fn.mousewheel&&this.$results.on("mousewheel",function(a){var b=c.$results.scrollTop(),d=c.$results.get(0).scrollHeight-c.$results.scrollTop()+a.deltaY,e=a.deltaY>0&&b-a.deltaY<=0,f=a.deltaY<0&&d<=c.$results.height();e?(c.$results.scrollTop(0),a.preventDefault(),a.stopPropagation()):f&&(c.$results.scrollTop(c.$results.get(0).scrollHeight-c.$results.height()),a.preventDefault(),a.stopPropagation())}),this.$results.on("mouseup",".select2-results__option[aria-selected]",function(b){var d=a(this),e=d.data("data");return"true"===d.attr("aria-selected")?void(c.options.get("multiple")?c.trigger("unselect",{originalEvent:b,data:e}):c.trigger("close")):void c.trigger("select",{originalEvent:b,data:e})}),this.$results.on("mouseenter",".select2-results__option[aria-selected]",function(){var b=a(this).data("data");c.getHighlightedResults().removeClass("select2-results__option--highlighted"),c.trigger("results:focus",{data:b,element:a(this)})})},c.prototype.getHighlightedResults=function(){var a=this.$results.find(".select2-results__option--highlighted");return a},c.prototype.destroy=function(){this.$results.remove()},c.prototype.ensureHighlightVisible=function(){var a=this.getHighlightedResults();if(0!==a.length){var b=this.$results.find("[aria-selected]"),c=b.index(a),d=this.$results.offset().top,e=a.offset().top,f=this.$results.scrollTop()+(e-d),g=e-d;f-=2*a.outerHeight(!1),2>=c?this.$results.scrollTop(0):(g>this.$results.outerHeight()||0>g)&&this.$results.scrollTop(f)}},c.prototype.template=function(b,c){var d=this.options.get("templateResult"),e=this.options.get("escapeMarkup"),f=d(b);null==f?c.style.display="none":"string"==typeof f?c.innerHTML=e(f):a(c).append(f)},c}),b.define("select2/keys",[],function(){var a={BACKSPACE:8,TAB:9,ENTER:13,SHIFT:16,CTRL:17,ALT:18,ESC:27,SPACE:32,PAGE_UP:33,PAGE_DOWN:34,END:35,HOME:36,LEFT:37,UP:38,RIGHT:39,DOWN:40,DELETE:46};return a}),b.define("select2/selection/base",["jquery","../utils","../keys"],function(a,b,c){function d(a,b){this.$element=a,this.options=b,d.__super__.constructor.call(this)}return b.Extend(d,b.Observable),d.prototype.render=function(){var b=a('<span class="select2-selection" role="combobox" aria-autocomplete="list" aria-haspopup="true" aria-expanded="false"></span>');return this._tabindex=0,null!=this.$element.data("old-tabindex")?this._tabindex=this.$element.data("old-tabindex"):null!=this.$element.attr("tabindex")&&(this._tabindex=this.$element.attr("tabindex")),b.attr("title",this.$element.attr("title")),b.attr("tabindex",this._tabindex),this.$selection=b,b},d.prototype.bind=function(a){var b=this,d=(a.id+"-container",a.id+"-results");this.container=a,this.$selection.on("focus",function(a){b.trigger("focus",a)}),this.$selection.on("blur",function(a){b.trigger("blur",a)}),this.$selection.on("keydown",function(a){b.trigger("keypress",a),a.which===c.SPACE&&a.preventDefault()}),a.on("results:focus",function(a){b.$selection.attr("aria-activedescendant",a.data._resultId)}),a.on("selection:update",function(a){b.update(a.data)}),a.on("open",function(){b.$selection.attr("aria-expanded","true"),b.$selection.attr("aria-owns",d),b._attachCloseHandler(a)}),a.on("close",function(){b.$selection.attr("aria-expanded","false"),b.$selection.removeAttr("aria-activedescendant"),b.$selection.removeAttr("aria-owns"),b.$selection.focus(),b._detachCloseHandler(a)}),a.on("enable",function(){b.$selection.attr("tabindex",b._tabindex)}),a.on("disable",function(){b.$selection.attr("tabindex","-1")})},d.prototype._attachCloseHandler=function(b){a(document.body).on("mousedown.select2."+b.id,function(b){var c=a(b.target),d=c.closest(".select2"),e=a(".select2.select2-container--open");e.each(function(){var b=a(this);if(this!=d[0]){var c=b.data("element");c.select2("close")}})})},d.prototype._detachCloseHandler=function(b){a(document.body).off("mousedown.select2."+b.id)},d.prototype.position=function(a,b){var c=b.find(".selection");c.append(a)},d.prototype.destroy=function(){this._detachCloseHandler(this.container)},d.prototype.update=function(){throw new Error("The `update` method must be defined in child classes.")},d}),b.define("select2/selection/single",["jquery","./base","../utils","../keys"],function(a,b,c){function d(){d.__super__.constructor.apply(this,arguments)}return c.Extend(d,b),d.prototype.render=function(){var a=d.__super__.render.call(this);return a.addClass("select2-selection--single"),a.html('<span class="select2-selection__rendered"></span><span class="select2-selection__arrow" role="presentation"><b role="presentation"></b></span>'),a},d.prototype.bind=function(a){var b=this;d.__super__.bind.apply(this,arguments);var c=a.id+"-container";this.$selection.find(".select2-selection__rendered").attr("id",c),this.$selection.attr("aria-labelledby",c),this.$selection.on("mousedown",function(a){1===a.which&&b.trigger("toggle",{originalEvent:a})}),this.$selection.on("focus",function(){}),this.$selection.on("blur",function(){}),a.on("selection:update",function(a){b.update(a.data)})},d.prototype.clear=function(){this.$selection.find(".select2-selection__rendered").empty()},d.prototype.display=function(a){var b=this.options.get("templateSelection"),c=this.options.get("escapeMarkup");return c(b(a))},d.prototype.selectionContainer=function(){return a("<span></span>")},d.prototype.update=function(a){if(0===a.length)return void this.clear();var b=a[0],c=this.display(b),d=this.$selection.find(".select2-selection__rendered");d.empty().append(c),d.prop("title",b.title||b.text)},d}),b.define("select2/selection/multiple",["jquery","./base","../utils"],function(a,b,c){function d(){d.__super__.constructor.apply(this,arguments)}return c.Extend(d,b),d.prototype.render=function(){var a=d.__super__.render.call(this);return a.addClass("select2-selection--multiple"),a.html('<ul class="select2-selection__rendered"></ul>'),a},d.prototype.bind=function(){var b=this;d.__super__.bind.apply(this,arguments),this.$selection.on("click",function(a){b.trigger("toggle",{originalEvent:a})}),this.$selection.on("click",".select2-selection__choice__remove",function(c){var d=a(this),e=d.parent(),f=e.data("data");b.trigger("unselect",{originalEvent:c,data:f})})},d.prototype.clear=function(){this.$selection.find(".select2-selection__rendered").empty()},d.prototype.display=function(a){var b=this.options.get("templateSelection"),c=this.options.get("escapeMarkup");return c(b(a))},d.prototype.selectionContainer=function(){var b=a('<li class="select2-selection__choice"><span class="select2-selection__choice__remove" role="presentation">&times;</span></li>');return b},d.prototype.update=function(a){if(this.clear(),0!==a.length){for(var b=[],d=0;d<a.length;d++){var e=a[d],f=this.display(e),g=this.selectionContainer();g.append(f),g.prop("title",e.title||e.text),g.data("data",e),b.push(g)}var h=this.$selection.find(".select2-selection__rendered");c.appendMany(h,b)}},d}),b.define("select2/selection/placeholder",["../utils"],function(){function a(a,b,c){this.placeholder=this.normalizePlaceholder(c.get("placeholder")),a.call(this,b,c)}return a.prototype.normalizePlaceholder=function(a,b){return"string"==typeof b&&(b={id:"",text:b}),b},a.prototype.createPlaceholder=function(a,b){var c=this.selectionContainer();return c.html(this.display(b)),c.addClass("select2-selection__placeholder").removeClass("select2-selection__choice"),c},a.prototype.update=function(a,b){var c=1==b.length&&b[0].id!=this.placeholder.id,d=b.length>1;if(d||c)return a.call(this,b);this.clear();var e=this.createPlaceholder(this.placeholder);this.$selection.find(".select2-selection__rendered").append(e)},a}),b.define("select2/selection/allowClear",["jquery","../keys"],function(a,b){function c(){}return c.prototype.bind=function(a,b,c){var d=this;a.call(this,b,c),null==this.placeholder&&this.options.get("debug")&&window.console&&console.error&&console.error("Select2: The `allowClear` option should be used in combination with the `placeholder` option."),this.$selection.on("mousedown",".select2-selection__clear",function(a){d._handleClear(a)}),b.on("keypress",function(a){d._handleKeyboardClear(a,b)})},c.prototype._handleClear=function(a,b){if(!this.options.get("disabled")){var c=this.$selection.find(".select2-selection__clear");if(0!==c.length){b.stopPropagation();for(var d=c.data("data"),e=0;e<d.length;e++){var f={data:d[e]};if(this.trigger("unselect",f),f.prevented)return}this.$element.val(this.placeholder.id).trigger("change"),this.trigger("toggle")}}},c.prototype._handleKeyboardClear=function(a,c,d){d.isOpen()||(c.which==b.DELETE||c.which==b.BACKSPACE)&&this._handleClear(c)},c.prototype.update=function(b,c){if(b.call(this,c),!(this.$selection.find(".select2-selection__placeholder").length>0||0===c.length)){var d=a('<span class="select2-selection__clear">&times;</span>');d.data("data",c),this.$selection.find(".select2-selection__rendered").prepend(d)}},c}),b.define("select2/selection/search",["jquery","../utils","../keys"],function(a,b,c){function d(a,b,c){a.call(this,b,c)}return d.prototype.render=function(b){var c=a('<li class="select2-search select2-search--inline"><input class="select2-search__field" type="search" tabindex="-1" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" role="textbox" /></li>');this.$searchContainer=c,this.$search=c.find("input");var d=b.call(this);return d},d.prototype.bind=function(a,b,d){var e=this;a.call(this,b,d),b.on("open",function(){e.$search.attr("tabindex",0),e.$search.focus()}),b.on("close",function(){e.$search.attr("tabindex",-1),e.$search.val(""),e.$search.focus()}),b.on("enable",function(){e.$search.prop("disabled",!1)}),b.on("disable",function(){e.$search.prop("disabled",!0)}),this.$selection.on("focusin",".select2-search--inline",function(a){e.trigger("focus",a)}),this.$selection.on("focusout",".select2-search--inline",function(a){e.trigger("blur",a)}),this.$selection.on("keydown",".select2-search--inline",function(a){a.stopPropagation(),e.trigger("keypress",a),e._keyUpPrevented=a.isDefaultPrevented();var b=a.which;if(b===c.BACKSPACE&&""===e.$search.val()){var d=e.$searchContainer.prev(".select2-selection__choice");if(d.length>0){var f=d.data("data");e.searchRemoveChoice(f),a.preventDefault()}}}),this.$selection.on("input",".select2-search--inline",function(){e.$selection.off("keyup.search")}),this.$selection.on("keyup.search input",".select2-search--inline",function(a){e.handleSearch(a)})},d.prototype.createPlaceholder=function(a,b){this.$search.attr("placeholder",b.text)},d.prototype.update=function(a,b){this.$search.attr("placeholder",""),a.call(this,b),this.$selection.find(".select2-selection__rendered").append(this.$searchContainer),this.resizeSearch()},d.prototype.handleSearch=function(){if(this.resizeSearch(),!this._keyUpPrevented){var a=this.$search.val();this.trigger("query",{term:a})}this._keyUpPrevented=!1},d.prototype.searchRemoveChoice=function(a,b){this.trigger("unselect",{data:b}),this.trigger("open"),this.$search.val(b.text+" ")},d.prototype.resizeSearch=function(){this.$search.css("width","25px");var a="";if(""!==this.$search.attr("placeholder"))a=this.$selection.find(".select2-selection__rendered").innerWidth();else{var b=this.$search.val().length+1;a=.75*b+"em"}this.$search.css("width",a)},d}),b.define("select2/selection/eventRelay",["jquery"],function(a){function b(){}return b.prototype.bind=function(b,c,d){var e=this,f=["open","opening","close","closing","select","selecting","unselect","unselecting"],g=["opening","closing","selecting","unselecting"];b.call(this,c,d),c.on("*",function(b,c){if(-1!==a.inArray(b,f)){c=c||{};var d=a.Event("select2:"+b,{params:c});e.$element.trigger(d),-1!==a.inArray(b,g)&&(c.prevented=d.isDefaultPrevented())}})},b}),b.define("select2/translation",["jquery","require"],function(a,b){function c(a){this.dict=a||{}}return c.prototype.all=function(){return this.dict},c.prototype.get=function(a){return this.dict[a]},c.prototype.extend=function(b){this.dict=a.extend({},b.all(),this.dict)},c._cache={},c.loadPath=function(a){if(!(a in c._cache)){var d=b(a);c._cache[a]=d}return new c(c._cache[a])},c}),b.define("select2/diacritics",[],function(){var a={"Ⓐ":"A","A":"A","À":"A","Á":"A","Â":"A","Ầ":"A","Ấ":"A","Ẫ":"A","Ẩ":"A","Ã":"A","Ā":"A","Ă":"A","Ằ":"A","Ắ":"A","Ẵ":"A","Ẳ":"A","Ȧ":"A","Ǡ":"A","Ä":"A","Ǟ":"A","Ả":"A","Å":"A","Ǻ":"A","Ǎ":"A","Ȁ":"A","Ȃ":"A","Ạ":"A","Ậ":"A","Ặ":"A","Ḁ":"A","Ą":"A","Ⱥ":"A","Ɐ":"A","Ꜳ":"AA","Æ":"AE","Ǽ":"AE","Ǣ":"AE","Ꜵ":"AO","Ꜷ":"AU","Ꜹ":"AV","Ꜻ":"AV","Ꜽ":"AY","Ⓑ":"B","B":"B","Ḃ":"B","Ḅ":"B","Ḇ":"B","Ƀ":"B","Ƃ":"B","Ɓ":"B","Ⓒ":"C","C":"C","Ć":"C","Ĉ":"C","Ċ":"C","Č":"C","Ç":"C","Ḉ":"C","Ƈ":"C","Ȼ":"C","Ꜿ":"C","Ⓓ":"D","D":"D","Ḋ":"D","Ď":"D","Ḍ":"D","Ḑ":"D","Ḓ":"D","Ḏ":"D","Đ":"D","Ƌ":"D","Ɗ":"D","Ɖ":"D","Ꝺ":"D","DZ":"DZ","DŽ":"DZ","Dz":"Dz","Dž":"Dz","Ⓔ":"E","E":"E","È":"E","É":"E","Ê":"E","Ề":"E","Ế":"E","Ễ":"E","Ể":"E","Ẽ":"E","Ē":"E","Ḕ":"E","Ḗ":"E","Ĕ":"E","Ė":"E","Ë":"E","Ẻ":"E","Ě":"E","Ȅ":"E","Ȇ":"E","Ẹ":"E","Ệ":"E","Ȩ":"E","Ḝ":"E","Ę":"E","Ḙ":"E","Ḛ":"E","Ɛ":"E","Ǝ":"E","Ⓕ":"F","F":"F","Ḟ":"F","Ƒ":"F","Ꝼ":"F","Ⓖ":"G","G":"G","Ǵ":"G","Ĝ":"G","Ḡ":"G","Ğ":"G","Ġ":"G","Ǧ":"G","Ģ":"G","Ǥ":"G","Ɠ":"G","Ꞡ":"G","Ᵹ":"G","Ꝿ":"G","Ⓗ":"H","H":"H","Ĥ":"H","Ḣ":"H","Ḧ":"H","Ȟ":"H","Ḥ":"H","Ḩ":"H","Ḫ":"H","Ħ":"H","Ⱨ":"H","Ⱶ":"H","Ɥ":"H","Ⓘ":"I","I":"I","Ì":"I","Í":"I","Î":"I","Ĩ":"I","Ī":"I","Ĭ":"I","İ":"I","Ï":"I","Ḯ":"I","Ỉ":"I","Ǐ":"I","Ȉ":"I","Ȋ":"I","Ị":"I","Į":"I","Ḭ":"I","Ɨ":"I","Ⓙ":"J","J":"J","Ĵ":"J","Ɉ":"J","Ⓚ":"K","K":"K","Ḱ":"K","Ǩ":"K","Ḳ":"K","Ķ":"K","Ḵ":"K","Ƙ":"K","Ⱪ":"K","Ꝁ":"K","Ꝃ":"K","Ꝅ":"K","Ꞣ":"K","Ⓛ":"L","L":"L","Ŀ":"L","Ĺ":"L","Ľ":"L","Ḷ":"L","Ḹ":"L","Ļ":"L","Ḽ":"L","Ḻ":"L","Ł":"L","Ƚ":"L","Ɫ":"L","Ⱡ":"L","Ꝉ":"L","Ꝇ":"L","Ꞁ":"L","LJ":"LJ","Lj":"Lj","Ⓜ":"M","M":"M","Ḿ":"M","Ṁ":"M","Ṃ":"M","Ɱ":"M","Ɯ":"M","Ⓝ":"N","N":"N","Ǹ":"N","Ń":"N","Ñ":"N","Ṅ":"N","Ň":"N","Ṇ":"N","Ņ":"N","Ṋ":"N","Ṉ":"N","Ƞ":"N","Ɲ":"N","Ꞑ":"N","Ꞥ":"N","NJ":"NJ","Nj":"Nj","Ⓞ":"O","O":"O","Ò":"O","Ó":"O","Ô":"O","Ồ":"O","Ố":"O","Ỗ":"O","Ổ":"O","Õ":"O","Ṍ":"O","Ȭ":"O","Ṏ":"O","Ō":"O","Ṑ":"O","Ṓ":"O","Ŏ":"O","Ȯ":"O","Ȱ":"O","Ö":"O","Ȫ":"O","Ỏ":"O","Ő":"O","Ǒ":"O","Ȍ":"O","Ȏ":"O","Ơ":"O","Ờ":"O","Ớ":"O","Ỡ":"O","Ở":"O","Ợ":"O","Ọ":"O","Ộ":"O","Ǫ":"O","Ǭ":"O","Ø":"O","Ǿ":"O","Ɔ":"O","Ɵ":"O","Ꝋ":"O","Ꝍ":"O","Ƣ":"OI","Ꝏ":"OO","Ȣ":"OU","Ⓟ":"P","P":"P","Ṕ":"P","Ṗ":"P","Ƥ":"P","Ᵽ":"P","Ꝑ":"P","Ꝓ":"P","Ꝕ":"P","Ⓠ":"Q","Q":"Q","Ꝗ":"Q","Ꝙ":"Q","Ɋ":"Q","Ⓡ":"R","R":"R","Ŕ":"R","Ṙ":"R","Ř":"R","Ȑ":"R","Ȓ":"R","Ṛ":"R","Ṝ":"R","Ŗ":"R","Ṟ":"R","Ɍ":"R","Ɽ":"R","Ꝛ":"R","Ꞧ":"R","Ꞃ":"R","Ⓢ":"S","S":"S","ẞ":"S","Ś":"S","Ṥ":"S","Ŝ":"S","Ṡ":"S","Š":"S","Ṧ":"S","Ṣ":"S","Ṩ":"S","Ș":"S","Ş":"S","Ȿ":"S","Ꞩ":"S","Ꞅ":"S","Ⓣ":"T","T":"T","Ṫ":"T","Ť":"T","Ṭ":"T","Ț":"T","Ţ":"T","Ṱ":"T","Ṯ":"T","Ŧ":"T","Ƭ":"T","Ʈ":"T","Ⱦ":"T","Ꞇ":"T","Ꜩ":"TZ","Ⓤ":"U","U":"U","Ù":"U","Ú":"U","Û":"U","Ũ":"U","Ṹ":"U","Ū":"U","Ṻ":"U","Ŭ":"U","Ü":"U","Ǜ":"U","Ǘ":"U","Ǖ":"U","Ǚ":"U","Ủ":"U","Ů":"U","Ű":"U","Ǔ":"U","Ȕ":"U","Ȗ":"U","Ư":"U","Ừ":"U","Ứ":"U","Ữ":"U","Ử":"U","Ự":"U","Ụ":"U","Ṳ":"U","Ų":"U","Ṷ":"U","Ṵ":"U","Ʉ":"U","Ⓥ":"V","V":"V","Ṽ":"V","Ṿ":"V","Ʋ":"V","Ꝟ":"V","Ʌ":"V","Ꝡ":"VY","Ⓦ":"W","W":"W","Ẁ":"W","Ẃ":"W","Ŵ":"W","Ẇ":"W","Ẅ":"W","Ẉ":"W","Ⱳ":"W","Ⓧ":"X","X":"X","Ẋ":"X","Ẍ":"X","Ⓨ":"Y","Y":"Y","Ỳ":"Y","Ý":"Y","Ŷ":"Y","Ỹ":"Y","Ȳ":"Y","Ẏ":"Y","Ÿ":"Y","Ỷ":"Y","Ỵ":"Y","Ƴ":"Y","Ɏ":"Y","Ỿ":"Y","Ⓩ":"Z","Z":"Z","Ź":"Z","Ẑ":"Z","Ż":"Z","Ž":"Z","Ẓ":"Z","Ẕ":"Z","Ƶ":"Z","Ȥ":"Z","Ɀ":"Z","Ⱬ":"Z","Ꝣ":"Z","ⓐ":"a","a":"a","ẚ":"a","à":"a","á":"a","â":"a","ầ":"a","ấ":"a","ẫ":"a","ẩ":"a","ã":"a","ā":"a","ă":"a","ằ":"a","ắ":"a","ẵ":"a","ẳ":"a","ȧ":"a","ǡ":"a","ä":"a","ǟ":"a","ả":"a","å":"a","ǻ":"a","ǎ":"a","ȁ":"a","ȃ":"a","ạ":"a","ậ":"a","ặ":"a","ḁ":"a","ą":"a","ⱥ":"a","ɐ":"a","ꜳ":"aa","æ":"ae","ǽ":"ae","ǣ":"ae","ꜵ":"ao","ꜷ":"au","ꜹ":"av","ꜻ":"av","ꜽ":"ay","ⓑ":"b","b":"b","ḃ":"b","ḅ":"b","ḇ":"b","ƀ":"b","ƃ":"b","ɓ":"b","ⓒ":"c","c":"c","ć":"c","ĉ":"c","ċ":"c","č":"c","ç":"c","ḉ":"c","ƈ":"c","ȼ":"c","ꜿ":"c","ↄ":"c","ⓓ":"d","d":"d","ḋ":"d","ď":"d","ḍ":"d","ḑ":"d","ḓ":"d","ḏ":"d","đ":"d","ƌ":"d","ɖ":"d","ɗ":"d","ꝺ":"d","dz":"dz","dž":"dz","ⓔ":"e","e":"e","è":"e","é":"e","ê":"e","ề":"e","ế":"e","ễ":"e","ể":"e","ẽ":"e","ē":"e","ḕ":"e","ḗ":"e","ĕ":"e","ė":"e","ë":"e","ẻ":"e","ě":"e","ȅ":"e","ȇ":"e","ẹ":"e","ệ":"e","ȩ":"e","ḝ":"e","ę":"e","ḙ":"e","ḛ":"e","ɇ":"e","ɛ":"e","ǝ":"e","ⓕ":"f","f":"f","ḟ":"f","ƒ":"f","ꝼ":"f","ⓖ":"g","g":"g","ǵ":"g","ĝ":"g","ḡ":"g","ğ":"g","ġ":"g","ǧ":"g","ģ":"g","ǥ":"g","ɠ":"g","ꞡ":"g","ᵹ":"g","ꝿ":"g","ⓗ":"h","h":"h","ĥ":"h","ḣ":"h","ḧ":"h","ȟ":"h","ḥ":"h","ḩ":"h","ḫ":"h","ẖ":"h","ħ":"h","ⱨ":"h","ⱶ":"h","ɥ":"h","ƕ":"hv","ⓘ":"i","i":"i","ì":"i","í":"i","î":"i","ĩ":"i","ī":"i","ĭ":"i","ï":"i","ḯ":"i","ỉ":"i","ǐ":"i","ȉ":"i","ȋ":"i","ị":"i","į":"i","ḭ":"i","ɨ":"i","ı":"i","ⓙ":"j","j":"j","ĵ":"j","ǰ":"j","ɉ":"j","ⓚ":"k","k":"k","ḱ":"k","ǩ":"k","ḳ":"k","ķ":"k","ḵ":"k","ƙ":"k","ⱪ":"k","ꝁ":"k","ꝃ":"k","ꝅ":"k","ꞣ":"k","ⓛ":"l","l":"l","ŀ":"l","ĺ":"l","ľ":"l","ḷ":"l","ḹ":"l","ļ":"l","ḽ":"l","ḻ":"l","ſ":"l","ł":"l","ƚ":"l","ɫ":"l","ⱡ":"l","ꝉ":"l","ꞁ":"l","ꝇ":"l","lj":"lj","ⓜ":"m","m":"m","ḿ":"m","ṁ":"m","ṃ":"m","ɱ":"m","ɯ":"m","ⓝ":"n","n":"n","ǹ":"n","ń":"n","ñ":"n","ṅ":"n","ň":"n","ṇ":"n","ņ":"n","ṋ":"n","ṉ":"n","ƞ":"n","ɲ":"n","ʼn":"n","ꞑ":"n","ꞥ":"n","nj":"nj","ⓞ":"o","o":"o","ò":"o","ó":"o","ô":"o","ồ":"o","ố":"o","ỗ":"o","ổ":"o","õ":"o","ṍ":"o","ȭ":"o","ṏ":"o","ō":"o","ṑ":"o","ṓ":"o","ŏ":"o","ȯ":"o","ȱ":"o","ö":"o","ȫ":"o","ỏ":"o","ő":"o","ǒ":"o","ȍ":"o","ȏ":"o","ơ":"o","ờ":"o","ớ":"o","ỡ":"o","ở":"o","ợ":"o","ọ":"o","ộ":"o","ǫ":"o","ǭ":"o","ø":"o","ǿ":"o","ɔ":"o","ꝋ":"o","ꝍ":"o","ɵ":"o","ƣ":"oi","ȣ":"ou","ꝏ":"oo","ⓟ":"p","p":"p","ṕ":"p","ṗ":"p","ƥ":"p","ᵽ":"p","ꝑ":"p","ꝓ":"p","ꝕ":"p","ⓠ":"q","q":"q","ɋ":"q","ꝗ":"q","ꝙ":"q","ⓡ":"r","r":"r","ŕ":"r","ṙ":"r","ř":"r","ȑ":"r","ȓ":"r","ṛ":"r","ṝ":"r","ŗ":"r","ṟ":"r","ɍ":"r","ɽ":"r","ꝛ":"r","ꞧ":"r","ꞃ":"r","ⓢ":"s","s":"s","ß":"s","ś":"s","ṥ":"s","ŝ":"s","ṡ":"s","š":"s","ṧ":"s","ṣ":"s","ṩ":"s","ș":"s","ş":"s","ȿ":"s","ꞩ":"s","ꞅ":"s","ẛ":"s","ⓣ":"t","t":"t","ṫ":"t","ẗ":"t","ť":"t","ṭ":"t","ț":"t","ţ":"t","ṱ":"t","ṯ":"t","ŧ":"t","ƭ":"t","ʈ":"t","ⱦ":"t","ꞇ":"t","ꜩ":"tz","ⓤ":"u","u":"u","ù":"u","ú":"u","û":"u","ũ":"u","ṹ":"u","ū":"u","ṻ":"u","ŭ":"u","ü":"u","ǜ":"u","ǘ":"u","ǖ":"u","ǚ":"u","ủ":"u","ů":"u","ű":"u","ǔ":"u","ȕ":"u","ȗ":"u","ư":"u","ừ":"u","ứ":"u","ữ":"u","ử":"u","ự":"u","ụ":"u","ṳ":"u","ų":"u","ṷ":"u","ṵ":"u","ʉ":"u","ⓥ":"v","v":"v","ṽ":"v","ṿ":"v","ʋ":"v","ꝟ":"v","ʌ":"v","ꝡ":"vy","ⓦ":"w","w":"w","ẁ":"w","ẃ":"w","ŵ":"w","ẇ":"w","ẅ":"w","ẘ":"w","ẉ":"w","ⱳ":"w","ⓧ":"x","x":"x","ẋ":"x","ẍ":"x","ⓨ":"y","y":"y","ỳ":"y","ý":"y","ŷ":"y","ỹ":"y","ȳ":"y","ẏ":"y","ÿ":"y","ỷ":"y","ẙ":"y","ỵ":"y","ƴ":"y","ɏ":"y","ỿ":"y","ⓩ":"z","z":"z","ź":"z","ẑ":"z","ż":"z","ž":"z","ẓ":"z","ẕ":"z","ƶ":"z","ȥ":"z","ɀ":"z","ⱬ":"z","ꝣ":"z","Ά":"Α","Έ":"Ε","Ή":"Η","Ί":"Ι","Ϊ":"Ι","Ό":"Ο","Ύ":"Υ","Ϋ":"Υ","Ώ":"Ω","ά":"α","έ":"ε","ή":"η","ί":"ι","ϊ":"ι","ΐ":"ι","ό":"ο","ύ":"υ","ϋ":"υ","ΰ":"υ","ω":"ω","ς":"σ"};return a}),b.define("select2/data/base",["../utils"],function(a){function b(){b.__super__.constructor.call(this)}return a.Extend(b,a.Observable),b.prototype.current=function(){throw new Error("The `current` method must be defined in child classes.")},b.prototype.query=function(){throw new Error("The `query` method must be defined in child classes.")},b.prototype.bind=function(){},b.prototype.destroy=function(){},b.prototype.generateResultId=function(b,c){var d=b.id+"-result-";return d+=a.generateChars(4),d+=null!=c.id?"-"+c.id.toString():"-"+a.generateChars(4)},b}),b.define("select2/data/select",["./base","../utils","jquery"],function(a,b,c){function d(a,b){this.$element=a,this.options=b,d.__super__.constructor.call(this)}return b.Extend(d,a),d.prototype.current=function(a){var b=[],d=this;this.$element.find(":selected").each(function(){var a=c(this),e=d.item(a);b.push(e)}),a(b)},d.prototype.select=function(a){var b=this;if(a.selected=!0,c(a.element).is("option"))return a.element.selected=!0,void this.$element.trigger("change");if(this.$element.prop("multiple"))this.current(function(d){var e=[];a=[a],a.push.apply(a,d);for(var f=0;f<a.length;f++){var g=a[f].id;-1===c.inArray(g,e)&&e.push(g)}b.$element.val(e),b.$element.trigger("change")});else{var d=a.id;this.$element.val(d),this.$element.trigger("change")}},d.prototype.unselect=function(a){var b=this;if(this.$element.prop("multiple"))return a.selected=!1,c(a.element).is("option")?(a.element.selected=!1,void this.$element.trigger("change")):void this.current(function(d){for(var e=[],f=0;f<d.length;f++){var g=d[f].id;g!==a.id&&-1===c.inArray(g,e)&&e.push(g)}b.$element.val(e),b.$element.trigger("change")})},d.prototype.bind=function(a){var b=this;this.container=a,a.on("select",function(a){b.select(a.data)}),a.on("unselect",function(a){b.unselect(a.data)})},d.prototype.destroy=function(){this.$element.find("*").each(function(){c.removeData(this,"data")})},d.prototype.query=function(a,b){var d=[],e=this,f=this.$element.children();f.each(function(){var b=c(this);if(b.is("option")||b.is("optgroup")){var f=e.item(b),g=e.matches(a,f);null!==g&&d.push(g)}}),b({results:d})},d.prototype.addOptions=function(a){b.appendMany(this.$element,a)},d.prototype.option=function(a){var b;a.children?(b=document.createElement("optgroup"),b.label=a.text):(b=document.createElement("option"),void 0!==b.textContent?b.textContent=a.text:b.innerText=a.text),a.id&&(b.value=a.id),a.disabled&&(b.disabled=!0),a.selected&&(b.selected=!0),a.title&&(b.title=a.title);var d=c(b),e=this._normalizeItem(a);return e.element=b,c.data(b,"data",e),d},d.prototype.item=function(a){var b={};
2
+ if(b=c.data(a[0],"data"),null!=b)return b;if(a.is("option"))b={id:a.val(),text:a.text(),disabled:a.prop("disabled"),selected:a.prop("selected"),title:a.prop("title")};else if(a.is("optgroup")){b={text:a.prop("label"),children:[],title:a.prop("title")};for(var d=a.children("option"),e=[],f=0;f<d.length;f++){var g=c(d[f]),h=this.item(g);e.push(h)}b.children=e}return b=this._normalizeItem(b),b.element=a[0],c.data(a[0],"data",b),b},d.prototype._normalizeItem=function(a){c.isPlainObject(a)||(a={id:a,text:a}),a=c.extend({},{text:""},a);var b={selected:!1,disabled:!1};return null!=a.id&&(a.id=a.id.toString()),null!=a.text&&(a.text=a.text.toString()),null==a._resultId&&a.id&&null!=this.container&&(a._resultId=this.generateResultId(this.container,a)),c.extend({},b,a)},d.prototype.matches=function(a,b){var c=this.options.get("matcher");return c(a,b)},d}),b.define("select2/data/array",["./select","../utils","jquery"],function(a,b,c){function d(a,b){var c=b.get("data")||[];d.__super__.constructor.call(this,a,b),this.addOptions(this.convertToOptions(c))}return b.Extend(d,a),d.prototype.select=function(a){var b=this.$element.find("option").filter(function(b,c){return c.value==a.id.toString()});0===b.length&&(b=this.option(a),this.addOptions(b)),d.__super__.select.call(this,a)},d.prototype.convertToOptions=function(a){function d(a){return function(){return c(this).val()==a.id}}for(var e=this,f=this.$element.find("option"),g=f.map(function(){return e.item(c(this)).id}).get(),h=[],i=0;i<a.length;i++){var j=this._normalizeItem(a[i]);if(c.inArray(j.id,g)>=0){var k=f.filter(d(j)),l=this.item(k),m=(c.extend(!0,{},l,j),this.option(l));k.replaceWith(m)}else{var n=this.option(j);if(j.children){var o=this.convertToOptions(j.children);b.appendMany(n,o)}h.push(n)}}return h},d}),b.define("select2/data/ajax",["./array","../utils","jquery"],function(a,b,c){function d(b,c){this.ajaxOptions=this._applyDefaults(c.get("ajax")),null!=this.ajaxOptions.processResults&&(this.processResults=this.ajaxOptions.processResults),a.__super__.constructor.call(this,b,c)}return b.Extend(d,a),d.prototype._applyDefaults=function(a){var b={data:function(a){return{q:a.term}},transport:function(a,b,d){var e=c.ajax(a);return e.then(b),e.fail(d),e}};return c.extend({},b,a,!0)},d.prototype.processResults=function(a){return a},d.prototype.query=function(a,b){function d(){var d=f.transport(f,function(d){var f=e.processResults(d,a);e.options.get("debug")&&window.console&&console.error&&(f&&f.results&&c.isArray(f.results)||console.error("Select2: The AJAX results did not return an array in the `results` key of the response.")),b(f)},function(){});e._request=d}var e=this;null!=this._request&&(c.isFunction(this._request.abort)&&this._request.abort(),this._request=null);var f=c.extend({type:"GET"},this.ajaxOptions);"function"==typeof f.url&&(f.url=f.url(a)),"function"==typeof f.data&&(f.data=f.data(a)),this.ajaxOptions.delay&&""!==a.term?(this._queryTimeout&&window.clearTimeout(this._queryTimeout),this._queryTimeout=window.setTimeout(d,this.ajaxOptions.delay)):d()},d}),b.define("select2/data/tags",["jquery"],function(a){function b(b,c,d){var e=d.get("tags"),f=d.get("createTag");if(void 0!==f&&(this.createTag=f),b.call(this,c,d),a.isArray(e))for(var g=0;g<e.length;g++){var h=e[g],i=this._normalizeItem(h),j=this.option(i);this.$element.append(j)}}return b.prototype.query=function(a,b,c){function d(a,f){for(var g=a.results,h=0;h<g.length;h++){var i=g[h],j=null!=i.children&&!d({results:i.children},!0),k=i.text===b.term;if(k||j)return f?!1:(a.data=g,void c(a))}if(f)return!0;var l=e.createTag(b);if(null!=l){var m=e.option(l);m.attr("data-select2-tag",!0),e.addOptions([m]),e.insertTag(g,l)}a.results=g,c(a)}var e=this;return this._removeOldTags(),null==b.term||null!=b.page?void a.call(this,b,c):void a.call(this,b,d)},b.prototype.createTag=function(b,c){var d=a.trim(c.term);return""===d?null:{id:d,text:d}},b.prototype.insertTag=function(a,b,c){b.unshift(c)},b.prototype._removeOldTags=function(){var b=(this._lastTag,this.$element.find("option[data-select2-tag]"));b.each(function(){this.selected||a(this).remove()})},b}),b.define("select2/data/tokenizer",["jquery"],function(a){function b(a,b,c){var d=c.get("tokenizer");void 0!==d&&(this.tokenizer=d),a.call(this,b,c)}return b.prototype.bind=function(a,b,c){a.call(this,b,c),this.$search=b.dropdown.$search||b.selection.$search||c.find(".select2-search__field")},b.prototype.query=function(a,b,c){function d(a){e.select(a)}var e=this;b.term=b.term||"";var f=this.tokenizer(b,this.options,d);f.term!==b.term&&(this.$search.length&&(this.$search.val(f.term),this.$search.focus()),b.term=f.term),a.call(this,b,c)},b.prototype.tokenizer=function(b,c,d,e){for(var f=d.get("tokenSeparators")||[],g=c.term,h=0,i=this.createTag||function(a){return{id:a.term,text:a.term}};h<g.length;){var j=g[h];if(-1!==a.inArray(j,f)){var k=g.substr(0,h),l=a.extend({},c,{term:k}),m=i(l);e(m),g=g.substr(h+1)||"",h=0}else h++}return{term:g}},b}),b.define("select2/data/minimumInputLength",[],function(){function a(a,b,c){this.minimumInputLength=c.get("minimumInputLength"),a.call(this,b,c)}return a.prototype.query=function(a,b,c){return b.term=b.term||"",b.term.length<this.minimumInputLength?void this.trigger("results:message",{message:"inputTooShort",args:{minimum:this.minimumInputLength,input:b.term,params:b}}):void a.call(this,b,c)},a}),b.define("select2/data/maximumInputLength",[],function(){function a(a,b,c){this.maximumInputLength=c.get("maximumInputLength"),a.call(this,b,c)}return a.prototype.query=function(a,b,c){return b.term=b.term||"",this.maximumInputLength>0&&b.term.length>this.maximumInputLength?void this.trigger("results:message",{message:"inputTooLong",args:{maximum:this.maximumInputLength,input:b.term,params:b}}):void a.call(this,b,c)},a}),b.define("select2/data/maximumSelectionLength",[],function(){function a(a,b,c){this.maximumSelectionLength=c.get("maximumSelectionLength"),a.call(this,b,c)}return a.prototype.query=function(a,b,c){var d=this;this.current(function(e){var f=null!=e?e.length:0;return d.maximumSelectionLength>0&&f>=d.maximumSelectionLength?void d.trigger("results:message",{message:"maximumSelected",args:{maximum:d.maximumSelectionLength}}):void a.call(d,b,c)})},a}),b.define("select2/dropdown",["jquery","./utils"],function(a,b){function c(a,b){this.$element=a,this.options=b,c.__super__.constructor.call(this)}return b.Extend(c,b.Observable),c.prototype.render=function(){var b=a('<span class="select2-dropdown"><span class="select2-results"></span></span>');return b.attr("dir",this.options.get("dir")),this.$dropdown=b,b},c.prototype.position=function(){},c.prototype.destroy=function(){this.$dropdown.remove()},c}),b.define("select2/dropdown/search",["jquery","../utils"],function(a){function b(){}return b.prototype.render=function(b){var c=b.call(this),d=a('<span class="select2-search select2-search--dropdown"><input class="select2-search__field" type="search" tabindex="-1" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" role="textbox" /></span>');return this.$searchContainer=d,this.$search=d.find("input"),c.prepend(d),c},b.prototype.bind=function(b,c,d){var e=this;b.call(this,c,d),this.$search.on("keydown",function(a){e.trigger("keypress",a),e._keyUpPrevented=a.isDefaultPrevented()}),this.$search.on("input",function(){a(this).off("keyup")}),this.$search.on("keyup input",function(a){e.handleSearch(a)}),c.on("open",function(){e.$search.attr("tabindex",0),e.$search.focus(),window.setTimeout(function(){e.$search.focus()},0)}),c.on("close",function(){e.$search.attr("tabindex",-1),e.$search.val("")}),c.on("results:all",function(a){if(null==a.query.term||""===a.query.term){var b=e.showSearch(a);b?e.$searchContainer.removeClass("select2-search--hide"):e.$searchContainer.addClass("select2-search--hide")}})},b.prototype.handleSearch=function(){if(!this._keyUpPrevented){var a=this.$search.val();this.trigger("query",{term:a})}this._keyUpPrevented=!1},b.prototype.showSearch=function(){return!0},b}),b.define("select2/dropdown/hidePlaceholder",[],function(){function a(a,b,c,d){this.placeholder=this.normalizePlaceholder(c.get("placeholder")),a.call(this,b,c,d)}return a.prototype.append=function(a,b){b.results=this.removePlaceholder(b.results),a.call(this,b)},a.prototype.normalizePlaceholder=function(a,b){return"string"==typeof b&&(b={id:"",text:b}),b},a.prototype.removePlaceholder=function(a,b){for(var c=b.slice(0),d=b.length-1;d>=0;d--){var e=b[d];this.placeholder.id===e.id&&c.splice(d,1)}return c},a}),b.define("select2/dropdown/infiniteScroll",["jquery"],function(a){function b(a,b,c,d){this.lastParams={},a.call(this,b,c,d),this.$loadingMore=this.createLoadingMore(),this.loading=!1}return b.prototype.append=function(a,b){this.$loadingMore.remove(),this.loading=!1,a.call(this,b),this.showLoadingMore(b)&&this.$results.append(this.$loadingMore)},b.prototype.bind=function(b,c,d){var e=this;b.call(this,c,d),c.on("query",function(a){e.lastParams=a,e.loading=!0}),c.on("query:append",function(a){e.lastParams=a,e.loading=!0}),this.$results.on("scroll",function(){var b=a.contains(document.documentElement,e.$loadingMore[0]);if(!e.loading&&b){var c=e.$results.offset().top+e.$results.outerHeight(!1),d=e.$loadingMore.offset().top+e.$loadingMore.outerHeight(!1);c+50>=d&&e.loadMore()}})},b.prototype.loadMore=function(){this.loading=!0;var b=a.extend({},{page:1},this.lastParams);b.page++,this.trigger("query:append",b)},b.prototype.showLoadingMore=function(a,b){return b.pagination&&b.pagination.more},b.prototype.createLoadingMore=function(){var b=a('<li class="option load-more" role="treeitem"></li>'),c=this.options.get("translations").get("loadingMore");return b.html(c(this.lastParams)),b},b}),b.define("select2/dropdown/attachBody",["jquery","../utils"],function(a,b){function c(a,b,c){this.$dropdownParent=c.get("dropdownParent")||document.body,a.call(this,b,c)}return c.prototype.bind=function(a,b,c){var d=this,e=!1;a.call(this,b,c),b.on("open",function(){d._showDropdown(),d._attachPositioningHandler(b),e||(e=!0,b.on("results:all",function(){d._positionDropdown(),d._resizeDropdown()}),b.on("results:append",function(){d._positionDropdown(),d._resizeDropdown()}))}),b.on("close",function(){d._hideDropdown(),d._detachPositioningHandler(b)}),this.$dropdownContainer.on("mousedown",function(a){a.stopPropagation()})},c.prototype.position=function(a,b,c){b.attr("class",c.attr("class")),b.removeClass("select2"),b.addClass("select2-container--open"),b.css({position:"absolute",top:-999999}),this.$container=c},c.prototype.render=function(b){var c=a("<span></span>"),d=b.call(this);return c.append(d),this.$dropdownContainer=c,c},c.prototype._hideDropdown=function(){this.$dropdownContainer.detach()},c.prototype._attachPositioningHandler=function(c){var d=this,e="scroll.select2."+c.id,f="resize.select2."+c.id,g="orientationchange.select2."+c.id,h=this.$container.parents().filter(b.hasScroll);h.each(function(){a(this).data("select2-scroll-position",{x:a(this).scrollLeft(),y:a(this).scrollTop()})}),h.on(e,function(){var b=a(this).data("select2-scroll-position");a(this).scrollTop(b.y)}),a(window).on(e+" "+f+" "+g,function(){d._positionDropdown(),d._resizeDropdown()})},c.prototype._detachPositioningHandler=function(c){var d="scroll.select2."+c.id,e="resize.select2."+c.id,f="orientationchange.select2."+c.id,g=this.$container.parents().filter(b.hasScroll);g.off(d),a(window).off(d+" "+e+" "+f)},c.prototype._positionDropdown=function(){var b=a(window),c=this.$dropdown.hasClass("select2-dropdown--above"),d=this.$dropdown.hasClass("select2-dropdown--below"),e=null,f=(this.$container.position(),this.$container.offset());f.bottom=f.top+this.$container.outerHeight(!1);var g={height:this.$container.outerHeight(!1)};g.top=f.top,g.bottom=f.top+g.height;var h={height:this.$dropdown.outerHeight(!1)},i={top:b.scrollTop(),bottom:b.scrollTop()+b.height()},j=i.top<f.top-h.height,k=i.bottom>f.bottom+h.height,l={left:f.left,top:g.bottom};c||d||(e="below"),k||!j||c?!j&&k&&c&&(e="below"):e="above",("above"==e||c&&"below"!==e)&&(l.top=g.top-h.height),null!=e&&(this.$dropdown.removeClass("select2-dropdown--below select2-dropdown--above").addClass("select2-dropdown--"+e),this.$container.removeClass("select2-container--below select2-container--above").addClass("select2-container--"+e)),this.$dropdownContainer.css(l)},c.prototype._resizeDropdown=function(){this.$dropdownContainer.width();var a={width:this.$container.outerWidth(!1)+"px"};this.options.get("dropdownAutoWidth")&&(a.minWidth=a.width,a.width="auto"),this.$dropdown.css(a)},c.prototype._showDropdown=function(){this.$dropdownContainer.appendTo(this.$dropdownParent),this._positionDropdown(),this._resizeDropdown()},c}),b.define("select2/dropdown/minimumResultsForSearch",[],function(){function a(b){for(var c=0,d=0;d<b.length;d++){var e=b[d];e.children?c+=a(e.children):c++}return c}function b(a,b,c,d){this.minimumResultsForSearch=c.get("minimumResultsForSearch"),this.minimumResultsForSearch<0&&(this.minimumResultsForSearch=1/0),a.call(this,b,c,d)}return b.prototype.showSearch=function(b,c){return a(c.data.results)<this.minimumResultsForSearch?!1:b.call(this,c)},b}),b.define("select2/dropdown/selectOnClose",[],function(){function a(){}return a.prototype.bind=function(a,b,c){var d=this;a.call(this,b,c),b.on("close",function(){d._handleSelectOnClose()})},a.prototype._handleSelectOnClose=function(){var a=this.getHighlightedResults();a.length<1||this.trigger("select",{data:a.data("data")})},a}),b.define("select2/dropdown/closeOnSelect",[],function(){function a(){}return a.prototype.bind=function(a,b,c){var d=this;a.call(this,b,c),b.on("select",function(a){d._selectTriggered(a)}),b.on("unselect",function(a){d._selectTriggered(a)})},a.prototype._selectTriggered=function(a,b){var c=b.originalEvent;c&&c.ctrlKey||this.trigger("close")},a}),b.define("select2/i18n/en",[],function(){return{errorLoading:function(){return"The results could not be loaded."},inputTooLong:function(a){var b=a.input.length-a.maximum,c="Please delete "+b+" character";return 1!=b&&(c+="s"),c},inputTooShort:function(a){var b=a.minimum-a.input.length,c="Please enter "+b+" or more characters";return c},loadingMore:function(){return"Loading more results…"},maximumSelected:function(a){var b="You can only select "+a.maximum+" item";return 1!=a.maximum&&(b+="s"),b},noResults:function(){return"No results found"},searching:function(){return"Searching…"}}}),b.define("select2/defaults",["jquery","require","./results","./selection/single","./selection/multiple","./selection/placeholder","./selection/allowClear","./selection/search","./selection/eventRelay","./utils","./translation","./diacritics","./data/select","./data/array","./data/ajax","./data/tags","./data/tokenizer","./data/minimumInputLength","./data/maximumInputLength","./data/maximumSelectionLength","./dropdown","./dropdown/search","./dropdown/hidePlaceholder","./dropdown/infiniteScroll","./dropdown/attachBody","./dropdown/minimumResultsForSearch","./dropdown/selectOnClose","./dropdown/closeOnSelect","./i18n/en"],function(a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z,A,B,C){function D(){this.reset()}D.prototype.apply=function(l){if(l=a.extend({},this.defaults,l),null==l.dataAdapter){if(l.dataAdapter=null!=l.ajax?o:null!=l.data?n:m,l.minimumInputLength>0&&(l.dataAdapter=j.Decorate(l.dataAdapter,r)),l.maximumInputLength>0&&(l.dataAdapter=j.Decorate(l.dataAdapter,s)),l.maximumSelectionLength>0&&(l.dataAdapter=j.Decorate(l.dataAdapter,t)),l.tags&&(l.dataAdapter=j.Decorate(l.dataAdapter,p)),(null!=l.tokenSeparators||null!=l.tokenizer)&&(l.dataAdapter=j.Decorate(l.dataAdapter,q)),null!=l.query){var C=b(l.amdBase+"compat/query");l.dataAdapter=j.Decorate(l.dataAdapter,C)}if(null!=l.initSelection){var D=b(l.amdBase+"compat/initSelection");l.dataAdapter=j.Decorate(l.dataAdapter,D)}}if(null==l.resultsAdapter&&(l.resultsAdapter=c,null!=l.ajax&&(l.resultsAdapter=j.Decorate(l.resultsAdapter,x)),null!=l.placeholder&&(l.resultsAdapter=j.Decorate(l.resultsAdapter,w)),l.selectOnClose&&(l.resultsAdapter=j.Decorate(l.resultsAdapter,A))),null==l.dropdownAdapter){if(l.multiple)l.dropdownAdapter=u;else{var E=j.Decorate(u,v);l.dropdownAdapter=E}if(0!==l.minimumResultsForSearch&&(l.dropdownAdapter=j.Decorate(l.dropdownAdapter,z)),l.closeOnSelect&&(l.dropdownAdapter=j.Decorate(l.dropdownAdapter,B)),null!=l.dropdownCssClass||null!=l.dropdownCss||null!=l.adaptDropdownCssClass){var F=b(l.amdBase+"compat/dropdownCss");l.dropdownAdapter=j.Decorate(l.dropdownAdapter,F)}l.dropdownAdapter=j.Decorate(l.dropdownAdapter,y)}if(null==l.selectionAdapter){if(l.selectionAdapter=l.multiple?e:d,null!=l.placeholder&&(l.selectionAdapter=j.Decorate(l.selectionAdapter,f)),l.allowClear&&(l.selectionAdapter=j.Decorate(l.selectionAdapter,g)),l.multiple&&(l.selectionAdapter=j.Decorate(l.selectionAdapter,h)),null!=l.containerCssClass||null!=l.containerCss||null!=l.adaptContainerCssClass){var G=b(l.amdBase+"compat/containerCss");l.selectionAdapter=j.Decorate(l.selectionAdapter,G)}l.selectionAdapter=j.Decorate(l.selectionAdapter,i)}if("string"==typeof l.language)if(l.language.indexOf("-")>0){var H=l.language.split("-"),I=H[0];l.language=[l.language,I]}else l.language=[l.language];if(a.isArray(l.language)){var J=new k;l.language.push("en");for(var K=l.language,L=0;L<K.length;L++){var M=K[L],N={};try{N=k.loadPath(M)}catch(O){try{M=this.defaults.amdLanguageBase+M,N=k.loadPath(M)}catch(P){l.debug&&window.console&&console.warn&&console.warn('Select2: The language file for "'+M+'" could not be automatically loaded. A fallback will be used instead.');continue}}J.extend(N)}l.translations=J}else{var Q=k.loadPath(this.defaults.amdLanguageBase+"en"),R=new k(l.language);R.extend(Q),l.translations=R}return l},D.prototype.reset=function(){function b(a){function b(a){return l[a]||a}return a.replace(/[^\u0000-\u007E]/g,b)}function c(d,e){if(""===a.trim(d.term))return e;if(e.children&&e.children.length>0){for(var f=a.extend(!0,{},e),g=e.children.length-1;g>=0;g--){var h=e.children[g],i=c(d,h);null==i&&f.children.splice(g,1)}return f.children.length>0?f:c(d,f)}var j=b(e.text).toUpperCase(),k=b(d.term).toUpperCase();return j.indexOf(k)>-1?e:null}this.defaults={amdBase:"./",amdLanguageBase:"./i18n/",closeOnSelect:!0,debug:!1,dropdownAutoWidth:!1,escapeMarkup:j.escapeMarkup,language:C,matcher:c,minimumInputLength:0,maximumInputLength:0,maximumSelectionLength:0,minimumResultsForSearch:0,selectOnClose:!1,sorter:function(a){return a},templateResult:function(a){return a.text},templateSelection:function(a){return a.text},theme:"default",width:"resolve"}},D.prototype.set=function(b,c){var d=a.camelCase(b),e={};e[d]=c;var f=j._convertData(e);a.extend(this.defaults,f)};var E=new D;return E}),b.define("select2/options",["require","jquery","./defaults","./utils"],function(a,b,c,d){function e(b,e){if(this.options=b,null!=e&&this.fromElement(e),this.options=c.apply(this.options),e&&e.is("input")){var f=a(this.get("amdBase")+"compat/inputData");this.options.dataAdapter=d.Decorate(this.options.dataAdapter,f)}}return e.prototype.fromElement=function(a){var c=["select2"];null==this.options.multiple&&(this.options.multiple=a.prop("multiple")),null==this.options.disabled&&(this.options.disabled=a.prop("disabled")),null==this.options.language&&(a.prop("lang")?this.options.language=a.prop("lang").toLowerCase():a.closest("[lang]").prop("lang")&&(this.options.language=a.closest("[lang]").prop("lang"))),null==this.options.dir&&(this.options.dir=a.prop("dir")?a.prop("dir"):a.closest("[dir]").prop("dir")?a.closest("[dir]").prop("dir"):"ltr"),a.prop("disabled",this.options.disabled),a.prop("multiple",this.options.multiple),a.data("select2Tags")&&(this.options.debug&&window.console&&console.warn&&console.warn('Select2: The `data-select2-tags` attribute has been changed to use the `data-data` and `data-tags="true"` attributes and will be removed in future versions of Select2.'),a.data("data",a.data("select2Tags")),a.data("tags",!0)),a.data("ajaxUrl")&&(this.options.debug&&window.console&&console.warn&&console.warn("Select2: The `data-ajax-url` attribute has been changed to `data-ajax--url` and support for the old attribute will be removed in future versions of Select2."),a.attr("ajax--url",a.data("ajaxUrl")),a.data("ajax--url",a.data("ajaxUrl")));var e={};e=b.fn.jquery&&"1."==b.fn.jquery.substr(0,2)&&a[0].dataset?b.extend(!0,{},a[0].dataset,a.data()):a.data();var f=b.extend(!0,{},e);f=d._convertData(f);for(var g in f)b.inArray(g,c)>-1||(b.isPlainObject(this.options[g])?b.extend(this.options[g],f[g]):this.options[g]=f[g]);return this},e.prototype.get=function(a){return this.options[a]},e.prototype.set=function(a,b){this.options[a]=b},e}),b.define("select2/core",["jquery","./options","./utils","./keys"],function(a,b,c,d){var e=function(a,c){null!=a.data("select2")&&a.data("select2").destroy(),this.$element=a,this.id=this._generateId(a),c=c||{},this.options=new b(c,a),e.__super__.constructor.call(this);var d=a.attr("tabindex")||0;a.data("old-tabindex",d),a.attr("tabindex","-1");var f=this.options.get("dataAdapter");this.dataAdapter=new f(a,this.options);var g=this.render();this._placeContainer(g);var h=this.options.get("selectionAdapter");this.selection=new h(a,this.options),this.$selection=this.selection.render(),this.selection.position(this.$selection,g);var i=this.options.get("dropdownAdapter");this.dropdown=new i(a,this.options),this.$dropdown=this.dropdown.render(),this.dropdown.position(this.$dropdown,g);var j=this.options.get("resultsAdapter");this.results=new j(a,this.options,this.dataAdapter),this.$results=this.results.render(),this.results.position(this.$results,this.$dropdown);var k=this;this._bindAdapters(),this._registerDomEvents(),this._registerDataEvents(),this._registerSelectionEvents(),this._registerDropdownEvents(),this._registerResultsEvents(),this._registerEvents(),this.dataAdapter.current(function(a){k.trigger("selection:update",{data:a})}),a.addClass("select2-hidden-accessible"),a.attr("aria-hidden","true"),this._syncAttributes(),a.data("select2",this)};return c.Extend(e,c.Observable),e.prototype._generateId=function(a){var b="";return b=null!=a.attr("id")?a.attr("id"):null!=a.attr("name")?a.attr("name")+"-"+c.generateChars(2):c.generateChars(4),b="select2-"+b},e.prototype._placeContainer=function(a){a.insertAfter(this.$element);var b=this._resolveWidth(this.$element,this.options.get("width"));null!=b&&a.css("width",b)},e.prototype._resolveWidth=function(a,b){var c=/^width:(([-+]?([0-9]*\.)?[0-9]+)(px|em|ex|%|in|cm|mm|pt|pc))/i;if("resolve"==b){var d=this._resolveWidth(a,"style");return null!=d?d:this._resolveWidth(a,"element")}if("element"==b){var e=a.outerWidth(!1);return 0>=e?"auto":e+"px"}if("style"==b){var f=a.attr("style");if("string"!=typeof f)return null;for(var g=f.split(";"),h=0,i=g.length;i>h;h+=1){var j=g[h].replace(/\s/g,""),k=j.match(c);if(null!==k&&k.length>=1)return k[1]}return null}return b},e.prototype._bindAdapters=function(){this.dataAdapter.bind(this,this.$container),this.selection.bind(this,this.$container),this.dropdown.bind(this,this.$container),this.results.bind(this,this.$container)},e.prototype._registerDomEvents=function(){var b=this;this.$element.on("change.select2",function(){b.dataAdapter.current(function(a){b.trigger("selection:update",{data:a})})}),this._sync=c.bind(this._syncAttributes,this),this.$element[0].attachEvent&&this.$element[0].attachEvent("onpropertychange",this._sync);var d=window.MutationObserver||window.WebKitMutationObserver||window.MozMutationObserver;null!=d?(this._observer=new d(function(c){a.each(c,b._sync)}),this._observer.observe(this.$element[0],{attributes:!0,subtree:!1})):this.$element[0].addEventListener&&this.$element[0].addEventListener("DOMAttrModified",b._sync,!1)},e.prototype._registerDataEvents=function(){var a=this;this.dataAdapter.on("*",function(b,c){a.trigger(b,c)})},e.prototype._registerSelectionEvents=function(){var b=this,c=["toggle"];this.selection.on("toggle",function(){b.toggleDropdown()}),this.selection.on("*",function(d,e){-1===a.inArray(d,c)&&b.trigger(d,e)})},e.prototype._registerDropdownEvents=function(){var a=this;this.dropdown.on("*",function(b,c){a.trigger(b,c)})},e.prototype._registerResultsEvents=function(){var a=this;this.results.on("*",function(b,c){a.trigger(b,c)})},e.prototype._registerEvents=function(){var a=this;this.on("open",function(){a.$container.addClass("select2-container--open")}),this.on("close",function(){a.$container.removeClass("select2-container--open")}),this.on("enable",function(){a.$container.removeClass("select2-container--disabled")}),this.on("disable",function(){a.$container.addClass("select2-container--disabled")}),this.on("focus",function(){a.$container.addClass("select2-container--focus")}),this.on("blur",function(){a.$container.removeClass("select2-container--focus")}),this.on("query",function(b){a.isOpen()||a.trigger("open"),this.dataAdapter.query(b,function(c){a.trigger("results:all",{data:c,query:b})})}),this.on("query:append",function(b){this.dataAdapter.query(b,function(c){a.trigger("results:append",{data:c,query:b})})}),this.on("keypress",function(b){var c=b.which;a.isOpen()?c===d.ENTER?(a.trigger("results:select"),b.preventDefault()):c===d.SPACE&&b.ctrlKey?(a.trigger("results:toggle"),b.preventDefault()):c===d.UP?(a.trigger("results:previous"),b.preventDefault()):c===d.DOWN?(a.trigger("results:next"),b.preventDefault()):(c===d.ESC||c===d.TAB)&&(a.close(),b.preventDefault()):(c===d.ENTER||c===d.SPACE||(c===d.DOWN||c===d.UP)&&b.altKey)&&(a.open(),b.preventDefault())})},e.prototype._syncAttributes=function(){this.options.set("disabled",this.$element.prop("disabled")),this.options.get("disabled")?(this.isOpen()&&this.close(),this.trigger("disable")):this.trigger("enable")},e.prototype.trigger=function(a,b){var c=e.__super__.trigger,d={open:"opening",close:"closing",select:"selecting",unselect:"unselecting"};if(a in d){var f=d[a],g={prevented:!1,name:a,args:b};if(c.call(this,f,g),g.prevented)return void(b.prevented=!0)}c.call(this,a,b)},e.prototype.toggleDropdown=function(){this.options.get("disabled")||(this.isOpen()?this.close():this.open())},e.prototype.open=function(){this.isOpen()||(this.trigger("query",{}),this.trigger("open"))},e.prototype.close=function(){this.isOpen()&&this.trigger("close")},e.prototype.isOpen=function(){return this.$container.hasClass("select2-container--open")},e.prototype.enable=function(a){this.options.get("debug")&&window.console&&console.warn&&console.warn('Select2: The `select2("enable")` method has been deprecated and will be removed in later Select2 versions. Use $element.prop("disabled") instead.'),(null==a||0===a.length)&&(a=[!0]);var b=!a[0];this.$element.prop("disabled",b)},e.prototype.data=function(){this.options.get("debug")&&arguments.length>0&&window.console&&console.warn&&console.warn('Select2: Data can no longer be set using `select2("data")`. You should consider setting the value instead using `$element.val()`.');var a=[];return this.dataAdapter.current(function(b){a=b}),a},e.prototype.val=function(b){if(this.options.get("debug")&&window.console&&console.warn&&console.warn('Select2: The `select2("val")` method has been deprecated and will be removed in later Select2 versions. Use $element.val() instead.'),null==b||0===b.length)return this.$element.val();var c=b[0];a.isArray(c)&&(c=a.map(c,function(a){return a.toString()})),this.$element.val(c).trigger("change")},e.prototype.destroy=function(){this.$container.remove(),this.$element[0].detachEvent&&this.$element[0].detachEvent("onpropertychange",this._sync),null!=this._observer?(this._observer.disconnect(),this._observer=null):this.$element[0].removeEventListener&&this.$element[0].removeEventListener("DOMAttrModified",this._sync,!1),this._sync=null,this.$element.off(".select2"),this.$element.attr("tabindex",this.$element.data("old-tabindex")),this.$element.removeClass("select2-hidden-accessible"),this.$element.attr("aria-hidden","false"),this.$element.removeData("select2"),this.dataAdapter.destroy(),this.selection.destroy(),this.dropdown.destroy(),this.results.destroy(),this.dataAdapter=null,this.selection=null,this.dropdown=null,this.results=null},e.prototype.render=function(){var b=a('<span class="select2 select2-container"><span class="selection"></span><span class="dropdown-wrapper" aria-hidden="true"></span></span>');return b.attr("dir",this.options.get("dir")),this.$container=b,this.$container.addClass("select2-container--"+this.options.get("theme")),b.data("element",this.$element),b},e}),b.define("jquery.select2",["jquery","require","./select2/core","./select2/defaults"],function(a,b,c,d){if(b("jquery.mousewheel"),null==a.fn.select2){var e=["open","close","destroy"];a.fn.select2=function(b){if(b=b||{},"object"==typeof b)return this.each(function(){{var d=a.extend({},b,!0);new c(a(this),d)}}),this;if("string"==typeof b){var d=this.data("select2");null==d&&window.console&&console.error&&console.error("The select2('"+b+"') method was called on an element that is not using Select2.");var f=Array.prototype.slice.call(arguments,1),g=d[b](f);return a.inArray(b,e)>-1?this:g}throw new Error("Invalid arguments for Select2: "+b)}}return null==a.fn.select2.defaults&&(a.fn.select2.defaults=d),c}),b.define("jquery.mousewheel",["jquery"],function(a){return a}),{define:b.define,require:b.require}}(),c=b.require("jquery.select2");return a.fn.select2.amd=b,c});
bulk-delete.php CHANGED
@@ -1,48 +1,39 @@
1
  <?php
2
  /**
3
- Plugin Name: Bulk Delete
4
- Plugin Script: bulk-delete.php
5
- Plugin URI: http://bulkwp.com
6
- Description: Bulk delete users and posts from selected categories, tags, post types, custom taxonomies or by post status like drafts, scheduled posts, revisions etc.
7
- Donate Link: http://sudarmuthu.com/if-you-wanna-thank-me
8
- Version: 5.4.1
9
- License: GPL
10
- Author: Sudar
11
- Author URI: http://sudarmuthu.com/
12
- Text Domain: bulk-delete
13
- Domain Path: languages/
14
-
15
- === RELEASE NOTES ===
16
- Check readme file for full release notes
17
- */
18
-
19
- /** Copyright 2009 Sudar Muthu (email : sudar@sudarmuthu.com)
20
-
21
- This program is free software; you can redistribute it and/or modify
22
- it under the terms of the GNU General Public License, version 2, as
23
- published by the Free Software Foundation.
24
-
25
- This program is distributed in the hope that it will be useful,
26
- but WITHOUT ANY WARRANTY; without even the implied warranty of
27
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
28
- GNU General Public License for more details.
29
-
30
- You should have received a copy of the GNU General Public License
31
- along with this program; if not, write to the Free Software
32
- Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
33
- */
34
-
35
- /**
36
- * @package Bulk_Delete
37
- * @subpackage core
38
  * @author Sudar
39
- * @version 5.4.1
40
  */
41
 
42
- // Exit if accessed directly
43
- if ( ! defined( 'ABSPATH' ) ) exit;
 
 
 
 
 
 
 
 
 
 
 
44
 
45
- if ( ! class_exists( 'Bulk_Delete' ) ) :
46
 
47
  /**
48
  * Main Bulk_Delete class
@@ -50,497 +41,446 @@ if ( ! class_exists( 'Bulk_Delete' ) ) :
50
  * Singleton @since 5.0
51
  */
52
  final class Bulk_Delete {
53
- /**
54
- * @var Bulk_Delete The one true Bulk_Delete
55
- * @since 5.0
56
- */
57
- private static $instance;
58
-
59
- // version
60
- const VERSION = '5.4.1';
61
-
62
- // Numeric constants
63
- const MENU_ORDER = '26.9966';
64
-
65
- // page slugs
66
- const POSTS_PAGE_SLUG = 'bulk-delete-posts';
67
- const PAGES_PAGE_SLUG = 'bulk-delete-pages';
68
- const USERS_PAGE_SLUG = 'bulk-delete-users';
69
- const CRON_PAGE_SLUG = 'bulk-delete-cron';
70
- const ADDON_PAGE_SLUG = 'bulk-delete-addon';
71
- const INFO_PAGE_SLUG = 'bulk-delete-info';
72
-
73
- // JS constants
74
- const JS_HANDLE = 'bulk-delete';
75
- const JS_VARIABLE = 'BulkWP';
76
-
77
- // Cron hooks
78
- const CRON_HOOK_CATEGORY = 'do-bulk-delete-cat';
79
- const CRON_HOOK_POST_STATUS = 'do-bulk-delete-post-status';
80
- const CRON_HOOK_TAG = 'do-bulk-delete-tag';
81
- const CRON_HOOK_TAXONOMY = 'do-bulk-delete-taxonomy';
82
- const CRON_HOOK_POST_TYPE = 'do-bulk-delete-post-type';
83
- const CRON_HOOK_CUSTOM_FIELD = 'do-bulk-delete-custom-field';
84
- const CRON_HOOK_TITLE = 'do-bulk-delete-by-title';
85
- const CRON_HOOK_DUPLICATE_TITLE = 'do-bulk-delete-by-duplicate-title';
86
- const CRON_HOOK_POST_BY_ROLE = 'do-bulk-delete-posts-by-role';
87
-
88
- const CRON_HOOK_PAGES_STATUS = 'do-bulk-delete-pages-by-status';
89
-
90
- const CRON_HOOK_USER_ROLE = 'do-bulk-delete-users-by-role';
91
-
92
- // meta boxes for delete posts
93
- const BOX_POST_STATUS = 'bd_by_post_status';
94
- const BOX_CATEGORY = 'bd_by_category';
95
- const BOX_TAG = 'bd_by_tag';
96
- const BOX_TAX = 'bd_by_tax';
97
- const BOX_POST_TYPE = 'bd_by_post_type';
98
- const BOX_URL = 'bd_by_url';
99
- const BOX_POST_REVISION = 'bd_by_post_revision';
100
- const BOX_CUSTOM_FIELD = 'bd_by_custom_field';
101
- const BOX_TITLE = 'bd_by_title';
102
- const BOX_DUPLICATE_TITLE = 'bd_by_duplicate_title';
103
- const BOX_POST_FROM_TRASH = 'bd_posts_from_trash';
104
- const BOX_POST_BY_ROLE = 'bd_post_by_user_role';
105
-
106
- // meta boxes for delete pages
107
- const BOX_PAGE_STATUS = 'bd_by_page_status';
108
- const BOX_PAGE_FROM_TRASH = 'bd_pages_from_trash';
109
-
110
- // meta boxes for delete users
111
- const BOX_USERS = 'bdu_by_users';
112
-
113
- // Settings constants
114
- const SETTING_OPTION_GROUP = 'bd_settings';
115
- const SETTING_OPTION_NAME = 'bd_licenses';
116
- const SETTING_SECTION_ID = 'bd_license_section';
117
-
118
- // Transient keys
119
- const LICENSE_CACHE_KEY_PREFIX = 'bd-license_';
120
-
121
- // path variables
122
- // Ideally these should be constants, but because of PHP's limitations, these are static variables
123
- static $PLUGIN_DIR;
124
- static $PLUGIN_URL;
125
- static $PLUGIN_FILE;
126
-
127
- /**
128
- * Main Bulk_Delete Instance
129
- *
130
- * Insures that only one instance of Bulk_Delete exists in memory at any one
131
- * time. Also prevents needing to define globals all over the place.
132
- *
133
- * @since 5.0
134
- * @static
135
- * @staticvar array $instance
136
- * @uses Bulk_Delete::setup_paths() Setup the plugin paths
137
- * @uses Bulk_Delete::includes() Include the required files
138
- * @uses Bulk_Delete::load_textdomain() Load text domain for translation
139
- * @uses Bulk_Delete::setup_actions() Setup the hooks and actions
140
- * @see BULK_DELETE()
141
- * @return The one true BULK_DELETE
142
- */
143
- public static function instance() {
144
- if ( ! isset( self::$instance ) && ! ( self::$instance instanceof Bulk_Delete ) ) {
145
- self::$instance = new Bulk_Delete;
146
- self::$instance->setup_paths();
147
- self::$instance->includes();
148
- self::$instance->load_textdomain();
149
- self::$instance->setup_actions();
150
- }
151
- return self::$instance;
152
- }
153
-
154
- /**
155
- * Throw error on object clone
156
- *
157
- * The whole idea of the singleton design pattern is that there is a single
158
- * object therefore, we don't want the object to be cloned.
159
- *
160
- * @since 5.0
161
- * @access protected
162
- * @return void
163
- */
164
- public function __clone() {
165
- // Cloning instances of the class is forbidden
166
- _doing_it_wrong( __FUNCTION__, __( 'Cheatin&#8217; huh?', 'bulk-delete' ), '5.0' );
167
- }
168
-
169
- /**
170
- * Disable unserializing of the class
171
- *
172
- * @since 5.0
173
- * @access protected
174
- * @return void
175
- */
176
- public function __wakeup() {
177
- // Unserializing instances of the class is forbidden
178
- _doing_it_wrong( __FUNCTION__, __( 'Cheatin&#8217; huh?', 'bulk-delete' ), '5.0' );
179
- }
180
-
181
- /**
182
- * Setup plugin constants
183
- *
184
- * @access private
185
- * @since 5.0
186
- * @return void
187
- */
188
- private function setup_paths() {
189
- // Plugin Folder Path
190
- self::$PLUGIN_DIR = plugin_dir_path( __FILE__ );
191
-
192
- // Plugin Folder URL
193
- self::$PLUGIN_URL = plugin_dir_url( __FILE__ );
194
-
195
- // Plugin Root File
196
- self::$PLUGIN_FILE = __FILE__;
197
- }
198
-
199
- /**
200
- * Include required files
201
- *
202
- * @access private
203
- * @since 5.0
204
- * @return void
205
- */
206
- private function includes() {
207
- require_once self::$PLUGIN_DIR . '/include/class-bulk-delete-posts.php';
208
- require_once self::$PLUGIN_DIR . '/include/class-bulk-delete-pages.php';
209
- require_once self::$PLUGIN_DIR . '/include/class-bulk-delete-users.php';
210
-
211
- require_once self::$PLUGIN_DIR . '/include/meta/class-bulk-delete-meta.php';
212
- require_once self::$PLUGIN_DIR . '/include/meta/class-bulk-delete-post-meta.php';
213
- require_once self::$PLUGIN_DIR . '/include/meta/class-bulk-delete-comment-meta.php';
214
- require_once self::$PLUGIN_DIR . '/include/meta/class-bulk-delete-user-meta.php';
215
-
216
- require_once self::$PLUGIN_DIR . '/include/misc/class-bulk-delete-misc.php';
217
- require_once self::$PLUGIN_DIR . '/include/misc/class-bulk-delete-jetpack-contact-form-messages.php';
218
-
219
- require_once self::$PLUGIN_DIR . '/include/settings/class-bd-settings-page.php';
220
- require_once self::$PLUGIN_DIR . '/include/settings/setting-helpers.php';
221
-
222
- require_once self::$PLUGIN_DIR . '/include/class-bulk-delete-system-info.php';
223
- require_once self::$PLUGIN_DIR . '/include/class-bulk-delete-util.php';
224
- require_once self::$PLUGIN_DIR . '/include/class-bd-license.php';
225
- require_once self::$PLUGIN_DIR . '/include/class-bd-license-handler.php';
226
- require_once self::$PLUGIN_DIR . '/include/class-bd-edd-api-wrapper.php';
227
- require_once self::$PLUGIN_DIR . '/include/class-bd-settings.php';
228
- require_once self::$PLUGIN_DIR . '/include/admin-ui.php';
229
- require_once self::$PLUGIN_DIR . '/include/class-bulk-delete-help-screen.php';
230
- }
231
-
232
- /**
233
- * Loads the plugin language files
234
- *
235
- * @since 5.0
236
- */
237
- public function load_textdomain() {
238
- // Load localization domain
239
- $this->translations = dirname( plugin_basename( self::$PLUGIN_FILE ) ) . '/languages/';
240
- load_plugin_textdomain( 'bulk-delete', false, $this->translations );
241
- }
242
-
243
- /**
244
- * Loads the plugin's actions and hooks
245
- *
246
- * @access private
247
- * @since 5.0
248
- * @return void
249
- */
250
- private function setup_actions() {
251
- add_action( 'admin_menu', array( &$this, 'add_menu' ) );
252
- add_action( 'admin_init', array( &$this, 'request_handler' ) );
253
- add_action( 'bd_pre_bulk_action', array( &$this, 'increase_timeout' ), 9 );
254
- add_action( 'bd_before_scheduler', array( &$this, 'increase_timeout' ), 9 );
255
- }
256
-
257
- /**
258
- * Add navigation menu
259
- */
260
- function add_menu() {
261
- add_menu_page( __( 'Bulk WP', 'bulk-delete' ), __( 'Bulk WP', 'bulk-delete' ), 'manage_options', self::POSTS_PAGE_SLUG, array( &$this, 'display_posts_page' ), 'dashicons-trash', self::MENU_ORDER );
262
-
263
- $this->posts_page = add_submenu_page( self::POSTS_PAGE_SLUG, __( 'Bulk Delete Posts', 'bulk-delete' ), __( 'Bulk Delete Posts', 'bulk-delete' ), 'delete_posts', self::POSTS_PAGE_SLUG, array( &$this, 'display_posts_page' ) );
264
- $this->pages_page = add_submenu_page( self::POSTS_PAGE_SLUG, __( 'Bulk Delete Pages', 'bulk-delete' ), __( 'Bulk Delete Pages', 'bulk-delete' ), 'delete_pages', self::PAGES_PAGE_SLUG, array( &$this, 'display_pages_page' ) );
265
- $this->users_page = add_submenu_page( self::POSTS_PAGE_SLUG, __( 'Bulk Delete Users', 'bulk-delete' ), __( 'Bulk Delete Users', 'bulk-delete' ), 'delete_users', self::USERS_PAGE_SLUG, array( &$this, 'display_users_page' ) );
266
-
267
- /**
268
- * Runs just after adding all *delete* menu items to Bulk WP main menu
269
- *
270
- * This action is primarily for adding extra *delete* menu items to the Bulk WP main menu.
271
- *
272
- * @since 5.3
273
- */
274
- do_action( 'bd_after_primary_menus' );
275
-
276
- /**
277
- * Runs just before adding non-action menu items to Bulk WP main menu
278
- *
279
- * This action is primarily for adding extra menu items before non-action menu items to the Bulk WP main menu.
280
- *
281
- * @since 5.3
282
- */
283
- do_action( 'bd_before_secondary_menus' );
284
-
285
- $this->cron_page = add_submenu_page( self::POSTS_PAGE_SLUG, __( 'Bulk Delete Schedules' , 'bulk-delete' ), __( 'Scheduled Jobs', 'bulk-delete' ), 'delete_posts' , self::CRON_PAGE_SLUG , array( &$this , 'display_cron_page' ) );
286
- $this->addon_page = add_submenu_page( self::POSTS_PAGE_SLUG, __( 'Addon Licenses' , 'bulk-delete' ), __( 'Addon Licenses', 'bulk-delete' ), 'activate_plugins', self::ADDON_PAGE_SLUG, array( 'BD_License' , 'display_addon_page' ) );
287
- $this->info_page = add_submenu_page( self::POSTS_PAGE_SLUG, __( 'Bulk Delete System Info', 'bulk-delete' ), __( 'System Info' , 'bulk-delete' ), 'manage_options' , self::INFO_PAGE_SLUG , array( 'Bulk_Delete_System_Info', 'display_system_info' ) );
288
-
289
- /**
290
- * Runs just after adding all menu items to Bulk WP main menu
291
- *
292
- * This action is primarily for adding extra menu items to the Bulk WP main menu.
293
- *
294
- * @since 5.3
295
- */
296
- do_action( 'bd_after_all_menus' );
297
-
298
- // enqueue JavaScript
299
- add_action( 'admin_print_scripts-' . $this->posts_page, array( &$this, 'add_script') );
300
- add_action( 'admin_print_scripts-' . $this->pages_page, array( &$this, 'add_script') );
301
- add_action( 'admin_print_scripts-' . $this->users_page, array( &$this, 'add_script') );
302
-
303
- // delete posts page
304
- add_action( "load-{$this->posts_page}", array( &$this, 'add_delete_posts_settings_panel' ) );
305
- add_action( "add_meta_boxes_{$this->posts_page}", array( &$this, 'add_delete_posts_meta_boxes' ) );
306
-
307
- // delete pages page
308
- add_action( "load-{$this->pages_page}", array( &$this, 'add_delete_pages_settings_panel' ) );
309
- add_action( "add_meta_boxes_{$this->pages_page}", array( &$this, 'add_delete_pages_meta_boxes' ) );
310
-
311
- // delete users page
312
- add_action( "load-{$this->users_page}", array( &$this, 'add_delete_users_settings_panel' ) );
313
- add_action( "add_meta_boxes_{$this->users_page}", array( &$this, 'add_delete_users_meta_boxes' ) );
314
  }
315
 
316
- /**
317
- * Add settings Panel for delete posts page
318
- */
319
- function add_delete_posts_settings_panel() {
320
-
321
- /**
322
- * Add contextual help for admin screens
323
- *
324
- * @since 5.1
325
- */
326
- do_action( 'bd_add_contextual_help', $this->posts_page );
327
-
328
- /* Trigger the add_meta_boxes hooks to allow meta boxes to be added */
329
- do_action('add_meta_boxes_' . $this->posts_page, null);
330
-
331
- /* Enqueue WordPress' script for handling the meta boxes */
332
- wp_enqueue_script('postbox');
333
- }
334
-
335
- /**
336
- * Register meta boxes for delete posts page
337
- */
338
- function add_delete_posts_meta_boxes() {
339
- add_meta_box( self::BOX_POST_STATUS , __( 'By Post Status' , 'bulk-delete' ) , 'Bulk_Delete_Posts::render_delete_posts_by_status_box' , $this->posts_page , 'advanced' );
340
- add_meta_box( self::BOX_CATEGORY , __( 'By Category' , 'bulk-delete' ) , 'Bulk_Delete_Posts::render_delete_posts_by_category_box' , $this->posts_page , 'advanced' );
341
- add_meta_box( self::BOX_TAG , __( 'By Tag' , 'bulk-delete' ) , 'Bulk_Delete_Posts::render_delete_posts_by_tag_box' , $this->posts_page , 'advanced' );
342
- add_meta_box( self::BOX_TAX , __( 'By Custom Taxonomy' , 'bulk-delete' ) , 'Bulk_Delete_Posts::render_delete_posts_by_taxonomy_box' , $this->posts_page , 'advanced' );
343
- add_meta_box( self::BOX_POST_TYPE , __( 'By Custom Post Types' , 'bulk-delete' ) , 'Bulk_Delete_Posts::render_delete_posts_by_post_type_box' , $this->posts_page , 'advanced' );
344
- add_meta_box( self::BOX_URL , __( 'By URL' , 'bulk-delete' ) , 'Bulk_Delete_Posts::render_delete_posts_by_url_box' , $this->posts_page , 'advanced' );
345
- add_meta_box( self::BOX_POST_REVISION , __( 'By Post Revision' , 'bulk-delete' ) , 'Bulk_Delete_Posts::render_posts_by_revision_box' , $this->posts_page , 'advanced' );
346
- add_meta_box( self::BOX_CUSTOM_FIELD , __( 'By Custom Field' , 'bulk-delete' ) , 'Bulk_Delete_Posts::render_delete_posts_by_custom_field_box' , $this->posts_page , 'advanced' );
347
- add_meta_box( self::BOX_TITLE , __( 'By Title' , 'bulk-delete' ) , 'Bulk_Delete_Posts::render_delete_posts_by_title_box' , $this->posts_page , 'advanced' );
348
- add_meta_box( self::BOX_DUPLICATE_TITLE , __( 'By Duplicate Title' , 'bulk-delete' ) , 'Bulk_Delete_Posts::render_delete_posts_by_duplicate_title_box' , $this->posts_page , 'advanced' );
349
- add_meta_box( self::BOX_POST_BY_ROLE , __( 'By User Role' , 'bulk-delete' ) , 'Bulk_Delete_Posts::render_delete_posts_by_user_role_box' , $this->posts_page , 'advanced' );
350
- add_meta_box( self::BOX_POST_FROM_TRASH , __( 'Posts in Trash' , 'bulk-delete' ) , 'Bulk_Delete_Posts::render_delete_posts_from_trash' , $this->posts_page , 'advanced' );
351
-
352
- /**
353
- * Add meta box in delete posts page
354
- * This hook can be used for adding additional meta boxes in delete posts page
355
- *
356
- * @since 5.3
357
- */
358
- do_action( 'bd_add_meta_box_for_posts' );
359
- }
360
-
361
- /**
362
- * Setup settings panel for delete pages page
363
- *
364
- * @since 5.0
365
- */
366
- function add_delete_pages_settings_panel() {
367
-
368
- /**
369
- * Add contextual help for admin screens
370
- *
371
- * @since 5.1
372
- */
373
- do_action( 'bd_add_contextual_help', $this->pages_page );
374
-
375
- /* Trigger the add_meta_boxes hooks to allow meta boxes to be added */
376
- do_action('add_meta_boxes_' . $this->pages_page, null);
377
-
378
- /* Enqueue WordPress' script for handling the meta boxes */
379
- wp_enqueue_script('postbox');
380
- }
381
-
382
- /**
383
- * Register meta boxes for delete pages page
384
- *
385
- * @since 5.0
386
- */
387
- function add_delete_pages_meta_boxes() {
388
- add_meta_box( self::BOX_PAGE_STATUS , __( 'By Page status' , 'bulk-delete' ) , 'Bulk_Delete_Pages::render_delete_pages_by_status_box' , $this->pages_page , 'advanced' );
389
- add_meta_box( self::BOX_PAGE_FROM_TRASH , __( 'Pages in Trash' , 'bulk-delete' ) , 'Bulk_Delete_Pages::render_delete_pages_from_trash' , $this->pages_page , 'advanced' );
390
-
391
- /**
392
- * Add meta box in delete pages page
393
- * This hook can be used for adding additional meta boxes in delete pages page
394
- *
395
- * @since 5.3
396
- */
397
- do_action( 'bd_add_meta_box_for_pages' );
398
- }
399
-
400
- /**
401
- * Add settings Panel for delete users page
402
- */
403
- function add_delete_users_settings_panel() {
404
-
405
- /**
406
- * Add contextual help for admin screens
407
- *
408
- * @since 5.1
409
- */
410
- do_action( 'bd_add_contextual_help', $this->users_page );
411
-
412
- /* Trigger the add_meta_boxes hooks to allow meta boxes to be added */
413
- do_action('add_meta_boxes_' . $this->users_page, null);
414
-
415
- /* Enqueue WordPress' script for handling the meta boxes */
416
- wp_enqueue_script('postbox');
417
- }
418
-
419
- /**
420
- * Register meta boxes for delete users page
421
- */
422
- function add_delete_users_meta_boxes() {
423
- add_meta_box( self::BOX_USERS, __( 'By User Role', 'bulk-delete' ), 'Bulk_Delete_Users::render_delete_users_by_role_box', $this->users_page, 'advanced' );
424
-
425
- /**
426
- * Add meta box in delete users page
427
- * This hook can be used for adding additional meta boxes in delete users page
428
- *
429
- * @since 5.3
430
- */
431
- do_action( 'bd_add_meta_box_for_users' );
432
- }
433
-
434
- /**
435
- * Enqueue JavaScript
436
- */
437
- function add_script() {
438
- global $wp_scripts;
439
-
440
- // uses code from http://trentrichardson.com/examples/timepicker/
441
- wp_enqueue_script( 'jquery-ui-timepicker', plugins_url( '/js/jquery-ui-timepicker.js', __FILE__ ), array( 'jquery-ui-slider', 'jquery-ui-datepicker' ), '1.4', true );
442
- wp_enqueue_script( self::JS_HANDLE, plugins_url('/js/bulk-delete.js', __FILE__), array('jquery-ui-timepicker'), self::VERSION, TRUE);
443
-
444
- $ui = $wp_scripts->query('jquery-ui-core');
445
-
446
- $url = "http://ajax.googleapis.com/ajax/libs/jqueryui/{$ui->ver}/themes/smoothness/jquery-ui.css";
447
- wp_enqueue_style('jquery-ui-smoothness', $url, false, $ui->ver);
448
- wp_enqueue_style('jquery-ui-timepicker', plugins_url('/style/jquery-ui-timepicker.css', __FILE__), array(), '1.1.1');
449
-
450
- /**
451
- * Filter JavaScript array
452
- *
453
- * This filter can be used to extend the array that is passed to JavaScript
454
- *
455
- * @since 5.4
456
- */
457
- $translation_array = apply_filters( 'bd_javascript_array', array(
458
- 'msg' => array(),
459
- 'validators' => array(),
460
- 'dt_iterators' => array(),
461
- 'pre_action_msg' => array(),
462
- 'error_msg' => array()
463
- ) );
464
- wp_localize_script( self::JS_HANDLE, self::JS_VARIABLE, $translation_array );
465
- }
466
-
467
- /**
468
- * Show the delete posts page.
469
- *
470
- * @Todo Move this function to Bulk_Delete_Posts class
471
- */
472
- function display_posts_page() {
473
- ?>
474
- <div class="wrap">
475
- <h2><?php _e('Bulk Delete Posts', 'bulk-delete');?></h2>
476
- <?php settings_errors(); ?>
477
 
478
- <form method = "post">
479
- <?php
480
- // nonce for bulk delete
481
- wp_nonce_field( 'sm-bulk-delete-posts', 'sm-bulk-delete-posts-nonce' );
 
 
 
 
 
 
 
482
 
483
- /* Used to save closed meta boxes and their order */
484
- wp_nonce_field( 'meta-box-order', 'meta-box-order-nonce', false );
485
- wp_nonce_field( 'closedpostboxes', 'closedpostboxesnonce', false );
486
- ?>
487
- <div id = "poststuff">
488
- <div id="post-body" class="metabox-holder columns-2">
 
 
 
 
 
 
 
 
 
 
 
489
 
490
- <div class="updated" >
491
- <p><strong><?php _e( 'WARNING: Posts deleted once cannot be retrieved back. Use with caution.', 'bulk-delete' ); ?></strong></p>
492
- </div>
 
 
 
 
 
 
 
493
 
494
- <div id="postbox-container-1" class="postbox-container">
495
- <iframe frameBorder="0" height = "1500" src = "http://sudarmuthu.com/projects/wordpress/bulk-delete/sidebar.php?color=<?php echo get_user_option( 'admin_color' ); ?>&version=<?php echo self::VERSION; ?>"></iframe>
496
- </div>
497
 
498
- <div id="postbox-container-2" class="postbox-container">
499
- <?php do_meta_boxes( '', 'advanced', null ); ?>
500
- </div> <!-- #postbox-container-2 -->
501
 
502
- </div> <!-- #post-body -->
503
- </div><!-- #poststuff -->
504
- </form>
505
- </div><!-- .wrap -->
506
 
507
- <?php
508
- /**
509
- * Runs just before displaying the footer text in the "Bulk Delete Posts" admin page.
510
- *
511
- * This action is primarily for adding extra content in the footer of "Bulk Delete Posts" admin page.
512
- *
513
- * @since 5.0
514
- */
515
- do_action( 'bd_admin_footer_posts_page' );
516
- }
517
-
518
- /**
519
- * Display the delete pages page
520
- *
521
- * @Todo Move this function to Bulk_Delete_Pages class
522
- * @since 5.0
523
- */
524
- function display_pages_page() {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
525
  ?>
526
  <div class="wrap">
527
- <h2><?php _e( 'Bulk Delete Pages', 'bulk-delete' );?></h2>
528
  <?php settings_errors(); ?>
529
 
530
  <form method = "post">
531
  <?php
532
- // nonce for bulk delete
533
- wp_nonce_field( 'sm-bulk-delete-pages', 'sm-bulk-delete-pages-nonce' );
534
 
535
- /* Used to save closed meta boxes and their order */
536
- wp_nonce_field( 'meta-box-order', 'meta-box-order-nonce', false );
537
- wp_nonce_field( 'closedpostboxes', 'closedpostboxesnonce', false );
538
  ?>
539
  <div id = "poststuff">
540
  <div id="post-body" class="metabox-holder columns-2">
541
 
542
- <div class = "updated">
543
- <p><strong><?php _e( 'WARNING: Pages deleted once cannot be retrieved back. Use with caution.', 'bulk-delete' ); ?></strong></p>
544
  </div>
545
 
546
  <div id="postbox-container-1" class="postbox-container">
@@ -557,40 +497,42 @@ final class Bulk_Delete {
557
  </div><!-- .wrap -->
558
 
559
  <?php
560
- /**
561
- * Runs just before displaying the footer text in the "Bulk Delete Pages" admin page.
562
- *
563
- * This action is primarily for adding extra content in the footer of "Bulk Delete Pages" admin page.
564
- *
565
- * @since 5.0
566
- */
567
- do_action( 'bd_admin_footer_pages_page' );
568
- }
569
-
570
- /**
571
- * Display bulk delete users page
572
- * @Todo Move this function to Bulk_Delete_Users class
573
- */
574
- function display_users_page() {
 
 
575
  ?>
576
  <div class="wrap">
577
- <h2><?php _e('Bulk Delete Users', 'bulk-delete');?></h2>
578
  <?php settings_errors(); ?>
579
 
580
  <form method = "post">
581
  <?php
582
- // nonce for bulk delete
583
- wp_nonce_field( 'sm-bulk-delete-users', 'sm-bulk-delete-users-nonce' );
584
 
585
- /* Used to save closed meta boxes and their order */
586
- wp_nonce_field( 'meta-box-order', 'meta-box-order-nonce', false );
587
- wp_nonce_field( 'closedpostboxes', 'closedpostboxesnonce', false );
588
  ?>
589
  <div id = "poststuff">
590
  <div id="post-body" class="metabox-holder columns-2">
591
 
592
- <div class = "updated">
593
- <p><strong><?php _e( 'WARNING: Users deleted once cannot be retrieved back. Use with caution.', 'bulk-delete' ); ?></strong></p>
594
  </div>
595
 
596
  <div id="postbox-container-1" class="postbox-container">
@@ -607,111 +549,123 @@ final class Bulk_Delete {
607
  </div><!-- .wrap -->
608
 
609
  <?php
610
- /**
611
- * Runs just before displaying the footer text in the "Bulk Delete Users" admin page.
612
- *
613
- * This action is primarily for adding extra content in the footer of "Bulk Delete Users" admin page.
614
- *
615
- * @since 5.0
616
- */
617
- do_action( 'bd_admin_footer_users_page' );
618
- }
619
-
620
- /**
621
- * Display the schedule page
622
- */
623
- function display_cron_page() {
624
-
625
- if(!class_exists('WP_List_Table')){
626
- require_once( ABSPATH . WPINC . '/class-wp-list-table.php' );
627
- }
628
-
629
- if ( !class_exists( 'Cron_List_Table' ) ) {
630
- require_once self::$PLUGIN_DIR . '/include/class-cron-list-table.php';
631
- }
632
-
633
- //Prepare Table of elements
634
- $cron_list_table = new Cron_List_Table();
635
- $cron_list_table->prepare_items();
636
  ?>
637
  <div class="wrap">
638
- <h2><?php _e('Bulk Delete Schedules', 'bulk-delete');?></h2>
639
  <?php settings_errors(); ?>
640
  <?php
641
- //Table of elements
642
- $cron_list_table->display();
 
643
  ?>
644
  </div>
645
  <?php
646
- /**
647
- * Runs just before displaying the footer text in the "Schedules" admin page.
648
- *
649
- * This action is primarily for adding extra content in the footer of "Schedules" admin page.
650
- *
651
- * @since 5.0
652
- */
653
- do_action( 'bd_admin_footer_cron_page' );
654
- }
655
-
656
- /**
657
- * Handle both POST and GET requests
658
- *
659
- * This method automatically triggers all the actions
660
- */
661
- public function request_handler() {
662
-
663
- if ( isset( $_POST['bd_action'] ) ) {
664
- if ( 'delete_pages_' === substr( $_POST['bd_action'], 0, strlen('delete_pages_') ) &&
665
- ! check_admin_referer( 'sm-bulk-delete-pages', 'sm-bulk-delete-pages-nonce' ) ) {
666
- return FALSE;
667
- }
668
-
669
- if ( 'delete_posts_' === substr( $_POST['bd_action'], 0, strlen('delete_posts_') ) &&
670
- ! check_admin_referer( 'sm-bulk-delete-posts', 'sm-bulk-delete-posts-nonce' ) ) {
671
- return FALSE;
672
- }
673
-
674
- if ( 'delete_users_' === substr( $_POST['bd_action'], 0, strlen('delete_users_') ) &&
675
- ! check_admin_referer( 'sm-bulk-delete-users', 'sm-bulk-delete-users-nonce' ) ) {
676
- return FALSE;
677
- }
678
-
679
- if ( 'delete_meta_' === substr( $_POST['bd_action'], 0, strlen('delete_meta_' ) ) &&
680
- ! check_admin_referer( 'sm-bulk-delete-meta', 'sm-bulk-delete-meta-nonce' ) ) {
681
- return FALSE;
682
- }
683
-
684
- /**
685
- * Before performing a bulk action
686
- *
687
- * This hook is for doing actions just before performing any bulk operation
688
- *
689
- * @since 5.4
690
- */
691
- do_action( 'bd_pre_bulk_action' );
692
- do_action( 'bd_' . $_POST['bd_action'], $_POST );
693
- }
694
-
695
- if ( isset( $_GET['bd_action'] ) ) {
696
- do_action( 'bd_' . $_GET['bd_action'], $_GET );
697
- }
698
- }
699
-
700
- /**
701
- * Increase PHP timeout.
702
- *
703
- * This is to prevent bulk operations from timing out
704
- *
705
- * @since 5.4
706
- */
707
- public function increase_timeout() {
708
- if ( ! ini_get( 'safe_mode' ) ) {
709
- @set_time_limit( 0 );
710
- }
711
- }
 
 
 
 
 
 
 
 
 
 
 
 
712
  }
713
 
714
- endif; // End if class_exists check
715
 
716
  /**
717
  * The main function responsible for returning the one true Bulk_Delete
@@ -720,10 +674,10 @@ endif; // End if class_exists check
720
  * Use this function like you would a global variable, except without needing
721
  * to declare the global.
722
  *
723
- * Example: <?php $bulk_delete = BULK_DELETE(); ?>
724
  *
725
  * @since 5.0
726
- * @return object The one true Bulk_Delete Instance
727
  */
728
  function BULK_DELETE() {
729
  return Bulk_Delete::instance();
1
  <?php
2
  /**
3
+ * Plugin Name: Bulk Delete
4
+ * Plugin Script: bulk-delete.php
5
+ * Plugin URI: http://bulkwp.com
6
+ * Description: Bulk delete users and posts from selected categories, tags, post types, custom taxonomies or by post status like drafts, scheduled posts, revisions etc.
7
+ * Donate Link: http://sudarmuthu.com/if-you-wanna-thank-me
8
+ * Version: 5.5
9
+ * License: GPL
10
+ * Author: Sudar
11
+ * Author URI: http://sudarmuthu.com/
12
+ * Text Domain: bulk-delete
13
+ * Domain Path: languages/
14
+ * === RELEASE NOTES ===
15
+ * Check readme file for full release notes
16
+ *
17
+ * @version 5.5
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
18
  * @author Sudar
19
+ * @package BulkDelete
20
  */
21
 
22
+ /**
23
+ * Copyright 2009 Sudar Muthu (email : sudar@sudarmuthu.com)
24
+ * This program is free software; you can redistribute it and/or modify
25
+ * it under the terms of the GNU General Public License, version 2, as
26
+ * published by the Free Software Foundation.
27
+ * This program is distributed in the hope that it will be useful,
28
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
29
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
30
+ * GNU General Public License for more details.
31
+ * You should have received a copy of the GNU General Public License
32
+ * along with this program; if not, write to the Free Software
33
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
34
+ */
35
 
36
+ defined( 'ABSPATH' ) || exit; // Exit if accessed directly
37
 
38
  /**
39
  * Main Bulk_Delete class
41
  * Singleton @since 5.0
42
  */
43
  final class Bulk_Delete {
44
+
45
+ /**
46
+ * @var Bulk_Delete The one true Bulk_Delete
47
+ * @since 5.0
48
+ */
49
+ private static $instance;
50
+
51
+ // version
52
+ const VERSION = '5.5';
53
+
54
+ // Numeric constants
55
+ const MENU_ORDER = '26.9966';
56
+
57
+ // page slugs
58
+ const POSTS_PAGE_SLUG = 'bulk-delete-posts';
59
+ const PAGES_PAGE_SLUG = 'bulk-delete-pages';
60
+ const CRON_PAGE_SLUG = 'bulk-delete-cron';
61
+ const ADDON_PAGE_SLUG = 'bulk-delete-addon';
62
+ const INFO_PAGE_SLUG = 'bulk-delete-info';
63
+
64
+ // JS constants
65
+ const JS_HANDLE = 'bulk-delete';
66
+ const JS_VARIABLE = 'BulkWP';
67
+
68
+ const CSS_HANDLE = 'bulk-delete';
69
+
70
+ // Cron hooks
71
+ const CRON_HOOK_CATEGORY = 'do-bulk-delete-cat';
72
+ const CRON_HOOK_POST_STATUS = 'do-bulk-delete-post-status';
73
+ const CRON_HOOK_TAG = 'do-bulk-delete-tag';
74
+ const CRON_HOOK_TAXONOMY = 'do-bulk-delete-taxonomy';
75
+ const CRON_HOOK_POST_TYPE = 'do-bulk-delete-post-type';
76
+ const CRON_HOOK_CUSTOM_FIELD = 'do-bulk-delete-custom-field';
77
+ const CRON_HOOK_TITLE = 'do-bulk-delete-by-title';
78
+ const CRON_HOOK_DUPLICATE_TITLE = 'do-bulk-delete-by-duplicate-title';
79
+ const CRON_HOOK_POST_BY_ROLE = 'do-bulk-delete-posts-by-role';
80
+
81
+ const CRON_HOOK_PAGES_STATUS = 'do-bulk-delete-pages-by-status';
82
+
83
+ // meta boxes for delete posts
84
+ const BOX_POST_STATUS = 'bd_by_post_status';
85
+ const BOX_CATEGORY = 'bd_by_category';
86
+ const BOX_TAG = 'bd_by_tag';
87
+ const BOX_TAX = 'bd_by_tax';
88
+ const BOX_POST_TYPE = 'bd_by_post_type';
89
+ const BOX_URL = 'bd_by_url';
90
+ const BOX_POST_REVISION = 'bd_by_post_revision';
91
+ const BOX_CUSTOM_FIELD = 'bd_by_custom_field';
92
+ const BOX_TITLE = 'bd_by_title';
93
+ const BOX_DUPLICATE_TITLE = 'bd_by_duplicate_title';
94
+ const BOX_POST_FROM_TRASH = 'bd_posts_from_trash';
95
+ const BOX_POST_BY_ROLE = 'bd_post_by_user_role';
96
+
97
+ // meta boxes for delete pages
98
+ const BOX_PAGE_STATUS = 'bd_by_page_status';
99
+ const BOX_PAGE_FROM_TRASH = 'bd_pages_from_trash';
100
+
101
+ // Settings constants
102
+ const SETTING_OPTION_GROUP = 'bd_settings';
103
+ const SETTING_OPTION_NAME = 'bd_licenses';
104
+ const SETTING_SECTION_ID = 'bd_license_section';
105
+
106
+ // Transient keys
107
+ const LICENSE_CACHE_KEY_PREFIX = 'bd-license_';
108
+
109
+ // path variables
110
+ // Ideally these should be constants, but because of PHP's limitations, these are static variables
111
+ public static $PLUGIN_DIR;
112
+ public static $PLUGIN_URL;
113
+ public static $PLUGIN_FILE;
114
+
115
+ // Instance variables
116
+ public $translations;
117
+ public $posts_page;
118
+ public $pages_page;
119
+ public $cron_page;
120
+ public $addon_page;
121
+ public $info_page;
122
+ public $settings_page;
123
+ public $meta_page;
124
+ public $misc_page;
125
+ public $display_activate_license_form = false;
126
+
127
+ // Deprecated.
128
+ // Will be removed in v6.0
129
+ const CRON_HOOK_USER_ROLE = 'do-bulk-delete-users-by-role';
130
+ public $users_page;
131
+
132
+ /**
133
+ * Main Bulk_Delete Instance
134
+ *
135
+ * Insures that only one instance of Bulk_Delete exists in memory at any one
136
+ * time. Also prevents needing to define globals all over the place.
137
+ *
138
+ * @since 5.0
139
+ * @static
140
+ * @staticvar array $instance
141
+ * @see BULK_DELETE()
142
+ * @uses Bulk_Delete::setup_paths() Setup the plugin paths
143
+ * @uses Bulk_Delete::includes() Include the required files
144
+ * @uses Bulk_Delete::load_textdomain() Load text domain for translation
145
+ * @uses Bulk_Delete::setup_actions() Setup the hooks and actions
146
+ * @return Bulk_Delete The one true instance of Bulk_Delete
147
+ */
148
+ public static function instance() {
149
+ if ( ! isset( self::$instance ) && ! ( self::$instance instanceof Bulk_Delete ) ) {
150
+ self::$instance = new Bulk_Delete;
151
+ self::$instance->setup_paths();
152
+ self::$instance->includes();
153
+ self::$instance->load_textdomain();
154
+ self::$instance->setup_actions();
155
+ }
156
+ return self::$instance;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
157
  }
158
 
159
+ /**
160
+ * Throw error on object clone
161
+ *
162
+ * The whole idea of the singleton design pattern is that there is a single
163
+ * object therefore, we don't want the object to be cloned.
164
+ *
165
+ * @since 5.0
166
+ * @access protected
167
+ * @return void
168
+ */
169
+ public function __clone() {
170
+ // Cloning instances of the class is forbidden
171
+ _doing_it_wrong( __FUNCTION__, __( 'Cheatin&#8217; huh?', 'bulk-delete' ), '5.0' );
172
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
173
 
174
+ /**
175
+ * Disable unserializing of the class
176
+ *
177
+ * @since 5.0
178
+ * @access protected
179
+ * @return void
180
+ */
181
+ public function __wakeup() {
182
+ // Unserializing instances of the class is forbidden
183
+ _doing_it_wrong( __FUNCTION__, __( 'Cheatin&#8217; huh?', 'bulk-delete' ), '5.0' );
184
+ }
185
 
186
+ /**
187
+ * Setup plugin constants
188
+ *
189
+ * @access private
190
+ * @since 5.0
191
+ * @return void
192
+ */
193
+ private function setup_paths() {
194
+ // Plugin Folder Path
195
+ self::$PLUGIN_DIR = plugin_dir_path( __FILE__ );
196
+
197
+ // Plugin Folder URL
198
+ self::$PLUGIN_URL = plugin_dir_url( __FILE__ );
199
+
200
+ // Plugin Root File
201
+ self::$PLUGIN_FILE = __FILE__;
202
+ }
203
 
204
+ /**
205
+ * Include required files
206
+ *
207
+ * @access private
208
+ * @since 5.0
209
+ * @return void
210
+ */
211
+ private function includes() {
212
+ require_once self::$PLUGIN_DIR . '/include/base/class-bd-meta-box-module.php';
213
+ require_once self::$PLUGIN_DIR . '/include/base/class-bd-page.php';
214
 
215
+ require_once self::$PLUGIN_DIR . '/include/ui/form.php';
 
 
216
 
217
+ require_once self::$PLUGIN_DIR . '/include/posts/class-bulk-delete-posts.php';
218
+ require_once self::$PLUGIN_DIR . '/include/pages/class-bulk-delete-pages.php';
 
219
 
220
+ require_once self::$PLUGIN_DIR . '/include/users/class-bd-users-page.php';
221
+ require_once self::$PLUGIN_DIR . '/include/users/modules/class-bulk-delete-users-by-user-role.php';
222
+ require_once self::$PLUGIN_DIR . '/include/users/modules/class-bulk-delete-users-by-user-meta.php';
 
223
 
224
+ require_once self::$PLUGIN_DIR . '/include/meta/class-bulk-delete-meta.php';
225
+ require_once self::$PLUGIN_DIR . '/include/meta/class-bulk-delete-post-meta.php';
226
+ require_once self::$PLUGIN_DIR . '/include/meta/class-bulk-delete-comment-meta.php';
227
+ require_once self::$PLUGIN_DIR . '/include/meta/class-bulk-delete-user-meta.php';
228
+
229
+ require_once self::$PLUGIN_DIR . '/include/misc/class-bulk-delete-misc.php';
230
+ require_once self::$PLUGIN_DIR . '/include/misc/class-bulk-delete-jetpack-contact-form-messages.php';
231
+
232
+ require_once self::$PLUGIN_DIR . '/include/settings/class-bd-settings-page.php';
233
+ require_once self::$PLUGIN_DIR . '/include/settings/setting-helpers.php';
234
+ require_once self::$PLUGIN_DIR . '/include/settings/class-bd-settings.php';
235
+
236
+ require_once self::$PLUGIN_DIR . '/include/system-info/class-bulk-delete-system-info.php';
237
+
238
+ require_once self::$PLUGIN_DIR . '/include/util/class-bd-util.php';
239
+ require_once self::$PLUGIN_DIR . '/include/util/query.php';
240
+
241
+ require_once self::$PLUGIN_DIR . '/include/compatibility/simple-login-log.php';
242
+
243
+ require_once self::$PLUGIN_DIR . '/include/deprecated/class-bulk-delete-users.php';
244
+ require_once self::$PLUGIN_DIR . '/include/deprecated/deprecated.php';
245
+
246
+ require_once self::$PLUGIN_DIR . '/include/addons/base/class-bd-addon.php';
247
+ require_once self::$PLUGIN_DIR . '/include/addons/base/class-bd-base-addon.php';
248
+ require_once self::$PLUGIN_DIR . '/include/addons/base/class-bd-scheduler-addon.php';
249
+
250
+ require_once self::$PLUGIN_DIR . '/include/addons/addon-list.php';
251
+ require_once self::$PLUGIN_DIR . '/include/addons/posts.php';
252
+ require_once self::$PLUGIN_DIR . '/include/addons/pages.php';
253
+ require_once self::$PLUGIN_DIR . '/include/addons/util.php';
254
+
255
+ require_once self::$PLUGIN_DIR . '/include/license/class-bd-license.php';
256
+ require_once self::$PLUGIN_DIR . '/include/license/class-bd-license-handler.php';
257
+ require_once self::$PLUGIN_DIR . '/include/license/class-bd-edd-api-wrapper.php';
258
+
259
+ require_once self::$PLUGIN_DIR . '/include/ui/admin-ui.php';
260
+ require_once self::$PLUGIN_DIR . '/include/ui/class-bulk-delete-help-screen.php';
261
+ }
262
+
263
+ /**
264
+ * Loads the plugin language files
265
+ *
266
+ * @since 5.0
267
+ */
268
+ public function load_textdomain() {
269
+ // Load localization domain
270
+ $this->translations = dirname( plugin_basename( self::$PLUGIN_FILE ) ) . '/languages/';
271
+ load_plugin_textdomain( 'bulk-delete', false, $this->translations );
272
+ }
273
+
274
+ /**
275
+ * Loads the plugin's actions and hooks
276
+ *
277
+ * @access private
278
+ * @since 5.0
279
+ * @return void
280
+ */
281
+ private function setup_actions() {
282
+ add_action( 'admin_menu', array( $this, 'add_menu' ) );
283
+ add_action( 'admin_init', array( $this, 'request_handler' ) );
284
+ add_action( 'bd_pre_bulk_action', array( $this, 'increase_timeout' ), 9 );
285
+ add_action( 'bd_before_scheduler', array( $this, 'increase_timeout' ), 9 );
286
+ }
287
+
288
+ /**
289
+ * Add navigation menu
290
+ */
291
+ public function add_menu() {
292
+ add_menu_page( __( 'Bulk WP', 'bulk-delete' ), __( 'Bulk WP', 'bulk-delete' ), 'manage_options', self::POSTS_PAGE_SLUG, array( $this, 'display_posts_page' ), 'dashicons-trash', self::MENU_ORDER );
293
+
294
+ $this->posts_page = add_submenu_page( self::POSTS_PAGE_SLUG, __( 'Bulk Delete Posts', 'bulk-delete' ), __( 'Bulk Delete Posts', 'bulk-delete' ), 'delete_posts', self::POSTS_PAGE_SLUG, array( $this, 'display_posts_page' ) );
295
+ $this->pages_page = add_submenu_page( self::POSTS_PAGE_SLUG, __( 'Bulk Delete Pages', 'bulk-delete' ), __( 'Bulk Delete Pages', 'bulk-delete' ), 'delete_pages', self::PAGES_PAGE_SLUG, array( $this, 'display_pages_page' ) );
296
+
297
+ /**
298
+ * Runs just after adding all *delete* menu items to Bulk WP main menu
299
+ *
300
+ * This action is primarily for adding extra *delete* menu items to the Bulk WP main menu.
301
+ *
302
+ * @since 5.3
303
+ */
304
+ do_action( 'bd_after_primary_menus' );
305
+
306
+ /**
307
+ * Runs just before adding non-action menu items to Bulk WP main menu
308
+ *
309
+ * This action is primarily for adding extra menu items before non-action menu items to the Bulk WP main menu.
310
+ *
311
+ * @since 5.3
312
+ */
313
+ do_action( 'bd_before_secondary_menus' );
314
+
315
+ $this->cron_page = add_submenu_page( self::POSTS_PAGE_SLUG, __( 'Bulk Delete Schedules' , 'bulk-delete' ), __( 'Scheduled Jobs', 'bulk-delete' ), 'delete_posts' , self::CRON_PAGE_SLUG , array( $this, 'display_cron_page' ) );
316
+ $this->addon_page = add_submenu_page( self::POSTS_PAGE_SLUG, __( 'Addon Licenses' , 'bulk-delete' ), __( 'Addon Licenses', 'bulk-delete' ), 'activate_plugins', self::ADDON_PAGE_SLUG, array( 'BD_License', 'display_addon_page' ) );
317
+ $this->info_page = add_submenu_page( self::POSTS_PAGE_SLUG, __( 'Bulk Delete System Info', 'bulk-delete' ), __( 'System Info' , 'bulk-delete' ), 'manage_options' , self::INFO_PAGE_SLUG , array( 'Bulk_Delete_System_Info', 'display_system_info' ) );
318
+
319
+ /**
320
+ * Runs just after adding all menu items to Bulk WP main menu
321
+ *
322
+ * This action is primarily for adding extra menu items to the Bulk WP main menu.
323
+ *
324
+ * @since 5.3
325
+ */
326
+ do_action( 'bd_after_all_menus' );
327
+
328
+ // enqueue JavaScript
329
+ add_action( 'admin_print_scripts-' . $this->posts_page, array( $this, 'add_script' ) );
330
+ add_action( 'admin_print_scripts-' . $this->pages_page, array( $this, 'add_script' ) );
331
+
332
+ // delete posts page
333
+ add_action( "load-{$this->posts_page}", array( $this, 'add_delete_posts_settings_panel' ) );
334
+ add_action( "add_meta_boxes_{$this->posts_page}", array( $this, 'add_delete_posts_meta_boxes' ) );
335
+
336
+ // delete pages page
337
+ add_action( "load-{$this->pages_page}", array( $this, 'add_delete_pages_settings_panel' ) );
338
+ add_action( "add_meta_boxes_{$this->pages_page}", array( $this, 'add_delete_pages_meta_boxes' ) );
339
+ }
340
+
341
+ /**
342
+ * Add settings Panel for delete posts page
343
+ */
344
+ public function add_delete_posts_settings_panel() {
345
+
346
+ /**
347
+ * Add contextual help for admin screens
348
+ *
349
+ * @since 5.1
350
+ */
351
+ do_action( 'bd_add_contextual_help', $this->posts_page );
352
+
353
+ /* Trigger the add_meta_boxes hooks to allow meta boxes to be added */
354
+ do_action( 'add_meta_boxes_' . $this->posts_page, null );
355
+
356
+ /* Enqueue WordPress' script for handling the meta boxes */
357
+ wp_enqueue_script( 'postbox' );
358
+ }
359
+
360
+ /**
361
+ * Register meta boxes for delete posts page
362
+ */
363
+ public function add_delete_posts_meta_boxes() {
364
+ add_meta_box( self::BOX_POST_STATUS , __( 'By Post Status' , 'bulk-delete' ) , 'Bulk_Delete_Posts::render_delete_posts_by_status_box' , $this->posts_page , 'advanced' );
365
+ add_meta_box( self::BOX_CATEGORY , __( 'By Category' , 'bulk-delete' ) , 'Bulk_Delete_Posts::render_delete_posts_by_category_box' , $this->posts_page , 'advanced' );
366
+ add_meta_box( self::BOX_TAG , __( 'By Tag' , 'bulk-delete' ) , 'Bulk_Delete_Posts::render_delete_posts_by_tag_box' , $this->posts_page , 'advanced' );
367
+ add_meta_box( self::BOX_TAX , __( 'By Custom Taxonomy' , 'bulk-delete' ) , 'Bulk_Delete_Posts::render_delete_posts_by_taxonomy_box' , $this->posts_page , 'advanced' );
368
+ add_meta_box( self::BOX_POST_TYPE , __( 'By Custom Post Types' , 'bulk-delete' ) , 'Bulk_Delete_Posts::render_delete_posts_by_post_type_box' , $this->posts_page , 'advanced' );
369
+ add_meta_box( self::BOX_URL , __( 'By URL' , 'bulk-delete' ) , 'Bulk_Delete_Posts::render_delete_posts_by_url_box' , $this->posts_page , 'advanced' );
370
+ add_meta_box( self::BOX_POST_REVISION , __( 'By Post Revision' , 'bulk-delete' ) , 'Bulk_Delete_Posts::render_posts_by_revision_box' , $this->posts_page , 'advanced' );
371
+
372
+ /**
373
+ * Add meta box in delete posts page
374
+ * This hook can be used for adding additional meta boxes in delete posts page
375
+ *
376
+ * @since 5.3
377
+ */
378
+ do_action( 'bd_add_meta_box_for_posts' );
379
+ }
380
+
381
+ /**
382
+ * Setup settings panel for delete pages page
383
+ *
384
+ * @since 5.0
385
+ */
386
+ public function add_delete_pages_settings_panel() {
387
+
388
+ /**
389
+ * Add contextual help for admin screens
390
+ *
391
+ * @since 5.1
392
+ */
393
+ do_action( 'bd_add_contextual_help', $this->pages_page );
394
+
395
+ /* Trigger the add_meta_boxes hooks to allow meta boxes to be added */
396
+ do_action( 'add_meta_boxes_' . $this->pages_page, null );
397
+
398
+ /* Enqueue WordPress' script for handling the meta boxes */
399
+ wp_enqueue_script( 'postbox' );
400
+ }
401
+
402
+ /**
403
+ * Register meta boxes for delete pages page
404
+ *
405
+ * @since 5.0
406
+ */
407
+ public function add_delete_pages_meta_boxes() {
408
+ add_meta_box( self::BOX_PAGE_STATUS , __( 'By Page status' , 'bulk-delete' ) , 'Bulk_Delete_Pages::render_delete_pages_by_status_box' , $this->pages_page , 'advanced' );
409
+
410
+ /**
411
+ * Add meta box in delete pages page
412
+ * This hook can be used for adding additional meta boxes in delete pages page
413
+ *
414
+ * @since 5.3
415
+ */
416
+ do_action( 'bd_add_meta_box_for_pages' );
417
+ }
418
+
419
+ /**
420
+ * Enqueue JavaScript.
421
+ *
422
+ * Uses code from http://trentrichardson.com/examples/timepicker/
423
+ */
424
+ public function add_script() {
425
+ global $wp_scripts;
426
+
427
+ wp_enqueue_script( 'jquery-ui-timepicker', plugins_url( '/assets/js/jquery-ui-timepicker-addon.min.js', __FILE__ ), array( 'jquery-ui-slider', 'jquery-ui-datepicker' ), '1.5.4', true );
428
+ wp_enqueue_style( 'jquery-ui-timepicker', plugins_url( '/assets/css/jquery-ui-timepicker-addon.min.css', __FILE__ ), array(), '1.5.4' );
429
+
430
+ wp_enqueue_script( 'select2', plugins_url( '/assets/js/select2.min.js', __FILE__ ), array( 'jquery' ), '4.0.0', true );
431
+ wp_enqueue_style( 'select2', plugins_url( '/assets/css/select2.min.css', __FILE__ ), array(), '4.0.0' );
432
+
433
+ $postfix = ( defined( 'SCRIPT_DEBUG' ) && true === SCRIPT_DEBUG ) ? '' : '.min';
434
+ wp_enqueue_script( self::JS_HANDLE, plugins_url( '/assets/js/bulk-delete' . $postfix . '.js', __FILE__ ), array( 'jquery-ui-timepicker' ), self::VERSION, true );
435
+ wp_enqueue_style( self::CSS_HANDLE, plugins_url( '/assets/css/bulk-delete' . $postfix . '.css', __FILE__ ), array( 'select2' ), self::VERSION );
436
+
437
+ $ui = $wp_scripts->query( 'jquery-ui-core' );
438
+ $url = "//ajax.googleapis.com/ajax/libs/jqueryui/{$ui->ver}/themes/smoothness/jquery-ui.css";
439
+ wp_enqueue_style( 'jquery-ui-smoothness', $url, false, $ui->ver );
440
+
441
+ /**
442
+ * Filter JavaScript array
443
+ *
444
+ * This filter can be used to extend the array that is passed to JavaScript
445
+ *
446
+ * @since 5.4
447
+ */
448
+ $translation_array = apply_filters( 'bd_javascript_array', array(
449
+ 'msg' => array(),
450
+ 'validators' => array(),
451
+ 'dt_iterators' => array(),
452
+ 'pre_action_msg' => array(),
453
+ 'error_msg' => array(),
454
+ 'pro_iterators' => array(),
455
+ ) );
456
+ wp_localize_script( self::JS_HANDLE, self::JS_VARIABLE, $translation_array );
457
+ }
458
+
459
+ /**
460
+ * Show the delete posts page.
461
+ *
462
+ * @Todo Move this function to Bulk_Delete_Posts class
463
+ */
464
+ public function display_posts_page() {
465
  ?>
466
  <div class="wrap">
467
+ <h2><?php _e( 'Bulk Delete Posts', 'bulk-delete' );?></h2>
468
  <?php settings_errors(); ?>
469
 
470
  <form method = "post">
471
  <?php
472
+ // nonce for bulk delete
473
+ wp_nonce_field( 'sm-bulk-delete-posts', 'sm-bulk-delete-posts-nonce' );
474
 
475
+ /* Used to save closed meta boxes and their order */
476
+ wp_nonce_field( 'meta-box-order', 'meta-box-order-nonce', false );
477
+ wp_nonce_field( 'closedpostboxes', 'closedpostboxesnonce', false );
478
  ?>
479
  <div id = "poststuff">
480
  <div id="post-body" class="metabox-holder columns-2">
481
 
482
+ <div class="notice notice-warning">
483
+ <p><strong><?php _e( 'WARNING: Posts deleted once cannot be retrieved back. Use with caution.', 'bulk-delete' ); ?></strong></p>
484
  </div>
485
 
486
  <div id="postbox-container-1" class="postbox-container">
497
  </div><!-- .wrap -->
498
 
499
  <?php
500
+ /**
501
+ * Runs just before displaying the footer text in the "Bulk Delete Posts" admin page.
502
+ *
503
+ * This action is primarily for adding extra content in the footer of "Bulk Delete Posts" admin page.
504
+ *
505
+ * @since 5.0
506
+ */
507
+ do_action( 'bd_admin_footer_posts_page' );
508
+ }
509
+
510
+ /**
511
+ * Display the delete pages page
512
+ *
513
+ * @Todo Move this function to Bulk_Delete_Pages class
514
+ * @since 5.0
515
+ */
516
+ public function display_pages_page() {
517
  ?>
518
  <div class="wrap">
519
+ <h2><?php _e( 'Bulk Delete Pages', 'bulk-delete' );?></h2>
520
  <?php settings_errors(); ?>
521
 
522
  <form method = "post">
523
  <?php
524
+ // nonce for bulk delete
525
+ wp_nonce_field( 'sm-bulk-delete-pages', 'sm-bulk-delete-pages-nonce' );
526
 
527
+ /* Used to save closed meta boxes and their order */
528
+ wp_nonce_field( 'meta-box-order', 'meta-box-order-nonce', false );
529
+ wp_nonce_field( 'closedpostboxes', 'closedpostboxesnonce', false );
530
  ?>
531
  <div id = "poststuff">
532
  <div id="post-body" class="metabox-holder columns-2">
533
 
534
+ <div class="notice notice-warning">
535
+ <p><strong><?php _e( 'WARNING: Pages deleted once cannot be retrieved back. Use with caution.', 'bulk-delete' ); ?></strong></p>
536
  </div>
537
 
538
  <div id="postbox-container-1" class="postbox-container">
549
  </div><!-- .wrap -->
550
 
551
  <?php
552
+ /**
553
+ * Runs just before displaying the footer text in the "Bulk Delete Pages" admin page.
554
+ *
555
+ * This action is primarily for adding extra content in the footer of "Bulk Delete Pages" admin page.
556
+ *
557
+ * @since 5.0
558
+ */
559
+ do_action( 'bd_admin_footer_pages_page' );
560
+ }
561
+
562
+ /**
563
+ * Display the schedule page
564
+ */
565
+ public function display_cron_page() {
566
+
567
+ if ( ! class_exists( 'WP_List_Table' ) ) {
568
+ require_once ABSPATH . WPINC . '/class-wp-list-table.php';
569
+ }
570
+
571
+ if ( ! class_exists( 'Cron_List_Table' ) ) {
572
+ require_once self::$PLUGIN_DIR . '/include/cron/class-cron-list-table.php';
573
+ }
574
+
575
+ // Prepare Table of elements
576
+ $cron_list_table = new Cron_List_Table();
577
+ $cron_list_table->prepare_items();
578
  ?>
579
  <div class="wrap">
580
+ <h2><?php _e( 'Bulk Delete Schedules', 'bulk-delete' );?></h2>
581
  <?php settings_errors(); ?>
582
  <?php
583
+ // Table of elements
584
+ $cron_list_table->display();
585
+ bd_display_available_addon_list();
586
  ?>
587
  </div>
588
  <?php
589
+ /**
590
+ * Runs just before displaying the footer text in the "Schedules" admin page.
591
+ *
592
+ * This action is primarily for adding extra content in the footer of "Schedules" admin page.
593
+ *
594
+ * @since 5.0
595
+ */
596
+ do_action( 'bd_admin_footer_cron_page' );
597
+ }
598
+
599
+ /**
600
+ * Handle both POST and GET requests.
601
+ * This method automatically triggers all the actions after checking the nonce.
602
+ */
603
+ public function request_handler() {
604
+ if ( isset( $_POST['bd_action'] ) ) {
605
+ $bd_action = sanitize_text_field( $_POST['bd_action'] );
606
+ $nonce_valid = false;
607
+
608
+ if ( 'delete_pages_' === substr( $_POST['bd_action'], 0, strlen( 'delete_pages_' ) )
609
+ && check_admin_referer( 'sm-bulk-delete-pages', 'sm-bulk-delete-pages-nonce' ) ) {
610
+ $nonce_valid = true;
611
+ }
612
+
613
+ if ( 'delete_posts_' === substr( $_POST['bd_action'], 0, strlen( 'delete_posts_' ) )
614
+ && check_admin_referer( 'sm-bulk-delete-posts', 'sm-bulk-delete-posts-nonce' ) ) {
615
+ $nonce_valid = true;
616
+ }
617
+
618
+ if ( 'delete_meta_' === substr( $_POST['bd_action'], 0, strlen( 'delete_meta_' ) )
619
+ && check_admin_referer( 'sm-bulk-delete-meta', 'sm-bulk-delete-meta-nonce' ) ) {
620
+ $nonce_valid = true;
621
+ }
622
+
623
+ /**
624
+ * Perform nonce check.
625
+ *
626
+ * @since 5.5
627
+ */
628
+ if ( ! apply_filters( 'bd_action_nonce_check', $nonce_valid, $bd_action ) ) {
629
+ return;
630
+ }
631
+
632
+ /**
633
+ * Before performing a bulk action.
634
+ * This hook is for doing actions just before performing any bulk operation
635
+ *
636
+ * @since 5.4
637
+ */
638
+ do_action( 'bd_pre_bulk_action', $bd_action );
639
+
640
+ /**
641
+ * Perform the bulk operation.
642
+ * This hook is for doing the bulk operation. Nonce check has already happened by this point.
643
+ *
644
+ * @since 5.4
645
+ */
646
+ do_action( 'bd_' . $_POST['bd_action'], $_POST );
647
+ }
648
+
649
+ if ( isset( $_GET['bd_action'] ) ) {
650
+ // TODO: check nonce for get requests as well.
651
+ do_action( 'bd_' . $_GET['bd_action'], $_GET );
652
+ }
653
+ }
654
+
655
+ /**
656
+ * Increase PHP timeout.
657
+ *
658
+ * This is to prevent bulk operations from timing out
659
+ *
660
+ * @since 5.4
661
+ */
662
+ public function increase_timeout() {
663
+ if ( ! ini_get( 'safe_mode' ) ) {
664
+ @set_time_limit( 0 );
665
+ }
666
+ }
667
  }
668
 
 
669
 
670
  /**
671
  * The main function responsible for returning the one true Bulk_Delete
674
  * Use this function like you would a global variable, except without needing
675
  * to declare the global.
676
  *
677
+ * Example: `<?php $bulk_delete = BULK_DELETE(); ?>`
678
  *
679
  * @since 5.0
680
+ * @return Bulk_Delete The one true Bulk_Delete Instance
681
  */
682
  function BULK_DELETE() {
683
  return Bulk_Delete::instance();
include/addons/addon-list.php ADDED
@@ -0,0 +1,146 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Addon related util functions.
4
+ *
5
+ * @since 5.5
6
+ * @author Sudar
7
+ * @package BulkDelete\Util\Addon
8
+ */
9
+
10
+ defined( 'ABSPATH' ) || exit; // Exit if accessed directly
11
+
12
+ /**
13
+ * Display information about all available addons
14
+ *
15
+ * @since 5.5
16
+ */
17
+ function bd_display_available_addon_list() {
18
+ echo '<p>';
19
+ _e( 'The following are the list of pro addons that are currently available for purchase.', 'bulk-delete' );
20
+ echo '</p>';
21
+
22
+ echo '<ul style="list-style:disc; padding-left:35px">';
23
+
24
+ echo '<li>';
25
+ echo '<strong>', __( 'Delete posts by custom field', 'bulk-delete' ), '</strong>', ' - ';
26
+ echo __( 'Adds the ability to delete posts based on custom fields', 'bulk-delete' );
27
+ echo ' <a href = "http://bulkwp.com/addons/bulk-delete-posts-by-custom-field/?utm_source=wpadmin&utm_campaign=BulkDelete&utm_medium=addonlist&utm_content=bd-cf">', __( 'More Info', 'bulk-delete' ), '</a>.';
28
+ echo '</li>';
29
+
30
+ echo '<li>';
31
+ echo '<strong>', __( 'Delete posts by title', 'bulk-delete' ), '</strong>', ' - ';
32
+ echo __( 'Adds the ability to delete posts based on title', 'bulk-delete' );
33
+ echo ' <a href = "http://bulkwp.com/addons/bulk-delete-posts-by-title/?utm_source=wpadmin&utm_campaign=BulkDelete&utm_medium=addonlist&utm_content=bd-ti">', __( 'More Info', 'bulk-delete' ), '</a>.';
34
+ echo '</li>';
35
+
36
+ echo '<li>';
37
+ echo '<strong>', __( 'Delete posts by duplicate title', 'bulk-delete' ), '</strong>', ' - ';
38
+ echo __( 'Adds the ability to delete posts based on duplicate title', 'bulk-delete' );
39
+ echo ' <a href = "http://bulkwp.com/addons/bulk-delete-posts-by-duplicate-title/?utm_source=wpadmin&utm_campaign=BulkDelete&utm_medium=addonlist&utm_content=bd-dti">', __( 'More Info', 'bulk-delete' ), '</a>.';
40
+ echo '</li>';
41
+
42
+ echo '<li>';
43
+ echo '<strong>', __( 'Delete posts by attachment', 'bulk-delete' ), '</strong>', ' - ';
44
+ echo __( 'Adds the ability to delete posts based on whether it contains attachment or not', 'bulk-delete' );
45
+ echo ' <a href = "http://bulkwp.com/addons/bulk-delete-posts-by-attachment/?utm_source=wpadmin&utm_campaign=BulkDelete&utm_medium=addonlist&utm_content=bd-p-at">', __( 'More Info', 'bulk-delete' ), '</a>.';
46
+ echo '</li>';
47
+
48
+ echo '<li>';
49
+ echo '<strong>', __( 'Delete posts by user role', 'bulk-delete' ), '</strong>', ' - ';
50
+ echo __( 'Adds the ability to delete posts based on user role', 'bulk-delete' );
51
+ echo ' <a href = "http://bulkwp.com/addons/bulk-delete-posts-by-user-role/?utm_source=wpadmin&utm_campaign=BulkDelete&utm_medium=addonlist&utm_content=bd-ur">', __( 'More Info', 'bulk-delete' ), '</a>.';
52
+ echo '</li>';
53
+
54
+ echo '<li>';
55
+ echo '<strong>', __( 'Delete from trash', 'bulk-delete' ), '</strong>', ' - ';
56
+ echo __( 'Adds the ability to delete posts and pages from trash', 'bulk-delete' );
57
+ echo ' <a href = "http://bulkwp.com/addons/bulk-delete-from-trash/?utm_source=wpadmin&utm_campaign=BulkDelete&utm_medium=addonlist&utm_content=bd-th">', __( 'More Info', 'bulk-delete' ), '</a>.';
58
+ echo '</li>';
59
+
60
+ echo '<li>';
61
+ echo '<strong>', __( 'Scheduler Email', 'bulk-delete' ), '</strong>', ' - ';
62
+ echo __( 'Sends an email every time a Bulk WP scheduler runs', 'bulk-delete' );
63
+ echo ' <a href = "http://bulkwp.com/addons/scheduler-email/?utm_source=wpadmin&utm_campaign=BulkDelete&utm_medium=addonlist&utm_content=bd-se">', __( 'More Info', 'bulk-delete' ), '</a>.';
64
+ echo '</li>';
65
+
66
+ echo '<li>';
67
+ echo '<strong>', __( 'Scheduler for deleting Posts by Category', 'bulk-delete' ), '</strong>', ' - ';
68
+ echo __( 'Adds the ability to schedule auto delete of posts based on category', 'bulk-delete' );
69
+ echo ' <a href = "http://bulkwp.com/addons/scheduler-for-deleting-posts-by-category/?utm_source=wpadmin&utm_campaign=BulkDelete&utm_medium=addonlist&utm_content=bd-sc">', __( 'More Info', 'bulk-delete' ), '</a>.';
70
+ echo '</li>';
71
+
72
+ echo '<li>';
73
+ echo '<strong>', __( 'Scheduler for deleting Posts by Tag', 'bulk-delete' ), '</strong>', ' - ';
74
+ echo __( 'Adds the ability to schedule auto delete of posts based on tag', 'bulk-delete' );
75
+ echo ' <a href = "http://bulkwp.com/addons/scheduler-for-deleting-posts-by-tag/?utm_source=wpadmin&utm_campaign=BulkDelete&utm_medium=addonlist&utm_content=bd-st">', __( 'More Info', 'bulk-delete' ), '</a>.';
76
+ echo '</li>';
77
+
78
+ echo '<li>';
79
+ echo '<strong>', __( 'Scheduler for deleting Posts by Custom Taxonomy', 'bulk-delete' ), '</strong>', ' - ';
80
+ echo __( 'Adds the ability to schedule auto delete of posts based on custom taxonomy', 'bulk-delete' );
81
+ echo ' <a href = "http://bulkwp.com/addons/scheduler-for-deleting-posts-by-taxonomy/?utm_source=wpadmin&utm_campaign=BulkDelete&utm_medium=addonlist&utm_content=bd-stx">', __( 'More Info', 'bulk-delete' ), '</a>.';
82
+ echo '</li>';
83
+
84
+ echo '<li>';
85
+ echo '<strong>', __( 'Scheduler for deleting Posts by Custom Post Type', 'bulk-delete' ), '</strong>', ' - ';
86
+ echo __( 'Adds the ability to schedule auto delete of posts based on custom post type', 'bulk-delete' );
87
+ echo ' <a href = "http://bulkwp.com/addons/scheduler-for-deleting-posts-by-post-type/?utm_source=wpadmin&utm_campaign=BulkDelete&utm_medium=addonlist&utm_content=bd-spt">', __( 'More Info', 'bulk-delete' ), '</a>.';
88
+ echo '</li>';
89
+
90
+ echo '<li>';
91
+ echo '<strong>', __( 'Scheduler for deleting Posts by Post Status', 'bulk-delete' ), '</strong>', ' - ';
92
+ echo __( 'Adds the ability to schedule auto delete of posts based on post status like drafts, pending posts, scheduled posts etc.', 'bulk-delete' );
93
+ echo ' <a href = "http://bulkwp.com/addons/scheduler-for-deleting-posts-by-status/?utm_source=wpadmin&utm_campaign=BulkDelete&utm_medium=addonlist&utm_content=bd-sps">', __( 'More Info', 'bulk-delete' ), '</a>.';
94
+ echo '</li>';
95
+
96
+ echo '<li>';
97
+ echo '<strong>', __( 'Scheduler for deleting Pages by Status', 'bulk-delete' ), '</strong>', ' - ';
98
+ echo __( 'Adds the ability to schedule auto delete pages based on status', 'bulk-delete' );
99
+ echo ' <a href = "http://bulkwp.com/addons/scheduler-for-deleting-pages-by-status/?utm_source=wpadmin&utm_campaign=BulkDelete&utm_medium=addonlist&utm_content=bd-sp">', __( 'More Info', 'bulk-delete' ), '</a>.';
100
+ echo '</li>';
101
+
102
+ echo '<li>';
103
+ echo '<strong>', __( 'Scheduler for deleting Users by User Role', 'bulk-delete' ), '</strong>', ' - ';
104
+ echo __( 'Adds the ability to schedule auto delete of users based on user role', 'bulk-delete' );
105
+ echo ' <a href = "http://bulkwp.com/addons/scheduler-for-deleting-users-by-role/?utm_source=wpadmin&utm_campaign=BulkDelete&utm_medium=addonlist&utm_content=bd-u-ur">', __( 'More Info', 'bulk-delete' ), '</a>.';
106
+ echo '</li>';
107
+
108
+ echo '<li>';
109
+ echo '<strong>', __( 'Scheduler for deleting Users by User Meta', 'bulk-delete' ), '</strong>', ' - ';
110
+ echo __( 'Adds the ability to schedule auto delete of users based on user meta', 'bulk-delete' );
111
+ echo ' <a href = "http://bulkwp.com/addons/scheduler-for-deleting-users-by-meta/?utm_source=wpadmin&utm_campaign=BulkDelete&utm_medium=addonlist&utm_content=bds-u-ma">', __( 'More Info', 'bulk-delete' ), '</a>.';
112
+ echo '</li>';
113
+
114
+ echo '<li>';
115
+ echo '<strong>', __( 'Delete Post Meta Fields', 'bulk-delete' ), '</strong>', ' - ';
116
+ echo __( 'Adds the ability to delete post meta fields based on value and to schedule automatic deletion', 'bulk-delete' );
117
+ echo ' <a href = "http://bulkwp.com/addons/bulk-delete-post-meta/?utm_source=wpadmin&utm_campaign=BulkDelete&utm_medium=addonlist&utm_content=bd-m-p">', __( 'More Info', 'bulk-delete' ), '</a>.';
118
+ echo '</li>';
119
+
120
+ echo '<li>';
121
+ echo '<strong>', __( 'Delete Comment Meta Fields', 'bulk-delete' ), '</strong>', ' - ';
122
+ echo __( 'Adds the ability to delete comment meta fields based on value and to schedule automatic deletion', 'bulk-delete' );
123
+ echo ' <a href = "http://bulkwp.com/addons/bulk-delete-comment-meta/?utm_source=wpadmin&utm_campaign=BulkDelete&utm_medium=addonlist&utm_content=bd-m-c">', __( 'More Info', 'bulk-delete' ), '</a>.';
124
+ echo '</li>';
125
+
126
+ echo '<li>';
127
+ echo '<strong>', __( 'Delete User Meta Fields', 'bulk-delete' ), '</strong>', ' - ';
128
+ echo __( 'Adds the ability to delete user meta fields based on value and to schedule automatic deletion', 'bulk-delete' );
129
+ echo ' <a href = "http://bulkwp.com/addons/bulk-delete-user-meta/?utm_source=wpadmin&utm_campaign=BulkDelete&utm_medium=addonlist&utm_content=bd-m-u">', __( 'More Info', 'bulk-delete' ), '</a>.';
130
+ echo '</li>';
131
+
132
+ echo '<li>';
133
+ echo '<strong>', __( 'Delete attachment', 'bulk-delete' ), '</strong>', ' - ';
134
+ echo __( 'Adds the ability to delete attachments based on whether they are attached to a post or not', 'bulk-delete' );
135
+ echo ' <a href = "http://bulkwp.com/addons/bulk-delete-attachments/?utm_source=wpadmin&utm_campaign=BulkDelete&utm_medium=addonlist&utm_content=bd-at">', __( 'More Info', 'bulk-delete' ), '</a>.';
136
+ echo '</li>';
137
+
138
+ echo '<li>';
139
+ echo '<strong>', __( 'Delete Jetpack Contact Form Messages', 'bulk-delete' ), '</strong>', ' - ';
140
+ echo __( 'Adds the ability to delete Jetpack Contact Form Messages based on filters and to schedule automatic deletion', 'bulk-delete' );
141
+ echo ' <a href = "http://bulkwp.com/addons/bulk-delete-jetpack-contact-form-messages/?utm_source=wpadmin&utm_campaign=BulkDelete&utm_medium=addonlist&utm_content=bd-jcm">', __( 'More Info', 'bulk-delete' ), '</a>.';
142
+ echo '</li>';
143
+
144
+ echo '</ul>';
145
+ }
146
+ ?>
include/addons/base/class-bd-addon.php ADDED
@@ -0,0 +1,135 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Base class for all BD Addons.
4
+ *
5
+ * @since 5.5
6
+ * @author Sudar
7
+ * @package BulkDelete\Addons\Base
8
+ */
9
+
10
+ defined( 'ABSPATH' ) || exit; // Exit if accessed directly
11
+
12
+ /**
13
+ * Base class for BD Addons.
14
+ *
15
+ * @abstract
16
+ * @since 5.5
17
+ */
18
+ abstract class BD_Addon {
19
+ /**
20
+ * @var string Addon Name.
21
+ */
22
+ protected $addon_name;
23
+
24
+ /**
25
+ * @var string Addon Code.
26
+ */
27
+ protected $addon_code;
28
+
29
+ /**
30
+ * @var string Addon File.
31
+ */
32
+ protected $addon_file;
33
+
34
+ /**
35
+ * @var string Addon Version.
36
+ */
37
+ protected $addon_version;
38
+
39
+ /**
40
+ * @var string Addon Author.
41
+ */
42
+ protected $addon_author = 'Sudar Muthu';
43
+
44
+ /**
45
+ * @var Module Name.
46
+ */
47
+ protected $module;
48
+
49
+ /**
50
+ * Initialize and setup variables.
51
+ *
52
+ * @since 5.5
53
+ * @abstract
54
+ * @return void
55
+ */
56
+ abstract protected function initialize();
57
+
58
+ /**
59
+ * Use `factory()` method to create instance of this class.
60
+ * Don't create instances directly
61
+ *
62
+ * @since 5.5
63
+ *
64
+ * @see factory()
65
+ */
66
+ public function __construct() {
67
+ $this->setup();
68
+ }
69
+
70
+ /**
71
+ * Setup the module.
72
+ *
73
+ * @access protected
74
+ * @since 5.5
75
+ */
76
+ protected function setup() {
77
+ $this->initialize();
78
+ $this->setup_translation();
79
+ if ( $this->dependencies_met() ) {
80
+ $this->setup_hooks();
81
+ }
82
+ }
83
+
84
+ /**
85
+ * Check if all dependencies are met.
86
+ * To check for dependencies overload this method in the child class.
87
+ *
88
+ * @return bool True if dependencies met, False otherwise.
89
+ */
90
+ protected function dependencies_met() {
91
+ return true;
92
+ }
93
+
94
+ /**
95
+ * Setup translation.
96
+ *
97
+ * @access protected
98
+ * @since 5.5
99
+ */
100
+ protected function setup_translation() {
101
+ $bd = BULK_DELETE();
102
+
103
+ // Load translation files from Bulk Delete language folder
104
+ load_plugin_textdomain( 'bulk-delete', false, $bd->translations );
105
+ }
106
+
107
+ /**
108
+ * Setup license handler.
109
+ *
110
+ * @since 5.5
111
+ *
112
+ * @param string $plugin_file Addon file name relative to plugin directory.
113
+ */
114
+ public function setup_license_handler( $plugin_file ) {
115
+ $this->addon_file = $plugin_file;
116
+ $this->license_handler = new BD_License_Handler(
117
+ $this->addon_name,
118
+ $this->addon_code,
119
+ $this->addon_version,
120
+ $this->addon_file,
121
+ $this->addon_author
122
+ );
123
+ }
124
+
125
+ /**
126
+ * Get addon class name.
127
+ *
128
+ * @since 5.5
129
+ * @return string Addon class name
130
+ */
131
+ protected function get_addon_class_name() {
132
+ return bd_get_addon_class_name( $this->addon_name );
133
+ }
134
+ }
135
+ ?>
include/addons/base/class-bd-base-addon.php ADDED
@@ -0,0 +1,61 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Base class for all Base Addons.
4
+ *
5
+ * @since 5.5
6
+ * @author Sudar
7
+ * @package BulkDelete\Addons\Base
8
+ */
9
+
10
+ defined( 'ABSPATH' ) || exit; // Exit if accessed directly
11
+
12
+ /**
13
+ * Base class for Base Addons.
14
+ *
15
+ * @abstract
16
+ * @since 5.5
17
+ */
18
+ abstract class BD_Base_Addon extends BD_Addon {
19
+
20
+ /**
21
+ * Use `factory()` method to create instance of this class.
22
+ * Don't create instances directly
23
+ *
24
+ * @since 5.5
25
+ *
26
+ * @see factory()
27
+ */
28
+ public function __construct() {
29
+ parent::__construct();
30
+ }
31
+
32
+ /**
33
+ * Setup hooks.
34
+ * This can be overridden by the child class.
35
+ *
36
+ * @since 5.5
37
+ */
38
+ protected function setup_hooks() {
39
+ }
40
+
41
+ /**
42
+ * Getter for cron hook.
43
+ *
44
+ * @since 5.5
45
+ * @return string Cron hook.
46
+ */
47
+ public function get_cron_hook() {
48
+ return $this->module->get_cron_hook();
49
+ }
50
+
51
+ /**
52
+ * Return reference to the module.
53
+ *
54
+ * @since 5.5
55
+ * @return object Reference to Module Object
56
+ */
57
+ public function get_module() {
58
+ return $this->module;
59
+ }
60
+ }
61
+ ?>
include/addons/base/class-bd-scheduler-addon.php ADDED
@@ -0,0 +1,180 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Base class for all Scheduler Addons.
4
+ *
5
+ * @since 5.5
6
+ * @author Sudar
7
+ * @package BulkDelete\Addons\Base
8
+ */
9
+
10
+ defined( 'ABSPATH' ) || exit; // Exit if accessed directly
11
+
12
+ /**
13
+ * Base class for Base Addons.
14
+ *
15
+ * @abstract
16
+ * @since 5.5
17
+ */
18
+ abstract class BD_Scheduler_Addon extends BD_Addon {
19
+
20
+ /**
21
+ * @var No base addon for this scheduler addon.
22
+ */
23
+ protected $no_base_addon = false;
24
+
25
+ /**
26
+ * @var Base addon name.
27
+ */
28
+ protected $base_addon;
29
+
30
+ /**
31
+ * @var Base addon version.
32
+ */
33
+ protected $base_addon_version;
34
+
35
+ /**
36
+ * @var Base addon class name.
37
+ */
38
+ protected $base_addon_class_name;
39
+
40
+ /**
41
+ * @var Base addon object.
42
+ */
43
+ protected $base_addon_obj;
44
+
45
+ /**
46
+ * @var Cron Hook to run the scheduler on.
47
+ */
48
+ protected $cron_hook;
49
+
50
+ /**
51
+ * Use `factory()` method to create instance of this class.
52
+ * Don't create instances directly
53
+ *
54
+ * @since 5.5
55
+ *
56
+ * @see factory()
57
+ */
58
+ public function __construct() {
59
+ parent::__construct();
60
+ }
61
+
62
+ /**
63
+ * Check if the base addon is available.
64
+ *
65
+ * @access protected
66
+ * @since 5.5
67
+ *
68
+ * @todo check for version as well
69
+ *
70
+ * @param string Base Addon class name. Default null. If not specified then it is auto calculated based on addon name.
71
+ * @return bool True if base addon is found, False other wise
72
+ */
73
+ protected function check_base_addon( $addon_class_name = null ) {
74
+ if ( null == $addon_class_name ) {
75
+ $this->base_addon_class_name = bd_get_addon_class_name( $this->base_addon );
76
+ } else {
77
+ $this->base_addon_class_name = $addon_class_name;
78
+ }
79
+
80
+ if ( class_exists( $this->base_addon_class_name ) ) {
81
+ // Ugly workaround, since we need to support PHP 5.2
82
+ $this->base_addon_obj = call_user_func( array( $this->base_addon_class_name, 'factory' ) );
83
+ return true;
84
+ } else {
85
+ add_action( 'admin_notices', array( $this, 'addon_missing_notice' ) );
86
+ return false;
87
+ }
88
+ }
89
+
90
+ /**
91
+ * Show a notice if the base addon is not available.
92
+ *
93
+ * @since 5.5
94
+ */
95
+ public function addon_missing_notice() {
96
+ $campaign_args = array(
97
+ 'utm_source' => 'wpadmin',
98
+ 'utm_campaign' => 'BulkDelete',
99
+ 'utm_medium' => 'header-notice',
100
+ 'utm_content' => $this->addon_code,
101
+ );
102
+ $addon_url = bd_get_addon_url( $this->base_addon, $campaign_args );
103
+
104
+ printf(
105
+ '<div class="error"><p>%s</p></div>',
106
+ sprintf( __( '"%s" addon requires "<a href="%s" target="_blank">%s</a>" addon to be installed and activated!', 'bulk-delete' ), $this->addon_name, $addon_url , $this->base_addon )
107
+ );
108
+ }
109
+
110
+ /**
111
+ * Setup hooks.
112
+ *
113
+ * @since 5.5
114
+ */
115
+ protected function setup_hooks() {
116
+ add_filter( 'bd_javascript_array', array( $this, 'filter_js_array' ) );
117
+
118
+ $cron_hook = $this->get_cron_hook();
119
+ if ( ! empty( $cron_hook ) ) {
120
+ add_action( $cron_hook, array( $this, 'do_delete' ), 10, 1 );
121
+ }
122
+ }
123
+
124
+ /**
125
+ * Filter JS Array and add pro hooks.
126
+ *
127
+ * @since 5.5
128
+ * @param array $js_array JavaScript Array
129
+ * @return array Modified JavaScript Array
130
+ */
131
+ public function filter_js_array( $js_array ) {
132
+ $js_array['pro_iterators'][] = $this->get_module()->get_field_slug();
133
+
134
+ return $js_array;
135
+ }
136
+
137
+ /**
138
+ * Hook handler.
139
+ *
140
+ * @since 5.5
141
+ * @param array $delete_options
142
+ */
143
+ public function do_delete( $delete_options ) {
144
+ do_action( 'bd_before_scheduler', $this->addon_name );
145
+ $count = $this->get_module()->delete( $delete_options );
146
+ do_action( 'bd_after_scheduler', $this->addon_name, $count );
147
+ }
148
+
149
+ /**
150
+ * Get the cron hook.
151
+ *
152
+ * @access protected
153
+ * @since 5.5
154
+ * @return string Cron hook.
155
+ */
156
+ protected function get_cron_hook() {
157
+ $cron_hook = '';
158
+ if ( null != $this->base_addon_obj ) {
159
+ $cron_hook = $this->base_addon_obj->get_cron_hook();
160
+ }
161
+
162
+ return $cron_hook;
163
+ }
164
+
165
+ /**
166
+ * Get base module.
167
+ *
168
+ * @access protected
169
+ * @since 5.5
170
+ * @return object Base module object
171
+ */
172
+ protected function get_module() {
173
+ if ( $this->no_base_addon ) {
174
+ return $this->base_addon_obj;
175
+ } else {
176
+ return $this->base_addon_obj->get_module();
177
+ }
178
+ }
179
+ }
180
+ ?>
include/addons/pages.php ADDED
@@ -0,0 +1,56 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Page Addons related functions.
4
+ *
5
+ * @since 5.5
6
+ * @author Sudar
7
+ * @package BulkDelete\Addon
8
+ */
9
+
10
+ defined( 'ABSPATH' ) || exit; // Exit if accessed directly
11
+
12
+ /**
13
+ * Register post related addons.
14
+ *
15
+ * @since 5.5
16
+ */
17
+ function bd_register_page_addons() {
18
+ $bd = BULK_DELETE();
19
+
20
+ add_meta_box( Bulk_Delete::BOX_PAGE_FROM_TRASH , __( 'Pages in Trash' , 'bulk-delete' ) , 'bd_render_delete_pages_from_trash', $bd->pages_page , 'advanced' );
21
+ }
22
+ add_action( 'bd_add_meta_box_for_pages', 'bd_register_page_addons' );
23
+
24
+ /**
25
+ * Render delete pages from trash box.
26
+ *
27
+ * @since 5.5
28
+ */
29
+ function bd_render_delete_pages_from_trash() {
30
+ if ( BD_Util::is_pages_box_hidden( Bulk_Delete::BOX_PAGE_FROM_TRASH ) ) {
31
+ printf( __( 'This section just got enabled. Kindly <a href = "%1$s">refresh</a> the page to fully enable it.', 'bulk-delete' ), 'admin.php?page=' . Bulk_Delete::PAGES_PAGE_SLUG );
32
+ return;
33
+ }
34
+
35
+ if ( ! class_exists( 'Bulk_Delete_From_Trash' ) ) {
36
+ ?>
37
+ <!-- pages In Trash box start-->
38
+ <p>
39
+ <span class = "bd-pages-trash-pro" style = "color:red">
40
+ <?php _e( 'You need "Bulk Delete From Trash" Addon, to delete pages in Trash.', 'bulk-delete' ); ?>
41
+ <a href = "http://bulkwp.com/addons/bulk-delete-from-trash/?utm_source=wpadmin&utm_campaign=BulkDelete&utm_medium=buynow&utm_content=bd-th">Buy now</a>
42
+ </span>
43
+ </p>
44
+ <!-- pages In Trash box end-->
45
+ <?php
46
+ } else {
47
+
48
+ /**
49
+ * Render delete pages from trash box
50
+ *
51
+ * @since 5.4
52
+ */
53
+ do_action( 'bd_render_delete_pages_from_trash' );
54
+ }
55
+ }
56
+ ?>
include/addons/posts.php ADDED
@@ -0,0 +1,171 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Post Addons related functions.
4
+ *
5
+ * @since 5.5
6
+ * @author Sudar
7
+ * @package BulkDelete\Addon
8
+ */
9
+
10
+ defined( 'ABSPATH' ) || exit; // Exit if accessed directly
11
+
12
+ /**
13
+ * Register post related addons.
14
+ *
15
+ * @since 5.5
16
+ */
17
+ function bd_register_post_addons() {
18
+ $bd = BULK_DELETE();
19
+
20
+ add_meta_box( Bulk_Delete::BOX_CUSTOM_FIELD , __( 'By Custom Field' , 'bulk-delete' ) , 'bd_render_delete_posts_by_custom_field_box' , $bd->posts_page , 'advanced' );
21
+ add_meta_box( Bulk_Delete::BOX_TITLE , __( 'By Title' , 'bulk-delete' ) , 'bd_render_delete_posts_by_title_box' , $bd->posts_page , 'advanced' );
22
+ add_meta_box( Bulk_Delete::BOX_DUPLICATE_TITLE , __( 'By Duplicate Title' , 'bulk-delete' ) , 'bd_render_delete_posts_by_duplicate_title_box' , $bd->posts_page , 'advanced' );
23
+ add_meta_box( Bulk_Delete::BOX_POST_BY_ROLE , __( 'By User Role' , 'bulk-delete' ) , 'bd_render_delete_posts_by_user_role_box' , $bd->posts_page , 'advanced' );
24
+ add_meta_box( Bulk_Delete::BOX_POST_FROM_TRASH , __( 'Posts in Trash' , 'bulk-delete' ) , 'bd_render_delete_posts_from_trash' , $bd->posts_page , 'advanced' );
25
+ }
26
+ add_action( 'bd_add_meta_box_for_posts', 'bd_register_post_addons' );
27
+
28
+ /**
29
+ * Render delete posts by custom field box
30
+ *
31
+ * @since 5.5
32
+ */
33
+ function bd_render_delete_posts_by_custom_field_box() {
34
+
35
+ if ( BD_Util::is_posts_box_hidden( Bulk_Delete::BOX_CUSTOM_FIELD ) ) {
36
+ printf( __( 'This section just got enabled. Kindly <a href = "%1$s">refresh</a> the page to fully enable it.', 'bulk-delete' ), 'admin.php?page=' . Bulk_Delete::POSTS_PAGE_SLUG );
37
+ return;
38
+ }
39
+
40
+ if ( ! class_exists( 'Bulk_Delete_Posts_By_Custom_Field' ) ) {
41
+ ?>
42
+ <!-- Custom Field box start-->
43
+ <p>
44
+ <span class = "bd-post-custom-field-pro" style = "color:red">
45
+ <?php _e( 'You need "Bulk Delete Posts by Custom Field" Addon, to delete post by custom field.', 'bulk-delete' ); ?>
46
+ <a href = "http://bulkwp.com/addons/bulk-delete-posts-by-custom-field/?utm_source=wpadmin&utm_campaign=BulkDelete&utm_medium=buynow&utm_content=bd-cf">Buy now</a>
47
+ </span>
48
+ </p>
49
+ <!-- Custom Field box end-->
50
+ <?php
51
+ } else {
52
+ Bulk_Delete_Posts_By_Custom_Field::render_delete_posts_by_custom_field_box();
53
+ }
54
+ }
55
+
56
+ /**
57
+ * Render posts by title box
58
+ *
59
+ * @since 5.5
60
+ */
61
+ function bd_render_delete_posts_by_title_box() {
62
+
63
+ if ( BD_Util::is_posts_box_hidden( Bulk_Delete::BOX_TITLE ) ) {
64
+ printf( __( 'This section just got enabled. Kindly <a href = "%1$s">refresh</a> the page to fully enable it.', 'bulk-delete' ), 'admin.php?page=' . Bulk_Delete::POSTS_PAGE_SLUG );
65
+ return;
66
+ }
67
+
68
+ if ( ! class_exists( 'Bulk_Delete_Posts_By_Title' ) ) {
69
+ ?>
70
+ <!-- Title box start-->
71
+ <p>
72
+ <span class = "bd-post-title-pro" style = "color:red">
73
+ <?php _e( 'You need "Bulk Delete Posts by Title" Addon, to delete post by title.', 'bulk-delete' ); ?>
74
+ <a href = "http://bulkwp.com/addons/bulk-delete-posts-by-title/?utm_source=wpadmin&utm_campaign=BulkDelete&utm_medium=buynow&utm_content=bd-ti">Buy now</a>
75
+ </span>
76
+ </p>
77
+ <!-- Title box end-->
78
+ <?php
79
+ } else {
80
+ Bulk_Delete_Posts_By_Title::render_delete_posts_by_title_box();
81
+ }
82
+ }
83
+
84
+ /**
85
+ * Render delete posts by duplicate title box
86
+ *
87
+ * @since 5.5
88
+ */
89
+ function bd_render_delete_posts_by_duplicate_title_box() {
90
+
91
+ if ( BD_Util::is_posts_box_hidden( Bulk_Delete::BOX_DUPLICATE_TITLE ) ) {
92
+ printf( __( 'This section just got enabled. Kindly <a href = "%1$s">refresh</a> the page to fully enable it.', 'bulk-delete' ), 'admin.php?page=' . Bulk_Delete::POSTS_PAGE_SLUG );
93
+ return;
94
+ }
95
+
96
+ if ( ! class_exists( 'Bulk_Delete_Posts_By_Duplicate_Title' ) ) {
97
+ ?>
98
+ <!-- Duplicate Title box start-->
99
+ <p>
100
+ <span class = "bd-post-title-pro" style = "color:red">
101
+ <?php _e( 'You need "Bulk Delete Posts by Duplicate Title" Addon, to delete post by duplicate title.', 'bulk-delete' ); ?>
102
+ <a href = "http://bulkwp.com/addons/bulk-delete-posts-by-duplicate-title/?utm_source=wpadmin&utm_campaign=BulkDelete&utm_medium=buynow&utm_content=bd-dti">Buy now</a>
103
+ </span>
104
+ </p>
105
+ <!-- Duplicate Title box end-->
106
+ <?php
107
+ } else {
108
+ Bulk_Delete_Posts_By_Duplicate_Title::render_delete_posts_by_duplicate_title_box();
109
+ }
110
+ }
111
+
112
+ /**
113
+ * Delete posts by user role
114
+ *
115
+ * @since 5.5
116
+ */
117
+ function bd_render_delete_posts_by_user_role_box() {
118
+
119
+ if ( BD_Util::is_posts_box_hidden( Bulk_Delete::BOX_POST_BY_ROLE ) ) {
120
+ printf( __( 'This section just got enabled. Kindly <a href = "%1$s">refresh</a> the page to fully enable it.', 'bulk-delete' ), 'admin.php?page=' . Bulk_Delete::POSTS_PAGE_SLUG );
121
+ return;
122
+ }
123
+ if ( ! class_exists( 'Bulk_Delete_Posts_By_User_Role' ) ) {
124
+ ?>
125
+ <!-- Posts by user role start-->
126
+ <p>
127
+ <span class = "bd-post-by-role-pro" style = "color:red">
128
+ <?php _e( 'You need "Bulk Delete Posts by User Role" Addon, to delete post based on User Role', 'bulk-delete' ); ?>
129
+ <a href = "http://bulkwp.com/addons/bulk-delete-posts-by-user-role/?utm_source=wpadmin&utm_campaign=BulkDelete&utm_medium=buynow&utm_content=bd-ur">Buy now</a>
130
+ </span>
131
+ </p>
132
+ <!-- Posts by user role end-->
133
+ <?php
134
+ } else {
135
+ Bulk_Delete_Posts_By_User_Role::render_delete_posts_by_user_role_box();
136
+ }
137
+ }
138
+
139
+ /**
140
+ * Render delete posts from trash box
141
+ *
142
+ * @since 5.5
143
+ */
144
+ function bd_render_delete_posts_from_trash() {
145
+ if ( BD_Util::is_posts_box_hidden( Bulk_Delete::BOX_POST_FROM_TRASH ) ) {
146
+ printf( __( 'This section just got enabled. Kindly <a href = "%1$s">refresh</a> the page to fully enable it.', 'bulk-delete' ), 'admin.php?page=' . Bulk_Delete::POSTS_PAGE_SLUG );
147
+ return;
148
+ }
149
+
150
+ if ( ! class_exists( 'Bulk_Delete_From_Trash' ) ) {
151
+ ?>
152
+ <!-- Posts In Trash box start-->
153
+ <p>
154
+ <span class = "bd-post-trash-pro" style = "color:red">
155
+ <?php _e( 'You need "Bulk Delete From Trash" Addon, to delete post in Trash.', 'bulk-delete' ); ?>
156
+ <a href = "http://bulkwp.com/addons/bulk-delete-from-trash/?utm_source=wpadmin&utm_campaign=BulkDelete&utm_medium=buynow&utm_content=bd-th">Buy now</a>
157
+ </span>
158
+ </p>
159
+ <!-- Posts In Trash box end-->
160
+ <?php
161
+ } else {
162
+
163
+ /**
164
+ * Render delete posts from trash box
165
+ *
166
+ * @since 5.4
167
+ */
168
+ do_action( 'bd_render_delete_posts_from_trash' );
169
+ }
170
+ }
171
+ ?>
include/addons/util.php ADDED
@@ -0,0 +1,71 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Addons related util functions.
4
+ *
5
+ * @since 5.5
6
+ * @author Sudar
7
+ * @package BulkDelete\Addon
8
+ */
9
+
10
+ defined( 'ABSPATH' ) || exit; // Exit if accessed directly
11
+
12
+ /**
13
+ * Compute class name from addon name.
14
+ *
15
+ * @since 5.5
16
+ *
17
+ * @param string $addon_name Name of the addon.
18
+ * @return string Computed class name for the addon.
19
+ */
20
+ function bd_get_addon_class_name( $addon_name ) {
21
+ $addon_class_name = str_replace( ' ', '_', $addon_name );
22
+
23
+ if ( false !== strpos( $addon_class_name, 'Scheduler' ) ) {
24
+ $addon_class_name = str_replace( 'Bulk_Delete', 'BD', $addon_class_name );
25
+ }
26
+
27
+ $addon_class_name .= '_Addon';
28
+
29
+ /**
30
+ * Filter to modify addon class name.
31
+ *
32
+ * @since 5.5
33
+ *
34
+ * @param string $addon_class_name Addon class name
35
+ * @param string $addon_name Addon name
36
+ */
37
+ return apply_filters( 'bd_addon_class_name', $addon_class_name, $addon_name );
38
+ }
39
+
40
+ /**
41
+ * Compute addon url from addon name.
42
+ *
43
+ * @since 5.5
44
+ *
45
+ * @param string $addon_name Name of the addon.
46
+ * @param array $campaign_args Campaign_args. Default empty array
47
+ * @return string Computed url for the addon.
48
+ */
49
+ function bd_get_addon_url( $addon_name, $campaign_args = array() ) {
50
+ $base = 'http://bulkwp.com/addons/';
51
+ $addon_slug = str_replace( ' ', '-', strtolower( $addon_name ) );
52
+
53
+ if ( false !== strpos( $addon_name, 'scheduler' ) ) {
54
+ $addon_slug = str_replace( 'bulk-delete-', '', $addon_name );
55
+ }
56
+
57
+ $addon_url = $base . $addon_slug;
58
+ $addon_url = add_query_arg( $campaign_args, $addon_url );
59
+
60
+ /**
61
+ * Filter to modify addon url.
62
+ *
63
+ * @since 5.5
64
+ *
65
+ * @param string $addon_name Addon name
66
+ * @param string $addon_url Addon url
67
+ * @param array $campaign_args Campaign_args. Default empty array
68
+ */
69
+ return apply_filters( 'bd_addon_url', $addon_url, $addon_name, $campaign_args );
70
+ }
71
+ ?>
include/admin-ui.php DELETED
@@ -1,90 +0,0 @@
1
- <?php
2
- /**
3
- * Customize admin UI for Bulk Delete plugin
4
- *
5
- * @package Bulk_Delete
6
- * @subpackage admin
7
- * @author Sudar
8
- * @since 5.0
9
- */
10
-
11
- /**
12
- * Add rating links to the admin dashboard
13
- *
14
- * @since 5.0
15
- * @param string $footer_text The existing footer text
16
- * @return string
17
- */
18
- function bd_add_rating_link( $footer_text ) {
19
- $rating_text = sprintf( __( 'Thank you for using <a href = "%1$s">Bulk Delete</a> plugin! Kindly <a href = "%2$s">rate us</a> at <a href = "%2$s">WordPress.org</a>', 'bulk-delete' ),
20
- 'http://bulkwp.com',
21
- 'http://wordpress.org/support/view/plugin-reviews/bulk-delete?filter=5#postform'
22
- );
23
-
24
- $rating_text = apply_filters( 'bd_rating_link', $rating_text );
25
- return str_replace( '</span>', '', $footer_text ) . ' | ' . $rating_text . '</span>';
26
- }
27
-
28
- /**
29
- * Modify admin footer in Bulk Delete plugin pages
30
- *
31
- * @since 5.0
32
- */
33
- function bd_modify_admin_footer() {
34
- add_filter( 'admin_footer_text', 'bd_add_rating_link' );
35
- }
36
-
37
- /**
38
- * Adds setting links in plugin listing page.
39
- * Based on http://striderweb.com/nerdaphernalia/2008/06/wp-use-action-links/
40
- *
41
- * @param array $links List of current links
42
- * @param string $file Plugin filename
43
- * @return array $links Modified list of links
44
- */
45
- function bd_add_plugin_action_links( $links, $file ) {
46
- $this_plugin = plugin_basename( Bulk_Delete::$PLUGIN_FILE );
47
-
48
- if ( $file == $this_plugin ) {
49
- $delete_users_link = '<a href="admin.php?page=' . Bulk_Delete::USERS_PAGE_SLUG . '">' . __( 'Bulk Delete Users', 'bulk-delete' ) . '</a>';
50
- array_unshift( $links, $delete_users_link ); // before other links
51
-
52
- $delete_posts_link = '<a href="admin.php?page=' . Bulk_Delete::POSTS_PAGE_SLUG . '">' . __( 'Bulk Delete Posts', 'bulk-delete' ) . '</a>';
53
- array_unshift( $links, $delete_posts_link ); // before other links
54
- }
55
-
56
- return $links;
57
- }
58
-
59
- /**
60
- * Add additional links in the Plugin listing page.
61
- * Based on http://zourbuth.com/archives/751/creating-additional-wordpress-plugin-links-row-meta/
62
- *
63
- * @param array $links List of current links
64
- * @param string $file Plugin filename
65
- * @return array $links Modified list of links
66
- */
67
- function bd_add_links_in_plugin_listing( $links, $file ) {
68
- $plugin = plugin_basename( Bulk_Delete::$PLUGIN_FILE );
69
-
70
- if ( $file == $plugin ) { // only for this plugin
71
- return array_merge( $links, array(
72
- '<a href="http://bulkwp.com/addons" target="_blank">' . __( 'Buy Addons', 'bulk-delete' ) . '</a>'
73
- ) );
74
- }
75
-
76
- return $links;
77
- }
78
-
79
- // Modify admin footer
80
- add_action( 'bd_admin_footer_posts_page', 'bd_modify_admin_footer' );
81
- add_action( 'bd_admin_footer_pages_page', 'bd_modify_admin_footer' );
82
- add_action( 'bd_admin_footer_users_page', 'bd_modify_admin_footer' );
83
- add_action( 'bd_admin_footer_cron_page' , 'bd_modify_admin_footer' );
84
- add_action( 'bd_admin_footer_addon_page', 'bd_modify_admin_footer' );
85
- add_action( 'bd_admin_footer_info_page' , 'bd_modify_admin_footer' );
86
-
87
- // Change plugin listing page
88
- add_filter( 'plugin_action_links', 'bd_add_plugin_action_links', 10, 2 );
89
- add_filter( 'plugin_row_meta', 'bd_add_links_in_plugin_listing', 10, 2 );
90
- ?>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
include/base/class-bd-meta-box-module.php ADDED
@@ -0,0 +1,358 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Base class for a Bulk Delete Meta Box Module.
4
+ *
5
+ * @since 5.5
6
+ * @author Sudar
7
+ * @package BulkDelete\Base
8
+ */
9
+
10
+ defined( 'ABSPATH' ) || exit; // Exit if accessed directly
11
+
12
+ /**
13
+ * Encapsulates the Bulk Delete Meta box Module Logic.
14
+ * All Bulk Delete Meta box Modules should extend this class.
15
+ *
16
+ * @since 5.5
17
+ * @abstract
18
+ */
19
+ abstract class BD_Meta_Box_Module {
20
+ /**
21
+ * @var string Item Type. Possible values 'posts', 'pages', 'users' etc.
22
+ */
23
+ protected $item_type = 'posts';
24
+
25
+ /**
26
+ * @var string The screen where this meta box would be shown.
27
+ */
28
+ protected $screen;
29
+
30
+ /**
31
+ * @var string Slug of the page where this module will be shown.
32
+ */
33
+ protected $page_slug;
34
+
35
+ /**
36
+ * @var string Slug for the form fields.
37
+ */
38
+ protected $field_slug;
39
+
40
+ /**
41
+ * @var string Slug of the meta box.
42
+ */
43
+ protected $meta_box_slug;
44
+
45
+ /**
46
+ * @var string Hook in which this meta box should be shown.
47
+ */
48
+ protected $meta_box_hook;
49
+
50
+ /**
51
+ * @var string Action in which the delete operation should be performed.
52
+ */
53
+ protected $delete_action;
54
+
55
+ /**
56
+ * @var string Hook for scheduler.
57
+ */
58
+ protected $cron_hook;
59
+
60
+ /**
61
+ * @var string Url of the scheduler addon.
62
+ */
63
+ protected $scheduler_url;
64
+
65
+ /**
66
+ * @var array Messages shown to the user.
67
+ */
68
+ protected $messages = array();
69
+
70
+ /**
71
+ * Initialize and setup variables.
72
+ *
73
+ * @since 5.5
74
+ * @abstract
75
+ * @return void
76
+ */
77
+ abstract protected function initialize();
78
+
79
+ /**
80
+ * Initialize and setup variables.
81
+ *
82
+ * @since 5.5
83
+ * @abstract
84
+ * @return void
85
+ */
86
+ abstract public function render();
87
+
88
+ /**
89
+ * Process the deletion.
90
+ *
91
+ * @since 5.5
92
+ * @abstract
93
+ * @return void
94
+ */
95
+ abstract public function process();
96
+
97
+ /**
98
+ * Perform the deletion
99
+ *
100
+ * @since 5.5
101
+ * @abstract
102
+ * @return int Number of users deleted
103
+ */
104
+ abstract public function delete( $delete_options );
105
+
106
+ /**
107
+ * Use `factory()` method to create instance of this class.
108
+ * Don't create instances directly
109
+ *
110
+ * @since 5.5
111
+ *
112
+ * @see factory()
113
+ */
114
+ public function __construct() {
115
+ $this->setup();
116
+ }
117
+
118
+ /**
119
+ * Setup the module.
120
+ *
121
+ * @since 5.5
122
+ */
123
+ protected function setup() {
124
+ $this->initialize();
125
+ $this->setup_hooks();
126
+ }
127
+
128
+ /**
129
+ * Setup hooks.
130
+ *
131
+ * @since 5.5
132
+ */
133
+ protected function setup_hooks() {
134
+ add_action( $this->meta_box_hook, array( $this, 'setup_metabox' ), 10, 2 );
135
+ add_action( 'bd_' . $this->delete_action, array( $this, 'process' ) );
136
+ add_filter( 'bd_javascript_array', array( $this, 'filter_js_array' ) );
137
+ }
138
+
139
+ /**
140
+ * Setup the meta box.
141
+ *
142
+ * @since 5.5
143
+ */
144
+ public function setup_metabox( $screen, $page_slug ) {
145
+ $this->screen = $screen;
146
+ $this->page_slug = $page_slug;
147
+
148
+ add_meta_box( $this->meta_box_slug, $this->messages['box_label'], array( $this, 'render_box' ), $this->screen, 'advanced' );
149
+ }
150
+
151
+ /**
152
+ * Render the meta box.
153
+ *
154
+ * @since 5.5
155
+ */
156
+ public function render_box() {
157
+ if ( $this->is_hidden() ) {
158
+ printf( __( 'This section just got enabled. Kindly <a href = "%1$s">refresh</a> the page to fully enable it.', 'bulk-delete' ), 'admin.php?page=' . $this->page_slug );
159
+ return;
160
+ }
161
+
162
+ $this->render();
163
+ }
164
+
165
+ /**
166
+ * Is the current meta box hidden by user.
167
+ *
168
+ * @since 5.5
169
+ * @return bool True, if hidden. False, otherwise.
170
+ */
171
+ protected function is_hidden() {
172
+ $current_user = wp_get_current_user();
173
+ $user_meta_field = $this->get_hidden_box_user_meta_field();
174
+ $hidden_boxes = get_user_meta( $current_user->ID, $user_meta_field, true );
175
+
176
+ return is_array( $hidden_boxes ) && in_array( $this->meta_box_slug, $hidden_boxes );
177
+ }
178
+
179
+ /**
180
+ * Get the user meta field that stores the status of the hidden meta boxes.
181
+ *
182
+ * @since 5.5
183
+ * @return string Name of the User Meta field.
184
+ */
185
+ protected function get_hidden_box_user_meta_field() {
186
+ if ( 'posts' == $this->item_type ) {
187
+ return 'metaboxhidden_toplevel_page_bulk-delete-posts';
188
+ } else {
189
+ return 'metaboxhidden_bulk-wp_page_' . $this->page_slug;
190
+ }
191
+ }
192
+
193
+ /**
194
+ * Filter the js array.
195
+ * This function will be overridden by the child classes.
196
+ *
197
+ * @since 5.5
198
+ * @param array $js_array JavaScript Array
199
+ * @return array Modified JavaScript Array
200
+ */
201
+ public function filter_js_array( $js_array) {
202
+ return $js_array;
203
+ }
204
+
205
+ /**
206
+ * Render filtering table header.
207
+ *
208
+ * @since 5.5
209
+ */
210
+ protected function render_filtering_table_header() {
211
+ bd_render_filtering_table_header();
212
+ }
213
+
214
+ /**
215
+ * Render restrict settings.
216
+ *
217
+ * @since 5.5
218
+ */
219
+ protected function render_restrict_settings() {
220
+ bd_render_restrict_settings( $this->field_slug, $this->item_type );
221
+ }
222
+
223
+ /**
224
+ * Render delete settings.
225
+ *
226
+ * @since 5.5
227
+ */
228
+ protected function render_delete_settings() {
229
+ bd_render_delete_settings( $this->field_slug );
230
+ }
231
+
232
+ /**
233
+ * Render limit settings.
234
+ *
235
+ * @since 5.5
236
+ */
237
+ protected function render_limit_settings() {
238
+ bd_render_limit_settings( $this->field_slug, $this->item_type );
239
+ }
240
+
241
+ /**
242
+ * Render cron settings.
243
+ *
244
+ * @since 5.5
245
+ */
246
+ protected function render_cron_settings() {
247
+ bd_render_cron_settings( $this->field_slug, $this->scheduler_url );
248
+ }
249
+
250
+ /**
251
+ * Render User Login restrict settings.
252
+ *
253
+ * @since 5.5
254
+ */
255
+ protected function render_user_login_restrict_settings() {
256
+ if ( bd_is_simple_login_log_present() ) {
257
+ $disabled = '';
258
+ } else {
259
+ $disabled = 'disabled';
260
+ }
261
+ ?>
262
+ <tr>
263
+ <td scope="row" colspan="2">
264
+ <input name="smbd_<?php echo $this->field_slug; ?>_login_restrict" id="smbd_<?php echo $this->field_slug; ?>_login_restrict" value="true" type="checkbox" <?php echo $disabled; ?>>
265
+ <?php _e( 'Only restrict to users who have not logged in the last ', 'bulk-delete' );?>
266
+ <input type="number" name="smbd_<?php echo $this->field_slug; ?>_login_days" id="smbd_<?php echo $this->field_slug; ?>_login_days" class="screen-per-page" value="0" min="0" disabled> <?php _e( 'days', 'bulk-delete' );?>.
267
+ <?php
268
+ if ( 'disabled' == $disabled ) {
269
+ ?>
270
+ <span style = "color:red">
271
+ <?php _e( 'Need the free "Simple Login Log" Plugin', 'bulk-delete' ); ?> <a href = "http://wordpress.org/plugins/simple-login-log/">Install now</a>
272
+ </span>
273
+ <?php
274
+ }
275
+ ?>
276
+ </td>
277
+ </tr>
278
+ <?php
279
+ }
280
+
281
+ /**
282
+ * Render delete user with no posts settings.
283
+ *
284
+ * @since 5.5
285
+ */
286
+ protected function render_user_with_no_posts_settings() {
287
+ ?>
288
+ <tr>
289
+ <td scope="row" colspan="2">
290
+ <input name="smbd_<?php echo $this->field_slug; ?>_no_posts" id="smbd_<?php echo $this->field_slug; ?>_no_posts" value="true" type="checkbox">
291
+ <?php _e( "Only if user doesn't have any post. Only posts from 'post' post type would be considered.", 'bulk-delete' ); ?>
292
+ </td>
293
+ </tr>
294
+ <?php
295
+ }
296
+
297
+ /**
298
+ * Render submit button.
299
+ *
300
+ * @since 5.5
301
+ */
302
+ protected function render_submit_button() {
303
+ bd_render_submit_button( $this->delete_action );
304
+ }
305
+
306
+ /**
307
+ * Helper function for processing deletion.
308
+ * Setups up cron and invokes the actual delete method.
309
+ *
310
+ * @since 5.5
311
+ */
312
+ protected function process_delete( $delete_options ) {
313
+ if ( array_get_bool( $_POST, 'smbd_' . $this->field_slug . '_cron', false ) ) {
314
+ $freq = $_POST[ 'smbd_' . $this->field_slug . '_cron_freq' ];
315
+ $time = strtotime( $_POST[ 'smbd_' . $this->field_slug . '_cron_start' ] ) - ( get_option( 'gmt_offset' ) * 60 * 60 );
316
+
317
+ if ( -1 == $freq ) {
318
+ wp_schedule_single_event( $time, $this->cron_hook, array( $delete_options ) );
319
+ } else {
320
+ wp_schedule_event( $time, $freq , $this->cron_hook, array( $delete_options ) );
321
+ }
322
+
323
+ $msg = $this->messages['scheduled'] . ' ' .
324
+ sprintf( __( 'See the full list of <a href = "%s">scheduled tasks</a>' , 'bulk-delete' ), get_bloginfo( 'wpurl' ) . '/wp-admin/admin.php?page=' . Bulk_Delete::CRON_PAGE_SLUG );
325
+ } else {
326
+ $deleted_count = $this->delete( $delete_options );
327
+ $msg = sprintf( _n( $this->messages['deleted_single'], $this->messages['deleted_plural'] , $deleted_count, 'bulk-delete' ), $deleted_count );
328
+ }
329
+
330
+ add_settings_error(
331
+ $this->page_slug,
332
+ 'deleted-' . $this->item_type,
333
+ $msg,
334
+ 'updated'
335
+ );
336
+ }
337
+
338
+ /**
339
+ * Getter for cron_hook.
340
+ *
341
+ * @since 5.5
342
+ * @return string Cron Hook name.
343
+ */
344
+ public function get_cron_hook() {
345
+ return $this->cron_hook;
346
+ }
347
+
348
+ /**
349
+ * Getter for field slug.
350
+ *
351
+ * @since 5.5
352
+ * @return string Field Slug.
353
+ */
354
+ public function get_field_slug() {
355
+ return $this->field_slug;
356
+ }
357
+ }
358
+ ?>
include/base/class-bd-page.php ADDED
@@ -0,0 +1,273 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Base class for all Pages.
4
+ *
5
+ * @since 5.5
6
+ * @author Sudar
7
+ * @package BulkDelete\Base\Page
8
+ */
9
+
10
+ defined( 'ABSPATH' ) || exit; // Exit if accessed directly
11
+
12
+ /**
13
+ * Base class for Pages.
14
+ *
15
+ * @abstract
16
+ * @since 5.5
17
+ */
18
+ abstract class BD_Page {
19
+ /**
20
+ * @var string Page Slug.
21
+ */
22
+ protected $page_slug;
23
+
24
+ /**
25
+ * @var string Item Type. Possible values 'posts', 'pages', 'users' etc.
26
+ */
27
+ protected $item_type;
28
+
29
+ /**
30
+ * @var string Minimum capability needed for viewing this page.
31
+ */
32
+ protected $capability = 'manage_options';
33
+
34
+ /**
35
+ * @var string The screen variable for this page.
36
+ */
37
+ protected $screen;
38
+
39
+ /**
40
+ * @var array Labels used in this page.
41
+ */
42
+ protected $label = array();
43
+
44
+ /**
45
+ * @var array Messages shown to the user.
46
+ */
47
+ protected $messages = array();
48
+
49
+ /**
50
+ * Initialize and setup variables.
51
+ *
52
+ * @since 5.5
53
+ * @abstract
54
+ * @return void
55
+ */
56
+ abstract protected function initialize();
57
+
58
+ /**
59
+ * Use `factory()` method to create instance of this class.
60
+ * Don't create instances directly
61
+ *
62
+ * @since 5.5
63
+ *
64
+ * @see factory()
65
+ */
66
+ public function __construct() {
67
+ $this->setup();
68
+ }
69
+
70
+ /**
71
+ * Setup the module.
72
+ *
73
+ * @since 5.5
74
+ */
75
+ protected function setup() {
76
+ $this->initialize();
77
+ $this->setup_hooks();
78
+ }
79
+
80
+ /**
81
+ * Setup hooks.
82
+ *
83
+ * @since 5.5
84
+ */
85
+ protected function setup_hooks() {
86
+ add_filter( 'bd_action_nonce_check', array( $this, 'nonce_check' ), 10, 2 );
87
+ add_filter( 'bd_admin_help_tabs', array( $this, 'render_help_tab' ), 10, 2 );
88
+
89
+ add_action( 'bd_after_primary_menus', array( $this, 'add_menu' ) );
90
+ add_action( "bd_admin_footer_for_{$this->item_type}", array( $this, 'modify_admin_footer' ) );
91
+ }
92
+
93
+ /**
94
+ * Check for nonce before executing the action.
95
+ *
96
+ * @since 5.5
97
+ * @param bool $result The current result.
98
+ * @param string $action Action name.
99
+ */
100
+ public function nonce_check( $result, $action ) {
101
+ $action_prefix = "delete_{$this->item_type}_";
102
+
103
+ if ( $action_prefix === substr( $action, 0, strlen( $action_prefix ) )
104
+ && check_admin_referer( "bd-{$this->page_slug}", "bd-{$this->page_slug}-nonce" ) ) {
105
+ return true;
106
+ } else {
107
+ return $result;
108
+ }
109
+ }
110
+
111
+ /**
112
+ * Add menu.
113
+ *
114
+ * @since 5.5
115
+ */
116
+ public function add_menu() {
117
+ $bd = BULK_DELETE();
118
+
119
+ $this->screen = add_submenu_page(
120
+ Bulk_Delete::POSTS_PAGE_SLUG,
121
+ $this->label['page_title'],
122
+ $this->label['menu_title'],
123
+ $this->capability,
124
+ $this->page_slug,
125
+ array( $this, 'render_page' )
126
+ );
127
+
128
+ add_action( "admin_print_scripts-{$this->screen}", array( $bd, 'add_script' ) );
129
+
130
+ add_action( "load-{$this->screen}", array( $this, 'add_settings_panel' ) );
131
+ add_action( "add_meta_boxes_{$this->screen}", array( $this, 'add_meta_boxes' ) );
132
+ }
133
+
134
+ /**
135
+ * Add settings Panel.
136
+ *
137
+ * @since 5.5
138
+ */
139
+ public function add_settings_panel() {
140
+ /**
141
+ * Add contextual help for admin screens.
142
+ *
143
+ * @since 5.1
144
+ */
145
+ do_action( 'bd_add_contextual_help', $this->screen );
146
+
147
+ // Trigger the add_meta_boxes hooks to allow meta boxes to be added
148
+ do_action( 'add_meta_boxes_' . $this->screen, null );
149
+
150
+ // Enqueue WordPress' script for handling the meta boxes
151
+ wp_enqueue_script( 'postbox' );
152
+ }
153
+
154
+ /**
155
+ * Modify help tabs for the current page.
156
+ *
157
+ * @since 5.5
158
+ * @param array $help_tabs Current list of help tabs.
159
+ * @param string $screen Current screen name.
160
+ * @return array Modified list of help tabs.
161
+ */
162
+ public function render_help_tab( $help_tabs, $screen ) {
163
+ if ( $this->screen == $screen ) {
164
+ $help_tabs = $this->add_help_tab( $help_tabs );
165
+ }
166
+
167
+ return $help_tabs;
168
+ }
169
+
170
+ /**
171
+ * Add help tabs.
172
+ * Help tabs can be added by overriding this function in the child class.
173
+ *
174
+ * @since 5.5
175
+ * @param array $help_tabs Current list of help tabs.
176
+ * @return array List of help tabs.
177
+ */
178
+ protected function add_help_tab( $help_tabs ) {
179
+ return $help_tabs;
180
+ }
181
+
182
+ /**
183
+ * Register meta boxes.
184
+ *
185
+ * @since 5.5
186
+ */
187
+ public function add_meta_boxes() {
188
+ /**
189
+ * Add meta box in delete users page.
190
+ * This hook can be used for adding additional meta boxes in delete users page
191
+ *
192
+ * @since 5.3
193
+ */
194
+ do_action( "bd_add_meta_box_for_{$this->item_type}", $this->screen, $this->page_slug );
195
+ }
196
+
197
+ /**
198
+ * Render the page.
199
+ *
200
+ * @since 5.5
201
+ */
202
+ public function render_page() {
203
+ ?>
204
+ <div class="wrap">
205
+ <h2><?php echo $this->label['page_title'];?></h2>
206
+ <?php settings_errors(); ?>
207
+
208
+ <form method = "post">
209
+ <?php
210
+ wp_nonce_field( "bd-{$this->page_slug}", "bd-{$this->page_slug}-nonce" );
211
+
212
+ // Used to save closed meta boxes and their order
213
+ wp_nonce_field( 'meta-box-order', 'meta-box-order-nonce', false );
214
+ wp_nonce_field( 'closedpostboxes', 'closedpostboxesnonce', false );
215
+ ?>
216
+ <div id = "poststuff">
217
+ <div id="post-body" class="metabox-holder columns-2">
218
+
219
+ <div class="notice notice-warning">
220
+ <p><strong><?php echo $this->messages['warning_message']; ?></strong></p>
221
+ </div>
222
+
223
+ <div id="postbox-container-1" class="postbox-container">
224
+ <iframe frameBorder="0" height = "1500" src = "http://sudarmuthu.com/projects/wordpress/bulk-delete/sidebar.php?color=<?php echo get_user_option( 'admin_color' ); ?>&version=<?php echo Bulk_Delete::VERSION; ?>"></iframe>
225
+ </div>
226
+
227
+ <div id="postbox-container-2" class="postbox-container">
228
+ <?php do_meta_boxes( '', 'advanced', null ); ?>
229
+ </div> <!-- #postbox-container-2 -->
230
+
231
+ </div> <!-- #post-body -->
232
+ </div><!-- #poststuff -->
233
+ </form>
234
+ </div><!-- .wrap -->
235
+ <?php
236
+ /**
237
+ * Runs just before displaying the footer text in the admin page.
238
+ *
239
+ * This action is primarily for adding extra content in the footer of admin page.
240
+ *
241
+ * @since 5.0
242
+ */
243
+ do_action( "bd_admin_footer_for_{$this->item_type}" );
244
+ }
245
+
246
+ /**
247
+ * Modify admin footer in Bulk Delete plugin pages.
248
+ *
249
+ * @since 5.5
250
+ */
251
+ public function modify_admin_footer() {
252
+ add_filter( 'admin_footer_text', 'bd_add_rating_link' );
253
+ }
254
+
255
+ /**
256
+ * Getter for screen.
257
+ *
258
+ * @return string Current value of screen
259
+ */
260
+ public function get_screen() {
261
+ return $this->screen;
262
+ }
263
+
264
+ /**
265
+ * Getter for page_slug.
266
+ *
267
+ * @return string Current value of page_slug
268
+ */
269
+ public function get_page_slug() {
270
+ return $this->page_slug;
271
+ }
272
+ }
273
+ ?>
include/class-bd-edd-api-wrapper.php DELETED
@@ -1,154 +0,0 @@
1
- <?php
2
- /**
3
- * Wrapper for EDD API
4
- *
5
- * @package Bulk_Delete
6
- * @subpackage EDD
7
- * @author Sudar
8
- * @since 5.0
9
- */
10
- class BD_EDD_API_Wrapper {
11
-
12
- /**
13
- * Store url
14
- *
15
- * @since 5.0
16
- */
17
- const STORE_URL = 'http://bulkwp.com';
18
-
19
- /**
20
- * Check license
21
- *
22
- * @since 5.0
23
- * @static
24
- * @param string $addon Addon name
25
- * @param string $license The license code
26
- * @return bool|array False if request fails, API response otherwise
27
- */
28
- public static function check_license( $addon, $license ) {
29
- $api_params = array(
30
- 'edd_action'=> 'check_license',
31
- 'license' => trim( $license ),
32
- 'item_name' => urlencode( $addon ),
33
- 'url' => home_url()
34
- );
35
-
36
- $license_data = array(
37
- 'license' => $license,
38
- 'item_name' => $addon,
39
- 'validity' => 'invalid'
40
- );
41
-
42
- $response = self::call_edd_api( $api_params );
43
-
44
- if ( $response && isset( $response->license ) ) {
45
- if ( 'valid' == $response->license ) {
46
- $license_data['license'] = $license;
47
- $license_data['validity'] = 'valid';
48
- $license_data['expires'] = $response->expires;
49
- $license_data['addon-name'] = $response->item_name;
50
- } elseif ( 'invalid' == $response->license ) {
51
- $license_data['validity'] = 'invalid';
52
- } elseif ( 'site_inactive' == $response->license ) {
53
- $license_data['validity'] = 'invalid';
54
- }
55
-
56
- return $license_data;
57
- }
58
-
59
- return FALSE;
60
- }
61
-
62
- /**
63
- * Activate license
64
- *
65
- * @since 5.0
66
- * @static
67
- * @param string $addon The addon that needs to be activated
68
- * @param string $license The license code
69
- * @return bool|array False if request fails, License info otherwise
70
- */
71
- public static function activate_license( $addon, $license ) {
72
- $api_params = array(
73
- 'edd_action'=> 'activate_license',
74
- 'license' => trim( $license ),
75
- 'item_name' => urlencode( $addon ),
76
- 'url' => home_url()
77
- );
78
-
79
- $response = self::call_edd_api( $api_params );
80
-
81
- if ( $response && isset( $response->success ) ) {
82
- if ( 'true' == $response->success ) {
83
- return array(
84
- 'license' => $license,
85
- 'validity' => 'valid',
86
- 'expires' => $response->expires,
87
- 'addon-name' => $response->item_name
88
- );
89
- } else {
90
- $err_response = array(
91
- 'validity' => 'invalid'
92
- );
93
-
94
- if ( isset( $response->error ) ) {
95
- $err_response['error'] = $response->error;
96
- }
97
-
98
- return $err_response;
99
- }
100
- }
101
-
102
- return FALSE;
103
- }
104
-
105
- /**
106
- * Deactivate License
107
- *
108
- * @since 5.0
109
- * @static
110
- * @param string $addon The addon that needs to be deactivated
111
- * @param string $license The license code
112
- * @return bool True if deactivated, False otherwise
113
- */
114
- public static function deactivate_license( $addon, $license ) {
115
- $api_params = array(
116
- 'edd_action'=> 'deactivate_license',
117
- 'license' => trim( $license ),
118
- 'item_name' => urlencode( $addon ),
119
- 'url' => home_url()
120
- );
121
-
122
- $response = self::call_edd_api( $api_params );
123
-
124
- if ( $response && isset( $response->license ) ) {
125
- if ( 'deactivated' == $response->license ) {
126
- return TRUE;
127
- }
128
- }
129
-
130
- return FALSE;
131
- }
132
-
133
- /**
134
- * Call the EDD API
135
- *
136
- * @since 5.0
137
- * @static
138
- * @access private
139
- * @param array $api_params Parameters for API
140
- * @return bool|array $license_data False if request fails, API response otherwise
141
- */
142
- private static function call_edd_api( $api_params ) {
143
- $response = wp_remote_get( add_query_arg( $api_params, self::STORE_URL ), array( 'timeout' => 15, 'sslverify' => false ) );
144
-
145
- // make sure the response came back okay
146
- if ( is_wp_error( $response ) ) {
147
- return false;
148
- }
149
-
150
- $license_object = json_decode( wp_remote_retrieve_body( $response ) );
151
- return $license_object;
152
- }
153
- }
154
- ?>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
include/class-bd-license-handler.php DELETED
@@ -1,187 +0,0 @@
1
- <?php
2
- /**
3
- * License Handler for Bulk Delete Addons
4
- *
5
- * @package Bulk_Delete
6
- * @subpackage License
7
- * @author Sudar
8
- * @since 5.0
9
- */
10
- class BD_License_Handler {
11
-
12
- /**
13
- * Name of the addon
14
- *
15
- * @since 5.0
16
- */
17
- private $addon_name;
18
-
19
- /**
20
- * Code of the addon
21
- *
22
- * @since 5.0
23
- */
24
- private $addon_code;
25
-
26
- /**
27
- * Version of the plugin
28
- *
29
- * @since 5.0
30
- */
31
- private $version;
32
-
33
- /**
34
- * plugin file name
35
- *
36
- * @since 5.0
37
- */
38
- private $plugin_file;
39
-
40
- /**
41
- * Author of the plugin
42
- *
43
- * @since 5.0
44
- */
45
- private $author;
46
-
47
- /**
48
- * Constructor
49
- *
50
- * @since 5.0
51
- *
52
- * @param string $addon_name Name of the addon
53
- * @param string $addon_code Code of the addon
54
- * @param string $version Version of the addon
55
- * @param string $plugin_file Addon file name
56
- * @param string $author Author of the addon
57
- */
58
- function __construct( $addon_name, $addon_code, $version, $plugin_file, $author = 'Sudar Muthu' ) {
59
-
60
- $this->addon_name = $addon_name;
61
- $this->addon_code = $addon_code;
62
- $this->version = $version;
63
- $this->plugin_file = $plugin_file;
64
- $this->author = $author;
65
-
66
- $this->hooks();
67
-
68
- if ( BD_License::has_valid_license( $this->addon_name, $this->addon_code ) ) {
69
- $license_code = BD_License::get_license_code( $this->addon_code );
70
- if ( FALSE != $license_code ) {
71
- $this->hook_updater( $license_code );
72
- }
73
- }
74
- }
75
-
76
- /**
77
- * Start the updater
78
- *
79
- * @since 5.0
80
- * @access private
81
- * @param string $license_code License Code
82
- */
83
- private function hook_updater( $license_code ) {
84
- $bd = BULK_DELETE();
85
-
86
- if ( ! class_exists( 'EDD_SL_Plugin_Updater' ) ) {
87
- require_once Bulk_Delete::$PLUGIN_DIR . '/include/libraries/EDD_SL_Plugin_Updater.php';
88
- }
89
-
90
- $this->updater = new EDD_SL_Plugin_Updater( BD_EDD_API_Wrapper::STORE_URL, $this->plugin_file, array(
91
- 'version' => $this->version,
92
- 'license' => $license_code,
93
- 'item_name' => $this->addon_name,
94
- 'addon_code' => $this->addon_code,
95
- 'author' => $this->author,
96
- 'url' => home_url()
97
- ));
98
- }
99
-
100
- /**
101
- * setup hooks
102
- *
103
- * @access private
104
- * @since 5.0
105
- */
106
- private function hooks() {
107
- add_action( 'bd_license_form' , array( &$this, 'display_license_form' ) );
108
- add_action( 'bd_license_field', array( &$this, 'add_license_field' ) );
109
- add_filter( 'bd_license_input', array( &$this, 'parse_license_input' ), 1 );
110
- }
111
-
112
- /**
113
- * Decide whether to display the license form or not
114
- *
115
- * @since 5.0
116
- */
117
- public function display_license_form() {
118
- if ( ! BD_License::has_valid_license( $this->addon_name, $this->addon_code ) ) {
119
- $bd = BULK_DELETE();
120
- $bd->display_activate_license_form = TRUE;
121
- }
122
- }
123
-
124
- /**
125
- * Add the license field to license form
126
- *
127
- * @since 5.0
128
- */
129
- public function add_license_field() {
130
- if ( ! BD_License::has_valid_license( $this->addon_name, $this->addon_code ) ) {
131
- add_settings_field(
132
- $this->addon_code, // ID
133
- '"' . $this->addon_name . '" ' . __( 'Addon License Key', 'bulk-delete' ), // Title
134
- array( &$this, 'print_license_key_field' ), // Callback
135
- Bulk_Delete::ADDON_PAGE_SLUG, // Page
136
- Bulk_Delete::SETTING_SECTION_ID // Section
137
- );
138
- }
139
- }
140
-
141
- /**
142
- * Print the license field
143
- *
144
- * @since 5.0
145
- */
146
- public function print_license_key_field() {
147
- if ( ! BD_License::has_valid_license( $this->addon_name, $this->addon_code ) ) {
148
- printf(
149
- '<input type="text" id="%s" name="%s[%s]" placeholder="%s">',
150
- $this->addon_code,
151
- Bulk_Delete::SETTING_OPTION_NAME,
152
- $this->addon_code,
153
- __( 'Enter license key', 'bulk-delete' )
154
- );
155
- }
156
- }
157
-
158
- /**
159
- * Parse the license key and activate it if needed.
160
- * If the key is invalid, then don't save it in the setting option
161
- *
162
- * @since 5.0
163
- */
164
- public function parse_license_input( $input ) {
165
- if ( is_array( $input ) && key_exists( $this->addon_code, $input ) ) {
166
- $license_code = trim( $input[ $this->addon_code ] );
167
-
168
- if ( ! empty( $license_code ) ) {
169
- if ( ! BD_License::has_valid_license( $this->addon_name, $this->addon_code ) ) {
170
- $activated = BD_License::activate_license( $this->addon_name, $this->addon_code, $license_code );
171
- if ( ! $activated ) {
172
- unset( $input[ $this->addon_code ] );
173
- }
174
- }
175
- } else {
176
- unset( $input[ $this->addon_code ] );
177
- }
178
- } else {
179
- if ( BD_License::has_valid_license( $this->addon_name, $this->addon_code ) ) {
180
- $license_code = BD_License::get_license_code( $this->addon_code );
181
- $input[ $this->addon_code ] = $license_code;
182
- }
183
- }
184
- return $input;
185
- }
186
- }
187
- ?>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
include/class-bd-license.php DELETED
@@ -1,478 +0,0 @@
1
- <?php
2
- /**
3
- * Addon license related functions
4
- *
5
- * @package Bulk_Delete
6
- * @subpackage addon
7
- * @author Sudar
8
- * @since 5.0
9
- */
10
- class BD_License {
11
- /**
12
- * Output addon page content
13
- *
14
- * @since 5.0
15
- * @static
16
- */
17
- public static function display_addon_page() {
18
- if( !class_exists( 'WP_List_Table' ) ){
19
- require_once( ABSPATH . WPINC . '/class-wp-list-table.php' );
20
- }
21
-
22
- if ( !class_exists( 'License_List_Table' ) ) {
23
- require_once Bulk_Delete::$PLUGIN_DIR . '/include/class-license-list-table.php';
24
- }
25
-
26
- $license_list_table = new License_List_Table();
27
- $license_list_table->prepare_items();
28
- ?>
29
- <div class="wrap">
30
- <h2><?php _e( 'Addon Licenses', 'bulk-delete' );?></h2>
31
- <?php settings_errors(); ?>
32
- <form method="post" action="options.php">
33
- <?php
34
- $license_list_table->display();
35
- do_action( 'bd_license_form' );
36
- BD_License::display_available_addon_list();
37
- ?>
38
- </form>
39
- </div>
40
- <?php
41
- /**
42
- * Runs just before displaying the footer text in the "Addon" admin page.
43
- *
44
- * This action is primarily for adding extra content in the footer of "Addon" admin page.
45
- *
46
- * @since 5.0
47
- */
48
- do_action( 'bd_admin_footer_addon_page' );
49
- }
50
-
51
- /**
52
- * Display License form
53
- *
54
- * @since 5.0
55
- * @static
56
- */
57
- public static function display_activate_license_form() {
58
- $bd = BULK_DELETE();
59
- if ( isset( $bd->display_activate_license_form ) && TRUE == $bd->display_activate_license_form ) {
60
- // This prints out all hidden setting fields
61
- settings_fields( Bulk_Delete::SETTING_OPTION_GROUP );
62
- do_settings_sections( Bulk_Delete::ADDON_PAGE_SLUG );
63
- submit_button( __( 'Activate License', 'bulk-delete' ) );
64
- }
65
- }
66
-
67
- /**
68
- * Check if an addon has a valid license or not
69
- *
70
- * @since 5.0
71
- * @static
72
- * @param string $addon_name Addon Name
73
- * @param string $addon_code Addon short Name
74
- * @return bool True if addon has a valid license, False otherwise
75
- */
76
- public static function has_valid_license( $addon_name, $addon_code ) {
77
- $key = Bulk_Delete::LICENSE_CACHE_KEY_PREFIX . $addon_code;
78
- $license_data = get_option( $key, FALSE );
79
-
80
- if ( ! $license_data ) {
81
- // if data about license is not present, then fetch it.
82
- // ideally this should not happen
83
- $licenses = get_option( Bulk_Delete::SETTING_OPTION_NAME );
84
- if ( is_array( $licenses ) && key_exists( $addon_code, $licenses ) ) {
85
- $license_data = BD_EDD_API_Wrapper::check_license( $addon_name, $licenses[ $addon_code ] );
86
- update_option( $key, $license_data );
87
- }
88
- }
89
-
90
- // TODO Encapsulate below code into a separate function
91
- if ( $license_data && is_array( $license_data ) && key_exists( 'validity', $license_data ) ) {
92
- if ( 'valid' == $license_data['validity'] ) {
93
- if ( strtotime( 'now' ) < strtotime( $license_data['expires'] ) ) {
94
- return TRUE;
95
- } else {
96
- $license_data['validity'] = 'expired';
97
- update_option( $key, $license_data );
98
- }
99
- }
100
- }
101
-
102
- return FALSE;
103
- }
104
-
105
- /**
106
- * Get the list of all licenses information to be displayed in the license page
107
- *
108
- * @since 5.0
109
- * @static
110
- * @return array $license_data License information
111
- */
112
- public static function get_licenses() {
113
- $licenses = get_option( Bulk_Delete::SETTING_OPTION_NAME );
114
- $license_data = array();
115
-
116
- if ( is_array( $licenses ) ) {
117
- foreach ( $licenses as $addon_code => $license ) {
118
- $license_data[ $addon_code ] = self::get_license( $addon_code, $license );
119
- }
120
- }
121
-
122
- return $license_data;
123
- }
124
-
125
- /**
126
- * Retrieve license information about an addon
127
- *
128
- * @since 5.0
129
- * @static
130
- * @param string $addon_code Addon short name
131
- * @return object $license_data License information
132
- */
133
- public static function get_license( $addon_code ) {
134
- $bd = BULK_DELETE();
135
- $key = Bulk_Delete::LICENSE_CACHE_KEY_PREFIX . $addon_code;
136
- $license_data = get_option( $key, FALSE );
137
-
138
- if ( $license_data && is_array( $license_data ) && key_exists( 'validity', $license_data ) ) {
139
- if ( 'valid' == $license_data['validity'] ) {
140
- if ( strtotime( 'now' ) < strtotime( $license_data['expires'] ) ) {
141
- // valid license
142
- } else {
143
- $license_data['validity'] = 'expired';
144
- update_option( $key, $license_data );
145
- }
146
- }
147
- }
148
-
149
- return $license_data;
150
- }
151
-
152
- /**
153
- * Get license code of an addon
154
- *
155
- * @since 5.0
156
- * @static
157
- * @param string $addon_code Addon code
158
- * @return bool|string License code of the addon, False otherwise
159
- */
160
- public static function get_license_code( $addon_code ) {
161
- $licenses = get_option( Bulk_Delete::SETTING_OPTION_NAME );
162
-
163
- if ( is_array($licenses ) && key_exists( $addon_code, $licenses ) ) {
164
- return $licenses[ $addon_code ];
165
- }
166
- else {
167
- return FALSE;
168
- }
169
- }
170
-
171
- /**
172
- * Deactivate license
173
- *
174
- * @since 5.0
175
- * @static
176
- */
177
- public static function deactivate_license() {
178
- if ( check_admin_referer( 'bd-deactivate-license', 'bd-deactivate-license-nonce' ) ) {
179
- $msg = array( 'msg' => '', 'type' => 'error' );
180
- $addon_code = $_GET['addon-code'];
181
- $license_data = self::get_license( $addon_code );
182
-
183
- $license = $license_data['license'];
184
- $addon_name = $license_data['addon-name'];
185
-
186
- $deactivated = BD_EDD_API_Wrapper::deactivate_license( $addon_name, $license );
187
-
188
- if ( $deactivated ) {
189
- self::delete_license_from_cache( $addon_code );
190
- $msg['msg'] = sprintf( __( 'The license key for "%s" addon was successfully deactivated', 'bulk-delete' ), $addon_name );
191
- $msg['type'] = 'updated';
192
-
193
- } else {
194
- self::validate_license( $addon_code, $addon_name );
195
- $msg['msg'] = sprintf( __( 'There was some problem while trying to deactivate license key for "%s" addon. Kindly try again', 'bulk-delete' ), $addon_name );
196
- }
197
-
198
- add_settings_error(
199
- Bulk_Delete::ADDON_PAGE_SLUG,
200
- 'license-deactivation',
201
- $msg['msg'],
202
- $msg['type']
203
- );
204
- }
205
- }
206
-
207
- /**
208
- * Delete license
209
- *
210
- * @since 5.0
211
- * @static
212
- */
213
- public static function delete_license() {
214
- if ( check_admin_referer( 'bd-deactivate-license', 'bd-deactivate-license-nonce' ) ) {
215
- $msg = array( 'msg' => '', 'type' => 'updated' );
216
- $addon_code = $_GET['addon-code'];
217
-
218
- self::delete_license_from_cache( $addon_code );
219
-
220
- $msg['msg'] = __( 'The license key was successfully deleted', 'bulk-delete' );
221
-
222
- add_settings_error(
223
- Bulk_Delete::ADDON_PAGE_SLUG,
224
- 'license-deleted',
225
- $msg['msg'],
226
- $msg['type']
227
- );
228
- }
229
- }
230
-
231
- /**
232
- * Delete license information from cache
233
- *
234
- * @since 5.0
235
- * @static
236
- * @param string $addon_code Addon code
237
- */
238
- private static function delete_license_from_cache( $addon_code ) {
239
- $key = Bulk_Delete::LICENSE_CACHE_KEY_PREFIX . $addon_code;
240
- delete_option( $key );
241
-
242
- $licenses = get_option( Bulk_Delete::SETTING_OPTION_NAME );
243
-
244
- if ( is_array( $licenses ) && key_exists( $addon_code, $licenses ) ) {
245
- unset( $licenses[ $addon_code ] );
246
- }
247
- update_option( Bulk_Delete::SETTING_OPTION_NAME, $licenses );
248
- }
249
-
250
- /*
251
- * Activate license
252
- *
253
- * @since 5.0
254
- * @static
255
- * @param string $addon_name Addon name
256
- * @param string $addon_code Addon code
257
- * @param string $license License code
258
- * @return bool $valid True if valid, False otherwise
259
- */
260
- public static function activate_license( $addon_name, $addon_code, $license ) {
261
- $license_data = BD_EDD_API_Wrapper::activate_license( $addon_name, $license );
262
- $valid = FALSE;
263
- $msg = array(
264
- 'msg' => sprintf( __( 'There was some problem in contacting our store to activate the license key for "%s" addon', 'bulk-delete' ), $addon_name ),
265
- 'type' => 'error'
266
- );
267
-
268
- if ( $license_data && is_array( $license_data ) && key_exists( 'validity', $license_data ) ) {
269
- if ( 'valid' == $license_data['validity'] ) {
270
- $key = Bulk_Delete::LICENSE_CACHE_KEY_PREFIX . $addon_code;
271
- $license_data['addon-code'] = $addon_code;
272
- update_option( $key, $license_data );
273
-
274
- $msg['msg'] = sprintf( __( 'The license key for "%s" addon was successfully activated. The addon will get updates automatically till the license key is valid.', 'bulk-delete' ), $addon_name );
275
- $msg['type'] = 'updated';
276
- $valid = TRUE;
277
- } else {
278
- if ( key_exists( 'error', $license_data ) ) {
279
- switch( $license_data['error'] ) {
280
-
281
- case 'no_activations_left':
282
- $msg['msg'] = sprintf( __( 'The license key for "%s" addon doesn\'t have any more activations left. Kindly buy a new license.', 'bulk-delete' ), $addon_name );
283
- break;
284
-
285
- case 'revoked':
286
- $msg['msg'] = sprintf( __( 'The license key for "%s" addon is revoked. Kindly buy a new license.', 'bulk-delete' ), $addon_name );
287
- break;
288
-
289
- case 'expired':
290
- $msg['msg'] = sprintf( __( 'The license key for "%s" addon has expired. Kindly buy a new license.', 'bulk-delete' ), $addon_name );
291
- break;
292
-
293
- default:
294
- $msg['msg'] = sprintf( __( 'The license key for "%s" addon is invalid', 'bulk-delete' ), $addon_name );
295
- break;
296
- }
297
- }
298
- }
299
- }
300
-
301
- add_settings_error(
302
- Bulk_Delete::ADDON_PAGE_SLUG,
303
- 'license-activation',
304
- $msg['msg'],
305
- $msg['type']
306
- );
307
-
308
- if ( !$valid && isset( $key ) ) {
309
- delete_option( $key );
310
- }
311
- return $valid;
312
- }
313
-
314
- /**
315
- * Validate the license for the given addon
316
- *
317
- * @since 5.0
318
- * @static
319
- * @param string $addon_name Addon name
320
- * @param string $addon_code Addon code
321
- */
322
- public static function validate_license( $addon_code, $addon_name ) {
323
- $key = Bulk_Delete::LICENSE_CACHE_KEY_PREFIX . $addon_code;
324
-
325
- $licenses = get_option( Bulk_Delete::SETTING_OPTION_NAME );
326
- if ( is_array( $licenses ) && key_exists( $addon_code, $licenses ) ) {
327
- $license_data = BD_EDD_API_Wrapper::check_license( $addon_name, $licenses[ $addon_code ] );
328
- if ( $license_data ) {
329
- $license_data['addon-code'] = $addon_code;
330
- $license_data['addon-name'] = $license_data['item_name'];
331
- update_option( $key, $license_data );
332
- } else {
333
- delete_option( $key );
334
- }
335
- }
336
-
337
- if ( $license_data && is_array( $license_data ) && key_exists( 'validity', $license_data ) ) {
338
- if ( 'valid' == $license_data['validity'] ) {
339
- if ( strtotime( 'now' ) > strtotime( $license_data['expires'] ) ) {
340
- $license_data['validity'] = 'expired';
341
- update_option( $key, $license_data );
342
- }
343
- }
344
- }
345
- }
346
-
347
- /**
348
- * Display information about all available addons
349
- *
350
- * @since 5.0
351
- * @static
352
- */
353
- public static function display_available_addon_list() {
354
-
355
- echo '<p>';
356
- _e('The following are the list of pro addons that are currently available for purchase.', 'bulk-delete');
357
- echo '</p>';
358
-
359
- echo '<ul style="list-style:disc; padding-left:35px">';
360
-
361
- echo '<li>';
362
- echo '<strong>', __('Delete posts by custom field', 'bulk-delete'), '</strong>', ' - ';
363
- echo __('Adds the ability to delete posts based on custom fields', 'bulk-delete');
364
- echo ' <a href = "http://bulkwp.com/addons/bulk-delete-posts-by-custom-field/?utm_source=wpadmin&utm_campaign=BulkDelete&utm_medium=addonlist&utm_content=bd-cf">', __('More Info', 'bulk-delete'), '</a>.';
365
- echo '</li>';
366
-
367
- echo '<li>';
368
- echo '<strong>', __( 'Delete posts by title', 'bulk-delete' ), '</strong>', ' - ';
369
- echo __( 'Adds the ability to delete posts based on title', 'bulk-delete' );
370
- echo ' <a href = "http://bulkwp.com/addons/bulk-delete-posts-by-title/?utm_source=wpadmin&utm_campaign=BulkDelete&utm_medium=addonlist&utm_content=bd-ti">', __( 'More Info', 'bulk-delete' ), '</a>.';
371
- echo '</li>';
372
-
373
- echo '<li>';
374
- echo '<strong>', __( 'Delete posts by duplicate title', 'bulk-delete' ), '</strong>', ' - ';
375
- echo __( 'Adds the ability to delete posts based on duplicate title', 'bulk-delete' );
376
- echo ' <a href = "http://bulkwp.com/addons/bulk-delete-posts-by-duplicate-title/?utm_source=wpadmin&utm_campaign=BulkDelete&utm_medium=addonlist&utm_content=bd-dti">', __( 'More Info', 'bulk-delete' ), '</a>.';
377
- echo '</li>';
378
-
379
- echo '<li>';
380
- echo '<strong>', __( 'Delete posts by attachment', 'bulk-delete' ), '</strong>', ' - ';
381
- echo __( 'Adds the ability to delete posts based on whether it contains attachment or not', 'bulk-delete' );
382
- echo ' <a href = "http://bulkwp.com/addons/bulk-delete-posts-by-attachment/?utm_source=wpadmin&utm_campaign=BulkDelete&utm_medium=addonlist&utm_content=bd-p-at">', __( 'More Info', 'bulk-delete' ), '</a>.';
383
- echo '</li>';
384
-
385
- echo '<li>';
386
- echo '<strong>', __( 'Delete posts by user role', 'bulk-delete' ), '</strong>', ' - ';
387
- echo __( 'Adds the ability to delete posts based on user role', 'bulk-delete' );
388
- echo ' <a href = "http://bulkwp.com/addons/bulk-delete-posts-by-user-role/?utm_source=wpadmin&utm_campaign=BulkDelete&utm_medium=addonlist&utm_content=bd-ur">', __( 'More Info', 'bulk-delete' ), '</a>.';
389
- echo '</li>';
390
-
391
- echo '<li>';
392
- echo '<strong>', __( 'Delete from trash', 'bulk-delete' ), '</strong>', ' - ';
393
- echo __( 'Adds the ability to delete posts and pages from trash', 'bulk-delete' );
394
- echo ' <a href = "http://bulkwp.com/addons/bulk-delete-from-trash/?utm_source=wpadmin&utm_campaign=BulkDelete&utm_medium=addonlist&utm_content=bd-th">', __( 'More Info', 'bulk-delete' ), '</a>.';
395
- echo '</li>';
396
-
397
- echo '<li>';
398
- echo '<strong>', __( 'Scheduler Email', 'bulk-delete' ), '</strong>', ' - ';
399
- echo __( 'Sends an email every time a Bulk WP scheduler runs', 'bulk-delete' );
400
- echo ' <a href = "http://bulkwp.com/addons/scheduler-email/?utm_source=wpadmin&utm_campaign=BulkDelete&utm_medium=addonlist&utm_content=bd-se">', __( 'More Info', 'bulk-delete' ), '</a>.';
401
- echo '</li>';
402
-
403
- echo '<li>';
404
- echo '<strong>', __('Scheduler for deleting Posts by Category', 'bulk-delete'), '</strong>', ' - ';
405
- echo __('Adds the ability to schedule auto delete of posts based on category', 'bulk-delete');
406
- echo ' <a href = "http://bulkwp.com/addons/scheduler-for-deleting-posts-by-category/?utm_source=wpadmin&utm_campaign=BulkDelete&utm_medium=addonlist&utm_content=bd-sc">', __('More Info', 'bulk-delete'), '</a>.';
407
- echo '</li>';
408
-
409
- echo '<li>';
410
- echo '<strong>', __('Scheduler for deleting Posts by Tag', 'bulk-delete'), '</strong>', ' - ';
411
- echo __('Adds the ability to schedule auto delete of posts based on tag', 'bulk-delete');
412
- echo ' <a href = "http://bulkwp.com/addons/scheduler-for-deleting-posts-by-tag/?utm_source=wpadmin&utm_campaign=BulkDelete&utm_medium=addonlist&utm_content=bd-st">', __('More Info', 'bulk-delete'), '</a>.';
413
- echo '</li>';
414
-
415
- echo '<li>';
416
- echo '<strong>', __('Scheduler for deleting Posts by Custom Taxonomy', 'bulk-delete'), '</strong>', ' - ';
417
- echo __('Adds the ability to schedule auto delete of posts based on custom taxonomy', 'bulk-delete');
418
- echo ' <a href = "http://bulkwp.com/addons/scheduler-for-deleting-posts-by-taxonomy/?utm_source=wpadmin&utm_campaign=BulkDelete&utm_medium=addonlist&utm_content=bd-stx">', __('More Info', 'bulk-delete'), '</a>.';
419
- echo '</li>';
420
-
421
- echo '<li>';
422
- echo '<strong>', __('Scheduler for deleting Posts by Custom Post Type', 'bulk-delete'), '</strong>', ' - ';
423
- echo __('Adds the ability to schedule auto delete of posts based on custom post type', 'bulk-delete');
424
- echo ' <a href = "http://bulkwp.com/addons/scheduler-for-deleting-posts-by-post-type/?utm_source=wpadmin&utm_campaign=BulkDelete&utm_medium=addonlist&utm_content=bd-spt">', __('More Info', 'bulk-delete'), '</a>.';
425
- echo '</li>';
426
-
427
- echo '<li>';
428
- echo '<strong>', __('Scheduler for deleting Posts by Post Status', 'bulk-delete'), '</strong>', ' - ';
429
- echo __('Adds the ability to schedule auto delete of posts based on post status like drafts, pending posts, scheduled posts etc.', 'bulk-delete');
430
- echo ' <a href = "http://bulkwp.com/addons/scheduler-for-deleting-posts-by-status/?utm_source=wpadmin&utm_campaign=BulkDelete&utm_medium=addonlist&utm_content=bd-sps">', __('More Info', 'bulk-delete'), '</a>.';
431
- echo '</li>';
432
-
433
- echo '<li>';
434
- echo '<strong>', __('Scheduler for deleting Pages by Status', 'bulk-delete'), '</strong>', ' - ';
435
- echo __('Adds the ability to schedule auto delete pages based on status', 'bulk-delete');
436
- echo ' <a href = "http://bulkwp.com/addons/scheduler-for-deleting-pages-by-status/?utm_source=wpadmin&utm_campaign=BulkDelete&utm_medium=addonlist&utm_content=bd-sp">', __('More Info', 'bulk-delete'), '</a>.';
437
- echo '</li>';
438
-
439
- echo '<li>';
440
- echo '<strong>', __('Scheduler for deleting Users by User Role', 'bulk-delete'), '</strong>', ' - ';
441
- echo __('Adds the ability to schedule auto delete of users based on user role', 'bulk-delete');
442
- echo ' <a href = "http://bulkwp.com/addons/scheduler-for-deleting-users-by-role/?utm_source=wpadmin&utm_campaign=BulkDelete&utm_medium=addonlist&utm_content=bd-u-ur">', __('More Info', 'bulk-delete'), '</a>.';
443
- echo '</li>';
444
-
445
- echo '<li>';
446
- echo '<strong>', __( 'Delete Post Meta Fields', 'bulk-delete' ), '</strong>', ' - ';
447
- echo __( 'Adds the ability to delete post meta fields based on value and to schedule automatic deletion', 'bulk-delete' );
448
- echo ' <a href = "http://bulkwp.com/addons/bulk-delete-post-meta/?utm_source=wpadmin&utm_campaign=BulkDelete&utm_medium=addonlist&utm_content=bd-m-p">', __( 'More Info', 'bulk-delete' ), '</a>.';
449
- echo '</li>';
450
-
451
- echo '<li>';
452
- echo '<strong>', __( 'Delete Comment Meta Fields', 'bulk-delete' ), '</strong>', ' - ';
453
- echo __( 'Adds the ability to delete comment meta fields based on value and to schedule automatic deletion', 'bulk-delete' );
454
- echo ' <a href = "http://bulkwp.com/addons/bulk-delete-comment-meta/?utm_source=wpadmin&utm_campaign=BulkDelete&utm_medium=addonlist&utm_content=bd-m-c">', __( 'More Info', 'bulk-delete' ), '</a>.';
455
- echo '</li>';
456
-
457
- echo '<li>';
458
- echo '<strong>', __( 'Delete User Meta Fields', 'bulk-delete' ), '</strong>', ' - ';
459
- echo __( 'Adds the ability to delete user meta fields based on value and to schedule automatic deletion', 'bulk-delete' );
460
- echo ' <a href = "http://bulkwp.com/addons/bulk-delete-user-meta/?utm_source=wpadmin&utm_campaign=BulkDelete&utm_medium=addonlist&utm_content=bd-m-u">', __( 'More Info', 'bulk-delete' ), '</a>.';
461
- echo '</li>';
462
-
463
- echo '<li>';
464
- echo '<strong>', __( 'Delete Jetpack Contact Form Messages', 'bulk-delete' ), '</strong>', ' - ';
465
- echo __( 'Adds the ability to delete Jetpack Contact Form Messages based on filters and to schedule automatic deletion', 'bulk-delete' );
466
- echo ' <a href = "http://bulkwp.com/addons/bulk-delete-jetpack-contact-form-messages/?utm_source=wpadmin&utm_campaign=BulkDelete&utm_medium=addonlist&utm_content=bd-jcm">', __( 'More Info', 'bulk-delete' ), '</a>.';
467
- echo '</li>';
468
-
469
- echo '</ul>';
470
- }
471
- }
472
-
473
- // hooks
474
- add_action( 'bd_license_form' , array( 'BD_License', 'display_activate_license_form' ), 100 );
475
- add_action( 'bd_deactivate_license', array( 'BD_License', 'deactivate_license' ) );
476
- add_action( 'bd_delete_license' , array( 'BD_License', 'delete_license' ) );
477
- add_action( 'bd_validate_license' , array( 'BD_License', 'validate_license' ), 10, 2 );
478
- ?>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
include/class-bd-settings.php DELETED
@@ -1,58 +0,0 @@
1
- <?php
2
- /**
3
- * Encapsulates the settings API for Bulk Delete Plugin
4
- *
5
- * @package Bulk_Delete
6
- * @subpackage Settings
7
- * @author Sudar
8
- * @since 5.0
9
- */
10
- class BD_Settings {
11
- /**
12
- * Register settings used by the plugin
13
- *
14
- * @since 5.0
15
- * @static
16
- */
17
- public static function create_settings() {
18
- register_setting(
19
- Bulk_Delete::SETTING_OPTION_GROUP, // Option group
20
- Bulk_Delete::SETTING_OPTION_NAME, // Option name
21
- array( 'BD_Settings', 'check_license' ) // Sanitize
22
- );
23
-
24
- add_settings_section(
25
- Bulk_Delete::SETTING_SECTION_ID, // ID
26
- __( 'Add Addon License', 'bulk-delete' ), // Title
27
- '__return_null', // Callback
28
- Bulk_Delete::ADDON_PAGE_SLUG // Page
29
- );
30
-
31
- /**
32
- * Runs just after registering license form fields
33
- *
34
- * This action is primarily for adding more fields to the license form
35
- * @since 5.0
36
- */
37
- do_action( 'bd_license_field' );
38
- }
39
-
40
- /**
41
- * Callback for sanitizing settings
42
- *
43
- * @since 5.0
44
- * @static
45
- */
46
- public static function check_license( $input ) {
47
- /**
48
- * Filter license form inputs
49
- *
50
- * @since 5.0
51
- */
52
- return apply_filters( 'bd_license_input', $input );
53
- }
54
- }
55
-
56
- // hooks
57
- add_action( 'admin_init', array( 'BD_Settings', 'create_settings' ), 100 );
58
- ?>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
include/class-bulk-delete-by-days.php CHANGED
@@ -1,35 +1,16 @@
1
  <?php
2
  /**
3
- * Class that encapsulates the deletion of posts based on days
4
  *
5
- * @package Bulk Delete
6
- * @author Sudar
7
  */
8
- class Bulk_Delete_By_Days {
9
- var $days;
10
- var $op;
11
 
12
- public function __construct(){
13
- add_action( 'parse_query', array( $this, 'parse_query' ) );
14
- }
15
-
16
- public function parse_query( $query ) {
17
- if( isset( $query->query_vars['days'] ) ){
18
- $this->days = $query->query_vars['days'];
19
- $this->op = $query->query_vars['op'];
20
-
21
- add_filter( 'posts_where', array( $this, 'filter_where' ) );
22
- add_filter( 'posts_selection', array( $this, 'remove_where' ) );
23
- }
24
- }
25
-
26
- public function filter_where($where = '') {
27
- $where .= " AND post_date " . $this->op . " '" . date('y-m-d', strtotime('-' . $this->days . ' days')) . "'";
28
- return $where;
29
- }
30
-
31
- public function remove_where() {
32
- remove_filter( 'posts_where', array( $this, 'filter_where' ) );
33
- }
34
  }
 
 
 
35
  ?>
1
  <?php
2
  /**
3
+ * The Bulk_Delete_By_Days class is moved to /includes/util/ directory in v5.5.
4
  *
5
+ * This file is still here for backward compatibility.
6
+ * Eventually once all the addons have been updated, this file will be removed.
7
  */
 
 
 
8
 
9
+ // Exit if accessed directly
10
+ if ( ! defined( 'ABSPATH' ) ) {
11
+ exit;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
12
  }
13
+
14
+ // include the correct file
15
+ require_once Bulk_Delete::$PLUGIN_DIR . '/include/util/class-bulk-delete-by-days.php';
16
  ?>
include/class-bulk-delete-help-screen.php DELETED
@@ -1,122 +0,0 @@
1
- <?php
2
- /**
3
- * Bulk Delete Help Screen
4
- *
5
- * Displays the help tab on top of Bulk Delete Admin pages
6
- *
7
- * @package Bulk_Delete
8
- * @subpackage Help
9
- * @author Sudar
10
- * @since 5.1
11
- */
12
- class Bulk_Delete_Help_Screen {
13
-
14
- /**
15
- * Add contextual help to admin screens
16
- *
17
- * @since 5.1
18
- * @static
19
- *
20
- * @param string $screen Screen name
21
- */
22
- public static function add_contextual_help( $screen ) {
23
- $help_tabs = self::get_help_tabs( $screen );
24
-
25
- foreach ( $help_tabs as $help_tab ) {
26
- get_current_screen()->add_help_tab( $help_tab );
27
- }
28
-
29
- // Add help sidebar
30
- get_current_screen()->set_help_sidebar(
31
- '<p><strong>' . __( 'More information', 'bulk-delete' ) . '</strong></p>' .
32
- '<p><a href = "http://bulkwp.com/support/?utm_source=wpadmin&utm_campaign=BulkDelete&utm_medium=helptab">' . __( 'Support Forums', 'bulk-delete' ) . '</a></p>' .
33
- '<p><a href = "http://bulkwp.com/addons/?utm_source=wpadmin&utm_campaign=BulkDelete&utm_medium=helptab">' . __( 'Buy pro addons', 'bulk-delete' ) . '</a></p>' .
34
- '<p><a href = "http://sudarmuthu.com/blog">' . __( "Plugin author's blog", 'bulk-delete' ) . '</a></p>' .
35
- '<p><a href = "http://sudarmuthu.com/wordpress/">' . __( "Other Plugin's by Author", 'bulk-delete' ) . '</a></p>'
36
- );
37
- }
38
-
39
- /**
40
- * Get the list of help tabs for a given screen
41
- *
42
- * @since 5.1
43
- * @static
44
- * @access private
45
- *
46
- * @param string $screen Screen name
47
- * @return array $help_tabs List of tabs
48
- */
49
- private static function get_help_tabs( $screen ) {
50
- $bd = BULK_DELETE();
51
- $help_tabs = array();
52
-
53
- switch ( $screen ) {
54
- case $bd->posts_page:
55
- $overview_tab = array(
56
- 'title' => __( 'Overview', 'bulk-delete' ),
57
- 'id' => 'overview_tab',
58
- 'content' => '<p>' . __( 'This screen contains different modules that allows you to delete posts or schedule them for deletion.', 'bulk-delete' ) . '</p>',
59
- 'callback' => FALSE
60
- );
61
-
62
- $help_tabs['overview_tab'] = $overview_tab;
63
- break;
64
-
65
- case $bd->pages_page:
66
- // Overview tab
67
- $overview_tab = array(
68
- 'title' => __( 'Overview', 'bulk-delete' ),
69
- 'id' => 'overview_tab',
70
- 'content' => '<p>' . __( 'This screen contains different modules that allows you to delete pages or schedule them for deletion.', 'bulk-delete' ) . '</p>',
71
- 'callback' => FALSE
72
- );
73
-
74
- $help_tabs['overview_tab'] = $overview_tab;
75
- break;
76
-
77
- case $bd->users_page:
78
- // Overview tab
79
- $overview_tab = array(
80
- 'title' => __( 'Overview', 'bulk-delete' ),
81
- 'id' => 'overview_tab',
82
- 'content' => '<p>' . __( 'This screen contains different modules that allows you to delete users or schedule them for deletion.', 'bulk-delete' ) . '</p>',
83
- 'callback' => FALSE
84
- );
85
-
86
- $help_tabs['overview_tab'] = $overview_tab;
87
- break;
88
- }
89
-
90
- // about plugin tab
91
- $about_plugin_tab = array(
92
- 'title' => __( 'About Plugin', 'bulk-delete' ),
93
- 'id' => 'about_plugin_tab',
94
- 'content' => '',
95
- 'callback' => array( 'Bulk_Delete_Help_Screen', 'print_about_plugin_tab_content' )
96
- );
97
-
98
- $help_tabs['about_plugin_tab'] = $about_plugin_tab;
99
-
100
- /**
101
- * Filters help tab content for admin screens
102
- *
103
- * @since 5.1
104
- */
105
- return apply_filters( 'bd_admin_help_tabs', $help_tabs, $screen );
106
- }
107
-
108
- /**
109
- * print the about plugin tab content
110
- *
111
- * @since 5.1
112
- * @static
113
- */
114
- public static function print_about_plugin_tab_content() {
115
- echo '<p>' . __( 'This plugin allows you to perform bulk operations in WordPress easily.', 'bulk-delete' ) . '</p>';
116
- echo '<p>' . __( 'This plugin can be used to delete the posts, pages or users using various filters and conditions.', 'bulk-delete' ) . '</p>';
117
- }
118
- }
119
-
120
- // hooks
121
- add_action( 'bd_add_contextual_help', array( 'Bulk_Delete_Help_Screen' , 'add_contextual_help' ) );
122
- ?>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
include/class-bulk-delete-pages.php DELETED
@@ -1,302 +0,0 @@
1
- <?php
2
- /**
3
- * Utility class for deleting pages
4
- *
5
- * @package Bulk_Delete
6
- * @package Page
7
- * @author Sudar
8
- * @since 5.0
9
- */
10
- class Bulk_Delete_Pages {
11
-
12
- /**
13
- * Render delete pages by page status box
14
- *
15
- * @access public
16
- * @static
17
- * @since 5.0
18
- */
19
- public static function render_delete_pages_by_status_box() {
20
-
21
- if ( Bulk_Delete_Util::is_pages_box_hidden( Bulk_Delete::BOX_PAGE_STATUS ) ) {
22
- printf( __( 'This section just got enabled. Kindly <a href = "%1$s">refresh</a> the page to fully enable it.', 'bulk-delete' ), 'admin.php?page=' . Bulk_Delete::PAGES_PAGE_SLUG );
23
- return;
24
- }
25
-
26
- $pages_count = wp_count_posts( 'page' );
27
- $pages = $pages_count->publish;
28
- $page_drafts = $pages_count->draft;
29
- $page_future = $pages_count->future;
30
- $page_pending = $pages_count->pending;
31
- $page_private = $pages_count->private;
32
- ?>
33
- <!-- Pages start-->
34
- <h4><?php _e( 'Select the pages which you want to delete', 'bulk-delete' ); ?></h4>
35
-
36
- <fieldset class="options">
37
- <table class="optiontable">
38
- <tr>
39
- <td>
40
- <input name="smbd_published_pages" value = "published_pages" type = "checkbox" />
41
- <label for="smbd_published_pages"><?php _e("All Published Pages", 'bulk-delete'); ?> (<?php echo $pages . " "; _e("Pages", 'bulk-delete'); ?>)</label>
42
- </td>
43
- </tr>
44
-
45
- <tr>
46
- <td>
47
- <input name="smbd_draft_pages" value = "draft_pages" type = "checkbox" />
48
- <label for="smbd_draft_pages"><?php _e("All Draft Pages", 'bulk-delete'); ?> (<?php echo $page_drafts . " "; _e("Pages", 'bulk-delete'); ?>)</label>
49
- </td>
50
- </tr>
51
-
52
- <tr>
53
- <td>
54
- <input name="smbd_future_pages" value = "scheduled_pages" type = "checkbox" />
55
- <label for="smbd_future_pages"><?php _e("All Scheduled Pages", 'bulk-delete'); ?> (<?php echo $page_future . " "; _e("Pages", 'bulk-delete'); ?>)</label>
56
- </td>
57
- </tr>
58
-
59
- <tr>
60
- <td>
61
- <input name="smbd_pending_pages" value = "pending_pages" type = "checkbox" />
62
- <label for="smbd_pending_pages"><?php _e("All Pending Pages", 'bulk-delete'); ?> (<?php echo $page_pending . " "; _e("Pages", 'bulk-delete'); ?>)</label>
63
- </td>
64
- </tr>
65
-
66
- <tr>
67
- <td>
68
- <input name="smbd_private_pages" value = "private_pages" type = "checkbox" />
69
- <label for="smbd_private_pages"><?php _e("All Private Pages", 'bulk-delete'); ?> (<?php echo $page_private . " "; _e("Pages", 'bulk-delete'); ?>)</label>
70
- </td>
71
- </tr>
72
-
73
- <tr>
74
- <td>
75
- <h4><?php _e("Choose your filtering options", 'bulk-delete'); ?></h4>
76
- </td>
77
- </tr>
78
-
79
- <tr>
80
- <td scope="row">
81
- <input name="smbd_pages_restrict" id="smbd_pages_restrict" value = "true" type = "checkbox">
82
- <?php _e("Only restrict to pages which are ", 'bulk-delete');?>
83
- <select name="smbd_pages_op" id="smbd_pages_op" disabled>
84
- <option value ="<"><?php _e("older than", 'bulk-delete');?></option>
85
- <option value =">"><?php _e("posted within last", 'bulk-delete');?></option>
86
- </select>
87
- <input type ="textbox" name="smbd_pages_days" id="smbd_pages_days" disabled value ="0" maxlength="4" size="4" /><?php _e("days", 'bulk-delete');?>
88
- </td>
89
- </tr>
90
-
91
- <tr>
92
- <td scope="row">
93
- <input name="smbd_pages_force_delete" value = "false" type = "radio" checked="checked" /> <?php _e('Move to Trash', 'bulk-delete'); ?>
94
- <input name="smbd_pages_force_delete" value = "true" type = "radio" /> <?php _e('Delete permanently', 'bulk-delete'); ?>
95
- </td>
96
- </tr>
97
-
98
- <tr>
99
- <td scope="row">
100
- <input name="smbd_pages_limit" id="smbd_pages_limit" value = "true" type = "checkbox">
101
- <?php _e("Only delete first ", 'bulk-delete');?>
102
- <input type ="textbox" name="smbd_pages_limit_to" id="smbd_pages_limit_to" disabled value ="0" maxlength="4" size="4" /><?php _e("pages.", 'bulk-delete');?>
103
- <?php _e("Use this option if there are more than 1000 pages and the script timesout.", 'bulk-delete') ?>
104
- </td>
105
- </tr>
106
-
107
- <tr>
108
- <td scope="row" colspan="2">
109
- <input name="smbd_pages_cron" value = "false" type = "radio" checked="checked" /> <?php _e('Delete now', 'bulk-delete'); ?>
110
- <input name="smbd_pages_cron" value = "true" type = "radio" id = "smbd_pages_cron" disabled > <?php _e('Schedule', 'bulk-delete'); ?>
111
- <input name="smbd_pages_cron_start" id = "smbd_pages_cron_start" value = "now" type = "text" disabled><?php _e('repeat ', 'bulk-delete');?>
112
- <select name = "smbd_pages_cron_freq" id = "smbd_pages_cron_freq" disabled>
113
- <option value = "-1"><?php _e("Don't repeat", 'bulk-delete'); ?></option>
114
- <?php
115
- $schedules = wp_get_schedules();
116
- foreach($schedules as $key => $value) {
117
- ?>
118
- <option value = "<?php echo $key; ?>"><?php echo $value['display']; ?></option>
119
- <?php
120
- }
121
- ?>
122
- </select>
123
- <span class = "bd-pages-pro" style = "color:red"><?php _e('Only available in Pro Addon', 'bulk-delete'); ?> <a href = "http://bulkwp.com/addons/scheduler-for-deleting-pages-by-status/?utm_source=wpadmin&utm_campaign=BulkDelete&utm_medium=buynow&utm_content=bd-sp">Buy now</a></span>
124
- </td>
125
- </tr>
126
- </table>
127
- </fieldset>
128
-
129
- <p>
130
- <button type="submit" name="bd_action" value = "delete_pages_by_status" class="button-primary"><?php _e( 'Bulk Delete ', 'bulk-delete' ) ?>&raquo;</button>
131
- </p>
132
- <!-- Pages end-->
133
- <?php
134
- }
135
-
136
- /**
137
- * Request handler for deleting pages by status
138
- *
139
- * @since 5.0
140
- */
141
- public static function do_delete_pages_by_status() {
142
- $delete_options = array();
143
- $delete_options['restrict'] = array_get( $_POST, 'smbd_pages_restrict', FALSE );
144
- $delete_options['limit_to'] = absint( array_get( $_POST, 'smbd_pages_limit_to', 0 ) );
145
- $delete_options['force_delete'] = array_get( $_POST, 'smbd_pages_force_delete', 'false' );
146
-
147
- $delete_options['page_op'] = array_get( $_POST, 'smbd_pages_op' );
148
- $delete_options['page_days'] = array_get( $_POST, 'smbd_pages_days' );
149
-
150
- $delete_options['publish'] = array_get( $_POST, 'smbd_published_pages' );
151
- $delete_options['drafts'] = array_get( $_POST, 'smbd_draft_pages' );
152
- $delete_options['pending'] = array_get( $_POST, 'smbd_pending_pages' );
153
- $delete_options['future'] = array_get( $_POST, 'smbd_future_pages' );
154
- $delete_options['private'] = array_get( $_POST, 'smbd_private_pages' );
155
-
156
- if ( array_get( $_POST, 'smbd_pages_cron', 'false' ) == 'true' ) {
157
- $freq = $_POST['smbd_pages_cron_freq'];
158
- $time = strtotime( $_POST['smbd_pages_cron_start'] ) - ( get_option( 'gmt_offset' ) * 60 * 60 );
159
-
160
- if ( $freq == -1 ) {
161
- wp_schedule_single_event( $time, Bulk_Delete::CRON_HOOK_PAGES_STATUS, array( $delete_options ) );
162
- } else {
163
- wp_schedule_event( $time, $freq , Bulk_Delete::CRON_HOOK_PAGES_STATUS, array( $delete_options ) );
164
- }
165
- $msg = __( 'The selected pages are scheduled for deletion.', 'bulk-delete' ) . ' ' .
166
- sprintf( __( 'See the full list of <a href = "%s">scheduled tasks</a>' , 'bulk-delete' ), get_bloginfo( "wpurl" ) . '/wp-admin/admin.php?page=' . Bulk_Delete::CRON_PAGE_SLUG );
167
- } else {
168
- $deleted_count = self::delete_pages_by_status( $delete_options );
169
- $msg = sprintf( _n( 'Deleted %d page', 'Deleted %d pages' , $deleted_count, 'bulk-delete' ), $deleted_count );
170
- }
171
-
172
- add_settings_error(
173
- Bulk_Delete::PAGES_PAGE_SLUG,
174
- 'deleted-cron',
175
- $msg,
176
- 'updated'
177
- );
178
- }
179
-
180
- /**
181
- * Bulk Delete pages
182
- *
183
- * @since 5.0
184
- */
185
- public static function delete_pages_by_status( $delete_options ) {
186
- global $wp_query;
187
-
188
- $options = array();
189
- $post_status = array();
190
-
191
- $limit_to = $delete_options['limit_to'];
192
-
193
- if ($limit_to > 0) {
194
- $options['showposts'] = $limit_to;
195
- } else {
196
- $options['nopaging'] = 'true';
197
- }
198
-
199
- $force_delete = $delete_options['force_delete'];
200
-
201
- if ($force_delete == 'true') {
202
- $force_delete = true;
203
- } else {
204
- $force_delete = false;
205
- }
206
-
207
- // published pages
208
- if ("published_pages" == $delete_options['publish']) {
209
- $post_status[] = 'publish';
210
- }
211
-
212
- // Drafts
213
- if ("draft_pages" == $delete_options['drafts']) {
214
- $post_status[] = 'draft';
215
- }
216
-
217
- // Pending pages
218
- if ("pending_pages" == $delete_options['pending']) {
219
- $post_status[] = 'pending';
220
- }
221
-
222
- // Future pages
223
- if ("future_pages" == $delete_options['future']) {
224
- $post_status[] = 'future';
225
- }
226
-
227
- // Private pages
228
- if ("private_pages" == $delete_options['private']) {
229
- $post_status[] = 'private';
230
- }
231
-
232
- $options['post_type'] = 'page';
233
- $options['post_status'] = $post_status;
234
-
235
- if ($delete_options['restrict'] == "true") {
236
- $options['op'] = $delete_options['page_op'];
237
- $options['days'] = $delete_options['page_days'];
238
-
239
- if ( !class_exists( 'Bulk_Delete_By_Days' ) ) {
240
- require_once Bulk_Delete::$PLUGIN_DIR . '/include/class-bulk-delete-by-days.php';
241
- }
242
- $bulk_Delete_By_Days = new Bulk_Delete_By_Days;
243
- }
244
-
245
- $pages = $wp_query->query($options);
246
- foreach ($pages as $page) {
247
- wp_delete_post($page->ID, $force_delete);
248
- }
249
-
250
- return count( $pages );
251
- }
252
-
253
- /**
254
- * Render delete pages from trash box
255
- *
256
- * @since 5.1
257
- * @static
258
- */
259
- public static function render_delete_pages_from_trash() {
260
- if ( Bulk_Delete_Util::is_pages_box_hidden( Bulk_Delete::BOX_PAGE_FROM_TRASH ) ) {
261
- printf( __( 'This section just got enabled. Kindly <a href = "%1$s">refresh</a> the page to fully enable it.', 'bulk-delete' ), 'admin.php?page=' . Bulk_Delete::PAGES_PAGE_SLUG );
262
- return;
263
- }
264
-
265
- if ( !class_exists( 'Bulk_Delete_From_Trash' ) ) {
266
- ?>
267
- <!-- pages In Trash box start-->
268
- <p>
269
- <span class = "bd-pages-trash-pro" style = "color:red">
270
- <?php _e( 'You need "Bulk Delete From Trash" Addon, to delete pages in Trash.', 'bulk-delete' ); ?>
271
- <a href = "http://bulkwp.com/addons/bulk-delete-from-trash/?utm_source=wpadmin&utm_campaign=BulkDelete&utm_medium=buynow&utm_content=bd-th">Buy now</a>
272
- </span>
273
- </p>
274
- <!-- pages In Trash box end-->
275
- <?php
276
- } else {
277
- /**
278
- * Render delete pages from trash box
279
- *
280
- * @since 5.4
281
- */
282
- do_action( 'bd_render_delete_pages_from_trash' );
283
- }
284
- }
285
-
286
- /**
287
- * Filter JS Array and add validation hooks
288
- *
289
- * @since 5.4
290
- * @static
291
- * @param array $js_array JavaScript Array
292
- * @return array Modified JavaScript Array
293
- */
294
- public static function filter_js_array( $js_array ) {
295
- $js_array['dt_iterators'][] = '_pages';
296
- return $js_array;
297
- }
298
- }
299
-
300
- add_action( 'bd_delete_pages_by_status', array( 'Bulk_Delete_Pages', 'do_delete_pages_by_status' ) );
301
- add_filter( 'bd_javascript_array', array( 'Bulk_Delete_Pages' , 'filter_js_array' ) );
302
- ?>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
include/class-bulk-delete-posts.php DELETED
@@ -1,1692 +0,0 @@
1
- <?php
2
- /**
3
- * Utility class for deleting posts
4
- *
5
- * @package Bulk_Delete
6
- * @subpackage Posts
7
- * @author Sudar
8
- */
9
- class Bulk_Delete_Posts {
10
-
11
- /**
12
- * Render post status box
13
- */
14
- public static function render_delete_posts_by_status_box() {
15
-
16
- if ( Bulk_Delete_Util::is_posts_box_hidden(Bulk_Delete::BOX_POST_STATUS) ) {
17
- printf( __( 'This section just got enabled. Kindly <a href = "%1$s">refresh</a> the page to fully enable it.', 'bulk-delete' ), 'admin.php?page=' . Bulk_Delete::POSTS_PAGE_SLUG );
18
- return;
19
- }
20
-
21
- $posts_count = wp_count_posts();
22
- $publish = $posts_count->publish;
23
- $drafts = $posts_count->draft;
24
- $future = $posts_count->future;
25
- $pending = $posts_count->pending;
26
- $private = $posts_count->private;
27
-
28
- $sticky = count( get_option( 'sticky_posts' ) );
29
- ?>
30
- <h4><?php _e("Select the posts which you want to delete", 'bulk-delete'); ?></h4>
31
-
32
- <fieldset class="options">
33
- <table class="optiontable">
34
- <tr>
35
- <td>
36
- <input name="smbd_publish" id ="smbd_publish" value = "publish" type = "checkbox" >
37
- <label for="smbd_publish"><?php _e( 'All publish posts', 'bulk-delete' ); ?> (<?php echo $publish . ' '; _e( 'Posts', 'bulk-delete' ); ?>)</label>
38
- </td>
39
- </tr>
40
-
41
- <tr>
42
- <td scope="row" >
43
- <input name="smbd_drafts" id ="smbd_drafts" value = "drafts" type = "checkbox" />
44
- <label for="smbd_drafts"><?php _e("All Draft Posts", 'bulk-delete'); ?> (<?php echo $drafts . " "; _e("Drafts", 'bulk-delete'); ?>)</label>
45
- </td>
46
- </tr>
47
-
48
- <tr>
49
- <td>
50
- <input name="smbd_pending" id ="smbd_pending" value = "pending" type = "checkbox" />
51
- <label for="smbd_pending"><?php _e("All Pending posts", 'bulk-delete'); ?> (<?php echo $pending . " "; _e("Posts", 'bulk-delete'); ?>)</label>
52
- </td>
53
- </tr>
54
-
55
- <tr>
56
- <td>
57
- <input name="smbd_future" id ="smbd_future" value = "future" type = "checkbox" />
58
- <label for="smbd_future"><?php _e("All scheduled posts", 'bulk-delete'); ?> (<?php echo $future . " "; _e("Posts", 'bulk-delete'); ?>)</label>
59
- </td>
60
- </tr>
61
-
62
- <tr>
63
- <td>
64
- <input name="smbd_private" id ="smbd_private" value = "private" type = "checkbox" />
65
- <label for="smbd_private"><?php _e("All private posts", 'bulk-delete'); ?> (<?php echo $private . " "; _e("Posts", 'bulk-delete'); ?>)</label>
66
- </td>
67
- </tr>
68
-
69
- <tr>
70
- <td>
71
- <input name="smbd_sticky" id ="smbd_sticky" value = "sticky" type = "checkbox" >
72
- <label for="smbd_sticky"><?php _e( 'All Sticky posts', 'bulk-delete' ); ?> (<?php echo $sticky . ' '; _e( 'Posts', 'bulk-delete' ); ?>)</label>
73
- </td>
74
- </tr>
75
-
76
- <tr>
77
- <td>
78
- <h4><?php _e("Choose your filtering options", 'bulk-delete'); ?></h4>
79
- </td>
80
- </tr>
81
-
82
- <tr>
83
- <td>
84
- <p><?php _e( 'Note: The date filter will not work for sticky posts', 'bulk-delete' ); ?></p>
85
- </td>
86
- </tr>
87
-
88
- <tr>
89
- <td scope="row">
90
- <input name="smbd_post_status_restrict" id="smbd_post_status_restrict" value = "true" type = "checkbox">
91
- <?php _e("Only restrict to posts which are ", 'bulk-delete');?>
92
- <select name="smbd_post_status_op" id="smbd_post_status_op" disabled>
93
- <option value ="<"><?php _e("older than", 'bulk-delete');?></option>
94
- <option value =">"><?php _e("posted within last", 'bulk-delete');?></option>
95
- </select>
96
- <input type ="textbox" name="smbd_post_status_days" id="smbd_post_status_days" disabled value ="0" maxlength="4" size="4" /><?php _e("days", 'bulk-delete');?>
97
- </td>
98
- </tr>
99
-
100
- <tr>
101
- <td scope="row">
102
- <input name="smbd_post_status_force_delete" value = "false" type = "radio" checked="checked" /> <?php _e('Move to Trash', 'bulk-delete'); ?>
103
- <input name="smbd_post_status_force_delete" value = "true" type = "radio" /> <?php _e('Delete permanently', 'bulk-delete'); ?>
104
- </td>
105
- </tr>
106
-
107
- <tr>
108
- <td scope="row">
109
- <input name="smbd_post_status_limit" id="smbd_post_status_limit" value = "true" type = "checkbox" >
110
- <?php _e("Only delete first ", 'bulk-delete');?>
111
- <input type ="textbox" name="smbd_post_status_limit_to" id="smbd_post_status_limit_to" disabled value ="0" maxlength="4" size="4" /><?php _e("posts.", 'bulk-delete');?>
112
- <?php _e("Use this option if there are more than 1000 posts and the script timesout.", 'bulk-delete') ?>
113
- </td>
114
- </tr>
115
-
116
- <tr>
117
- <td scope="row" colspan="2">
118
- <input name="smbd_post_status_cron" value = "false" type = "radio" checked="checked" /> <?php _e('Delete now', 'bulk-delete'); ?>
119
- <input name="smbd_post_status_cron" value = "true" type = "radio" id = "smbd_post_status_cron" disabled > <?php _e('Schedule', 'bulk-delete'); ?>
120
- <input name="smbd_post_status_cron_start" id = "smbd_post_status_cron_start" value = "now" type = "text" disabled><?php _e('repeat ', 'bulk-delete');?>
121
- <select name = "smbd_post_status_cron_freq" id = "smbd_post_status_cron_freq" disabled>
122
- <option value = "-1"><?php _e("Don't repeat", 'bulk-delete'); ?></option>
123
- <?php
124
- $schedules = wp_get_schedules();
125
- foreach($schedules as $key => $value) {
126
- ?>
127
- <option value = "<?php echo $key; ?>"><?php echo $value['display']; ?></option>
128
- <?php
129
- }
130
- ?>
131
- </select>
132
- <span class = "bd-post-status-pro" style = "color:red"><?php _e( 'Only available in Pro Addon', 'bulk-delete' ); ?> <a href = "http://bulkwp.com/addons/scheduler-for-deleting-posts-by-status/?utm_source=wpadmin&utm_campaign=BulkDelete&utm_medium=buynow&utm_content=bd-sps">Buy now</a></span>
133
- </td>
134
- </tr>
135
- </table>
136
- </fieldset>
137
-
138
- <p>
139
- <button type="submit" name="bd_action" value = "delete_posts_by_status" class="button-primary"><?php _e( 'Bulk Delete ', 'bulk-delete' ) ?>&raquo;</button>
140
- </p>
141
- <?php
142
- }
143
-
144
- /**
145
- * Delete posts by post status
146
- *
147
- * @since 5.0
148
- * @static
149
- */
150
- public static function do_delete_posts_by_status() {
151
-
152
- $delete_options = array();
153
- $delete_options['restrict'] = array_get($_POST, 'smbd_post_status_restrict', FALSE);
154
- $delete_options['limit_to'] = absint(array_get($_POST, 'smbd_post_status_limit_to', 0));
155
- $delete_options['force_delete'] = array_get($_POST, 'smbd_post_status_force_delete', 'false');
156
-
157
- $delete_options['post_status_op'] = array_get($_POST, 'smbd_post_status_op');
158
- $delete_options['post_status_days'] = array_get($_POST, 'smbd_post_status_days');
159
-
160
- $delete_options['publish'] = array_get( $_POST, 'smbd_publish' );
161
- $delete_options['drafts'] = array_get($_POST, 'smbd_drafts');
162
- $delete_options['pending'] = array_get($_POST, 'smbd_pending');
163
- $delete_options['future'] = array_get($_POST, 'smbd_future');
164
- $delete_options['private'] = array_get($_POST, 'smbd_private');
165
- $delete_options['sticky'] = array_get( $_POST, 'smbd_sticky' );
166
-
167
- if (array_get($_POST, 'smbd_post_status_cron', 'false') == 'true') {
168
- $freq = $_POST['smbd_post_status_cron_freq'];
169
- $time = strtotime($_POST['smbd_post_status_cron_start']) - ( get_option('gmt_offset') * 60 * 60 );
170
-
171
- if ($freq == -1) {
172
- wp_schedule_single_event($time, Bulk_Delete::CRON_HOOK_POST_STATUS, array($delete_options));
173
- } else {
174
- wp_schedule_event($time, $freq, Bulk_Delete::CRON_HOOK_POST_STATUS, array($delete_options));
175
- }
176
- $msg = __('Posts with the selected status are scheduled for deletion.', 'bulk-delete') . ' ' .
177
- sprintf( __( 'See the full list of <a href = "%s">scheduled tasks</a>' , 'bulk-delete' ), get_bloginfo( "wpurl" ) . '/wp-admin/admin.php?page=' . Bulk_Delete::CRON_PAGE_SLUG );
178
- } else {
179
- $deleted_count = self::delete_posts_by_status($delete_options);
180
- $msg = sprintf( _n('Deleted %d post with the selected post status', 'Deleted %d posts with the selected post status' , $deleted_count, 'bulk-delete' ), $deleted_count);
181
- }
182
-
183
- add_settings_error(
184
- Bulk_Delete::POSTS_PAGE_SLUG,
185
- 'deleted-posts',
186
- $msg,
187
- 'updated'
188
- );
189
- }
190
-
191
- /**
192
- * Delete posts by post status - drafts, pending posts, scheduled posts etc.
193
- *
194
- * @since 5.0
195
- * @static
196
- * @param array $delete_options Options for deleting posts
197
- * @return int $posts_deleted Number of posts that were deleted
198
- *
199
- */
200
- public static function delete_posts_by_status( $delete_options ) {
201
- global $wp_query;
202
- global $wpdb;
203
-
204
- $posts_deleted = 0;
205
-
206
- $force_delete = $delete_options['force_delete'];
207
-
208
- if ($force_delete == 'true') {
209
- $force_delete = true;
210
- } else {
211
- $force_delete = false;
212
- }
213
-
214
- // Delete sticky posts
215
- if ( 'sticky' == $delete_options['sticky'] ) {
216
- $sticky_post_ids = get_option( 'sticky_posts' );
217
-
218
- foreach ( $sticky_post_ids as $sticky_post_id ) {
219
- wp_delete_post( $sticky_post_id, $force_delete );
220
- }
221
-
222
- $posts_deleted += count( $sticky_post_ids );
223
- }
224
-
225
- $options = array();
226
- $post_status = array();
227
-
228
- $limit_to = $delete_options['limit_to'];
229
-
230
- if ($limit_to > 0) {
231
- $options['showposts'] = $limit_to;
232
- } else {
233
- $options['nopaging'] = 'true';
234
- }
235
-
236
- $force_delete = $delete_options['force_delete'];
237
-
238
- if ($force_delete == 'true') {
239
- $force_delete = true;
240
- } else {
241
- $force_delete = false;
242
- }
243
-
244
- // Published posts
245
- if ( 'publish' == $delete_options['publish'] ) {
246
- $post_status[] = 'publish';
247
- }
248
-
249
- // Drafts
250
- if ( 'drafts' == $delete_options['drafts'] ) {
251
- $post_status[] = 'draft';
252
-
253
- // ignore sticky posts.
254
- // For some reason, sticky posts also gets deleted when deleting drafts through a schedule
255
- $options['post__not_in'] = get_option( 'sticky_posts' );
256
- }
257
-
258
- // Pending Posts
259
- if ("pending" == $delete_options['pending']) {
260
- $post_status[] = 'pending';
261
- }
262
-
263
- // Future Posts
264
- if ("future" == $delete_options['future']) {
265
- $post_status[] = 'future';
266
- }
267
-
268
- // Private Posts
269
- if ("private" == $delete_options['private']) {
270
- $post_status[] = 'private';
271
- }
272
-
273
- if ($delete_options['restrict'] == "true") {
274
- $options['op'] = $delete_options['post_status_op'];
275
- $options['days'] = $delete_options['post_status_days'];
276
-
277
- if ( !class_exists( 'Bulk_Delete_By_Days' ) ) {
278
- require_once Bulk_Delete::$PLUGIN_DIR . '/include/class-bulk-delete-by-days.php';
279
- }
280
- $bulk_Delete_By_Days = new Bulk_Delete_By_Days;
281
- }
282
-
283
- // now retrieve all posts and delete them
284
- $options['post_status'] = $post_status;
285
-
286
- $posts = $wp_query->query($options);
287
-
288
- foreach ($posts as $post) {
289
- wp_delete_post($post->ID, $force_delete);
290
- }
291
-
292
- $posts_deleted += count( $posts );
293
- return $posts_deleted;
294
- }
295
-
296
- /**
297
- * Render Delete posts by category box
298
- */
299
- public static function render_delete_posts_by_category_box() {
300
-
301
- if ( Bulk_Delete_Util::is_posts_box_hidden(Bulk_Delete::BOX_CATEGORY) ) {
302
- printf( __( 'This section just got enabled. Kindly <a href = "%1$s">refresh</a> the page to fully enable it.', 'bulk-delete' ), 'admin.php?page=' . Bulk_Delete::POSTS_PAGE_SLUG );
303
- return;
304
- }
305
-
306
- $types = get_post_types( array(
307
- '_builtin' => false
308
- ), 'names'
309
- );
310
-
311
- array_unshift( $types, 'post' );
312
- ?>
313
- <!-- Category Start-->
314
- <h4><?php _e( 'Select the post type whose category posts you want to delete', 'bulk-delete' ); ?></h4>
315
- <fieldset class="options">
316
- <table class="optiontable">
317
- <?php
318
- foreach ( $types as $type ) {
319
- ?>
320
- <tr>
321
- <td scope="row" >
322
- <input name="smbd_cat_post_type" value = "<?php echo $type; ?>" type = "radio" class = "smbd_cat_post_type" <?php checked( $type, 'post' ); ?>>
323
- </td>
324
- <td>
325
- <label for="smbd_cat_post_type"><?php echo $type; ?> </label>
326
- </td>
327
- </tr>
328
- <?php
329
- }
330
- ?>
331
- </table>
332
-
333
- <h4><?php _e( 'Select the categories whose post you want to delete', 'bulk-delete' ); ?></h4>
334
- <p><?php _e( 'Note: The post count below for each category is the total number of posts in that category, irrespective of post type', 'bulk-delete' ); ?></p>
335
- <?php
336
- $categories = get_categories( array(
337
- 'hide_empty' => false
338
- )
339
- );
340
- ?>
341
- <table class="optiontable">
342
- <?php
343
- foreach ( $categories as $category ) {
344
- ?>
345
- <tr>
346
- <td scope="row" >
347
- <input name="smbd_cats[]" value = "<?php echo $category->cat_ID; ?>" type = "checkbox" >
348
- </td>
349
- <td>
350
- <label for="smbd_cats"><?php echo $category->cat_name; ?> (<?php echo $category->count . " "; _e( 'Posts', 'bulk-delete' ); ?>)</label>
351
- </td>
352
- </tr>
353
- <?php
354
- }
355
- ?>
356
- <tr>
357
- <td scope="row" >
358
- <input name="smbd_cats_all" id ="smbd_cats_all" value = "-1" type = "checkbox" >
359
- </td>
360
- <td>
361
- <label for="smbd_cats_all"><?php _e("All Categories", 'bulk-delete') ?></label>
362
- </td>
363
- </tr>
364
- </table>
365
-
366
- <table class="optiontable">
367
- <tr>
368
- <td colspan="2">
369
- <h4><?php _e("Choose your filtering options", 'bulk-delete'); ?></h4>
370
- </td>
371
- </tr>
372
-
373
- <tr>
374
- <td scope="row">
375
- <input name="smbd_cats_restrict" id="smbd_cats_restrict" value = "true" type = "checkbox" >
376
- </td>
377
- <td>
378
- <?php _e("Only restrict to posts which are ", 'bulk-delete');?>
379
- <select name="smbd_cats_op" id="smbd_cats_op" disabled>
380
- <option value ="<"><?php _e("older than", 'bulk-delete');?></option>
381
- <option value =">"><?php _e("posted within last", 'bulk-delete');?></option>
382
- </select>
383
- <input type ="textbox" name="smbd_cats_days" id="smbd_cats_days" disabled value ="0" maxlength="4" size="4" /><?php _e("days", 'bulk-delete');?>
384
- </td>
385
- </tr>
386
-
387
- <tr>
388
- <td scope="row" colspan="2">
389
- <input name="smbd_cats_force_delete" value = "false" type = "radio" checked="checked" /> <?php _e('Move to Trash', 'bulk-delete'); ?>
390
- <input name="smbd_cats_force_delete" value = "true" type = "radio" /> <?php _e('Delete permanently', 'bulk-delete'); ?>
391
- </td>
392
- </tr>
393
-
394
- <tr>
395
- <td scope="row" colspan="2">
396
- <input name="smbd_cats_private" value = "false" type = "radio" checked="checked" /> <?php _e('Public posts', 'bulk-delete'); ?>
397
- <input name="smbd_cats_private" value = "true" type = "radio" /> <?php _e('Private Posts', 'bulk-delete'); ?>
398
- </td>
399
- </tr>
400
-
401
- <tr>
402
- <td scope="row">
403
- <input name="smbd_cats_limit" id="smbd_cats_limit" value = "true" type = "checkbox">
404
- </td>
405
- <td>
406
- <?php _e("Only delete first ", 'bulk-delete');?>
407
- <input type ="textbox" name="smbd_cats_limit_to" id="smbd_cats_limit_to" disabled value ="0" maxlength="4" size="4" /><?php _e("posts.", 'bulk-delete');?>
408
- <?php _e("Use this option if there are more than 1000 posts and the script timesout.", 'bulk-delete') ?>
409
- </td>
410
- </tr>
411
-
412
- <tr>
413
- <td scope="row" colspan="2">
414
- <input name="smbd_cats_cron" value = "false" type = "radio" checked="checked" /> <?php _e('Delete now', 'bulk-delete'); ?>
415
- <input name="smbd_cats_cron" value = "true" type = "radio" id = "smbd_cats_cron" disabled > <?php _e('Schedule', 'bulk-delete'); ?>
416
- <input name="smbd_cats_cron_start" id = "smbd_cats_cron_start" value = "now" type = "text" disabled><?php _e('repeat ', 'bulk-delete');?>
417
- <select name = "smbd_cats_cron_freq" id = "smbd_cats_cron_freq" disabled>
418
- <option value = "-1"><?php _e("Don't repeat", 'bulk-delete'); ?></option>
419
- <?php
420
- $schedules = wp_get_schedules();
421
- foreach($schedules as $key => $value) {
422
- ?>
423
- <option value = "<?php echo $key; ?>"><?php echo $value['display']; ?></option>
424
- <?php
425
- }
426
- ?>
427
- </select>
428
- <span class = "bd-cats-pro" style = "color:red"><?php _e('Only available in Pro Addon', 'bulk-delete'); ?> <a href = "http://bulkwp.com/addons/scheduler-for-deleting-posts-by-category/?utm_source=wpadmin&utm_campaign=BulkDelete&utm_medium=buynow&utm_content=bd-sc">Buy now</a></span>
429
- </td>
430
- </tr>
431
-
432
- <tr>
433
- <td scope="row" colspan="2">
434
- <?php _e("Enter time in Y-m-d H:i:s format or enter now to use current time", 'bulk-delete');?>
435
- </td>
436
- </tr>
437
-
438
- </table>
439
- </fieldset>
440
-
441
- <p>
442
- <button type="submit" name="bd_action" value = "delete_posts_by_category" class="button-primary"><?php _e( 'Bulk Delete ', 'bulk-delete' ); ?>&raquo;</button>
443
- </p>
444
- <!-- Category end-->
445
- <?php
446
- }
447
-
448
- /**
449
- * Process delete posts by category
450
- *
451
- * @since 5.0
452
- * @static
453
- */
454
- public static function do_delete_posts_by_category() {
455
-
456
- $delete_options = array();
457
- $delete_options['post_type'] = array_get( $_POST, 'smbd_cat_post_type', 'post' );
458
- $delete_options['selected_cats'] = array_get($_POST, 'smbd_cats');
459
- $delete_options['restrict'] = array_get($_POST, 'smbd_cats_restrict', FALSE);
460
- $delete_options['private'] = array_get($_POST, 'smbd_cats_private');
461
- $delete_options['limit_to'] = absint(array_get($_POST, 'smbd_cats_limit_to', 0));
462
- $delete_options['force_delete'] = array_get($_POST, 'smbd_cats_force_delete', 'false');
463
-
464
- $delete_options['cats_op'] = array_get($_POST, 'smbd_cats_op');
465
- $delete_options['cats_days'] = array_get($_POST, 'smbd_cats_days');
466
-
467
- if (array_get($_POST, 'smbd_cats_cron', 'false') == 'true') {
468
- $freq = $_POST['smbd_cats_cron_freq'];
469
- $time = strtotime($_POST['smbd_cats_cron_start']) - ( get_option('gmt_offset') * 60 * 60 );
470
-
471
- if ($freq == -1) {
472
- wp_schedule_single_event($time, Bulk_Delete::CRON_HOOK_CATEGORY, array($delete_options));
473
- } else {
474
- wp_schedule_event($time, $freq , Bulk_Delete::CRON_HOOK_CATEGORY, array($delete_options));
475
- }
476
-
477
- $msg = __('Posts from the selected categories are scheduled for deletion.', 'bulk-delete') . ' ' .
478
- sprintf( __( 'See the full list of <a href = "%s">scheduled tasks</a>' , 'bulk-delete' ), get_bloginfo( "wpurl" ) . '/wp-admin/admin.php?page=' . Bulk_Delete::CRON_PAGE_SLUG );
479
- } else {
480
- $deleted_count = self::delete_posts_by_category( $delete_options );
481
- $msg = sprintf( _n('Deleted %d post from the selected categories', 'Deleted %d posts from the selected categories' , $deleted_count, 'bulk-delete' ), $deleted_count);
482
- }
483
-
484
- add_settings_error(
485
- Bulk_Delete::POSTS_PAGE_SLUG,
486
- 'deleted-posts',
487
- $msg,
488
- 'updated'
489
- );
490
- }
491
-
492
- /**
493
- * Delete posts by category
494
- *
495
- * @since 5.0
496
- * @static
497
- * @param array $delete_options Options for deleting posts
498
- * @return int $posts_deleted Number of posts that were deleted
499
- */
500
- public static function delete_posts_by_category( $delete_options ) {
501
-
502
- // For compatibility reasons set default post type to 'post'
503
- $post_type = array_get( $delete_options, 'post_type', 'post' );
504
- $selected_cats = $delete_options['selected_cats'];
505
-
506
- $options = array(
507
- 'post_type' => $post_type,
508
- 'category__in' => $selected_cats,
509
- 'post_status' => 'publish'
510
- );
511
-
512
- $private = $delete_options['private'];
513
-
514
- if ($private == 'true') {
515
- $options[ 'post_status' ] = 'private';
516
- }
517
-
518
- $limit_to = $delete_options['limit_to'];
519
-
520
- if ($limit_to > 0) {
521
- $options['showposts'] = $limit_to;
522
- } else {
523
- $options['nopaging'] = 'true';
524
- }
525
-
526
- $force_delete = $delete_options['force_delete'];
527
-
528
- if ($force_delete == 'true') {
529
- $force_delete = true;
530
- } else {
531
- $force_delete = false;
532
- }
533
-
534
- if ($delete_options['restrict'] == "true") {
535
- $options['op'] = $delete_options['cats_op'];
536
- $options['days'] = $delete_options['cats_days'];
537
-
538
- if ( !class_exists( 'Bulk_Delete_By_Days' ) ) {
539
- require_once Bulk_Delete::$PLUGIN_DIR . '/include/class-bulk-delete-by-days.php';
540
- }
541
- $bulk_Delete_By_Days = new Bulk_Delete_By_Days;
542
- }
543
-
544
- $wp_query = new WP_Query();
545
- $posts = $wp_query->query($options);
546
-
547
- foreach ($posts as $post) {
548
- // $force delete parameter to custom post types doesn't work
549
- if ( $force_delete ) {
550
- wp_delete_post( $post->ID, TRUE );
551
- } else {
552
- wp_trash_post( $post->ID );
553
- }
554
- }
555
-
556
- return count($posts);
557
- }
558
-
559
- /**
560
- * Render delete posts by tag box
561
- */
562
- public static function render_delete_posts_by_tag_box() {
563
-
564
- if ( Bulk_Delete_Util::is_posts_box_hidden(Bulk_Delete::BOX_TAG) ) {
565
- printf( __( 'This section just got enabled. Kindly <a href = "%1$s">refresh</a> the page to fully enable it.', 'bulk-delete' ), 'admin.php?page=' . Bulk_Delete::POSTS_PAGE_SLUG );
566
- return;
567
- }
568
-
569
- $tags = get_tags();
570
- if (count($tags) > 0) {
571
- ?>
572
- <h4><?php _e("Select the tags whose post you want to delete", 'bulk-delete') ?></h4>
573
-
574
- <!-- Tags start-->
575
- <fieldset class="options">
576
- <table class="optiontable">
577
- <?php
578
- foreach ($tags as $tag) {
579
- ?>
580
- <tr>
581
- <td scope="row" >
582
- <input name="smbd_tags[]" value = "<?php echo $tag->term_id; ?>" type = "checkbox">
583
- </td>
584
- <td>
585
- <label for="smbd_tags"><?php echo $tag->name; ?> (<?php echo $tag->count . " "; _e("Posts", 'bulk-delete'); ?>)</label>
586
- </td>
587
- </tr>
588
- <?php
589
- }
590
- ?>
591
- <tr>
592
- <td scope="row" >
593
- <input name="smbd_tags_all" id ="smbd_tags_all" value = "-1" type = "checkbox" >
594
- </td>
595
- <td>
596
- <label for="smbd_tags_all"><?php _e("All Tags", 'bulk-delete') ?></label>
597
- </td>
598
- </tr>
599
-
600
- <tr>
601
- <td colspan="2">
602
- <h4><?php _e("Choose your filtering options", 'bulk-delete'); ?></h4>
603
- </td>
604
- </tr>
605
-
606
- <tr>
607
- <td scope="row">
608
- <input name="smbd_tags_restrict" id ="smbd_tags_restrict" value = "true" type = "checkbox">
609
- </td>
610
- <td>
611
- <?php _e("Only restrict to posts which are ", 'bulk-delete');?>
612
- <select name="smbd_tags_op" id="smbd_tags_op" disabled>
613
- <option value ="<"><?php _e("older than", 'bulk-delete');?></option>
614
- <option value =">"><?php _e("posted within last", 'bulk-delete');?></option>
615
- </select>
616
- <input type ="textbox" name="smbd_tags_days" id ="smbd_tags_days" value ="0" maxlength="4" size="4" disabled /><?php _e("days", 'bulk-delete');?>
617
- </td>
618
- </tr>
619
-
620
- <tr>
621
- <td scope="row" colspan="2">
622
- <input name="smbd_tags_force_delete" value = "false" type = "radio" checked="checked" > <?php _e('Move to Trash', 'bulk-delete'); ?>
623
- <input name="smbd_tags_force_delete" value = "true" type = "radio" > <?php _e('Delete permanently', 'bulk-delete'); ?>
624
- </td>
625
- </tr>
626
-
627
- <tr>
628
- <td scope="row" colspan="2">
629
- <input name="smbd_tags_private" value = "false" type = "radio" checked="checked" /> <?php _e('Public posts', 'bulk-delete'); ?>
630
- <input name="smbd_tags_private" value = "true" type = "radio" /> <?php _e('Private Posts', 'bulk-delete'); ?>
631
- </td>
632
- </tr>
633
-
634
- <tr>
635
- <td scope="row">
636
- <input name="smbd_tags_limit" id="smbd_tags_limit" value = "true" type = "checkbox">
637
- </td>
638
- <td>
639
- <?php _e("Only delete first ", 'bulk-delete');?>
640
- <input type ="textbox" name="smbd_tags_limit_to" id="smbd_tags_limit_to" disabled value ="0" maxlength="4" size="4" ><?php _e("posts.", 'bulk-delete');?>
641
- <?php _e("Use this option if there are more than 1000 posts and the script timesout.", 'bulk-delete') ?>
642
- </td>
643
- </tr>
644
-
645
- <tr>
646
- <td scope="row" colspan="2">
647
- <input name="smbd_tags_cron" value = "false" type = "radio" checked="checked" > <?php _e('Delete now', 'bulk-delete'); ?>
648
- <input name="smbd_tags_cron" value = "true" type = "radio" id = "smbd_tags_cron" disabled > <?php _e('Schedule', 'bulk-delete'); ?>
649
- <input name="smbd_tags_cron_start" id = "smbd_tags_cron_start" value = "now" type = "text" disabled><?php _e('repeat ', 'bulk-delete');?>
650
- <select name = "smbd_tags_cron_freq" id = "smbd_tags_cron_freq" disabled>
651
- <option value = "-1"><?php _e("Don't repeat", 'bulk-delete'); ?></option>
652
- <?php
653
- $schedules = wp_get_schedules();
654
- foreach($schedules as $key => $value) {
655
- ?>
656
- <option value = "<?php echo $key; ?>"><?php echo $value['display']; ?></option>
657
- <?php
658
- }
659
- ?>
660
- </select>
661
- <span class = "bd-tags-pro" style = "color:red"><?php _e('Only available in Pro Addon', 'bulk-delete'); ?> <a href = "http://bulkwp.com/addons/scheduler-for-deleting-posts-by-tag/?utm_source=wpadmin&utm_campaign=BulkDelete&utm_medium=buynow&utm_content=bd-st">Buy now</a></span>
662
- </td>
663
- </tr>
664
-
665
- </table>
666
- </fieldset>
667
- <p class="submit">
668
- <button type="submit" name="bd_action" value = "delete_posts_by_tag" class="button-primary"><?php _e( 'Bulk Delete ', 'bulk-delete' ); ?>&raquo;</button>
669
- </p>
670
- <!-- Tags end-->
671
- <?php
672
- } else {
673
- ?>
674
- <h4><?php _e("You don't have any posts assigned to tags in this blog.", 'bulk-delete') ?></h4>
675
- <?php
676
- }
677
- }
678
-
679
- /**
680
- * Process Delete Posts by tag request
681
- *
682
- * @static
683
- * @since 5.0
684
- */
685
- public static function do_delete_posts_by_tag() {
686
-
687
- $delete_options = array();
688
- $delete_options['selected_tags'] = array_get($_POST, 'smbd_tags');
689
- $delete_options['restrict'] = array_get($_POST, 'smbd_tags_restrict', FALSE);
690
- $delete_options['private'] = array_get($_POST, 'smbd_tags_private');
691
- $delete_options['limit_to'] = absint(array_get($_POST, 'smbd_tags_limit_to', 0));
692
- $delete_options['force_delete'] = array_get($_POST, 'smbd_tags_force_delete', 'false');
693
-
694
- $delete_options['tags_op'] = array_get($_POST, 'smbd_tags_op');
695
- $delete_options['tags_days'] = array_get($_POST, 'smbd_tags_days');
696
-
697
- if (array_get($_POST, 'smbd_tags_cron', 'false') == 'true') {
698
- $freq = $_POST['smbd_tags_cron_freq'];
699
- $time = strtotime($_POST['smbd_tags_cron_start']) - ( get_option('gmt_offset') * 60 * 60 );
700
-
701
- if ($freq == -1) {
702
- wp_schedule_single_event($time, Bulk_Delete::CRON_HOOK_TAG, array($delete_options));
703
- } else {
704
- wp_schedule_event($time, $freq, Bulk_Delete::CRON_HOOK_TAG, array($delete_options));
705
- }
706
- $msg = __('Posts from the selected tags are scheduled for deletion.', 'bulk-delete') . ' ' .
707
- sprintf( __( 'See the full list of <a href = "%s">scheduled tasks</a>' , 'bulk-delete' ), get_bloginfo( "wpurl" ) . '/wp-admin/admin.php?page=' . Bulk_Delete::CRON_PAGE_SLUG );
708
- } else {
709
- $deleted_count = self::delete_posts_by_tag( $delete_options );
710
- $msg = sprintf( _n('Deleted %d post from the selected tags', 'Deleted %d posts from the selected tags' , $deleted_count, 'bulk-delete' ), $deleted_count);
711
- }
712
-
713
- add_settings_error(
714
- Bulk_Delete::POSTS_PAGE_SLUG,
715
- 'deleted-posts',
716
- $msg,
717
- 'updated'
718
- );
719
- }
720
-
721
- /**
722
- * Delete posts by tag
723
- *
724
- * @since 5.0
725
- * @static
726
- * @param array $delete_options Options for deleting posts
727
- * @return int $posts_deleted Number of posts that were deleted
728
- */
729
- public static function delete_posts_by_tag( $delete_options ) {
730
-
731
- $selected_tags = $delete_options['selected_tags'];
732
- $options = array('tag__in'=>$selected_tags, 'post_status'=>'publish', 'post_type'=>'post');
733
-
734
- $private = $delete_options['private'];
735
-
736
- if ($private == 'true') {
737
- $options['post_status'] = 'private';
738
- }
739
-
740
- $limit_to = $delete_options['limit_to'];
741
-
742
- if ($limit_to > 0) {
743
- $options['showposts'] = $limit_to;
744
- } else {
745
- $options['nopaging'] = 'true';
746
- }
747
-
748
- $force_delete = $delete_options['force_delete'];
749
-
750
- if ($force_delete == 'true') {
751
- $force_delete = true;
752
- } else {
753
- $force_delete = false;
754
- }
755
-
756
- if ($delete_options['restrict'] == "true") {
757
- $options['op'] = $delete_options['tags_op'];
758
- $options['days'] = $delete_options['tags_days'];
759
-
760
- if ( !class_exists( 'Bulk_Delete_By_Days' ) ) {
761
- require_once Bulk_Delete::$PLUGIN_DIR . '/include/class-bulk-delete-by-days.php';
762
- }
763
- $bulk_Delete_By_Days = new Bulk_Delete_By_Days;
764
- }
765
-
766
- $wp_query = new WP_Query();
767
- $posts = $wp_query->query($options);
768
-
769
- foreach ($posts as $post) {
770
- wp_delete_post($post->ID, $force_delete);
771
- }
772
-
773
- return count($posts);
774
- }
775
-
776
- /**
777
- * Render delete by custom taxonomy box
778
- */
779
- public static function render_delete_posts_by_taxonomy_box() {
780
-
781
- if ( Bulk_Delete_Util::is_posts_box_hidden(Bulk_Delete::BOX_TAX) ) {
782
- printf( __( 'This section just got enabled. Kindly <a href = "%1$s">refresh</a> the page to fully enable it.', 'bulk-delete' ), 'admin.php?page=' . Bulk_Delete::POSTS_PAGE_SLUG );
783
- return;
784
- }
785
-
786
- $types = get_post_types( array(
787
- '_builtin' => false
788
- ), 'names'
789
- );
790
-
791
- array_unshift( $types, 'post' );
792
-
793
- $taxs = get_taxonomies(array(
794
- 'public' => true,
795
- '_builtin' => false
796
- ), 'objects'
797
- );
798
-
799
- $terms_array = array();
800
- if (count($taxs) > 0) {
801
- foreach ($taxs as $tax) {
802
- $terms = get_terms($tax->name);
803
- if (count($terms) > 0) {
804
- $terms_array[$tax->name] = $terms;
805
- }
806
- }
807
- }
808
-
809
- if ( count( $terms_array ) > 0 ) {
810
- ?>
811
- <!-- Custom tax Start-->
812
- <h4><?php _e( 'Select the post type whose taxonomy posts you want to delete', 'bulk-delete' ); ?></h4>
813
-
814
- <fieldset class="options">
815
- <table class="optiontable">
816
- <?php
817
- foreach ( $types as $type ) {
818
- ?>
819
- <tr>
820
- <td scope="row" >
821
- <input name="smbd_tax_post_type" value = "<?php echo $type; ?>" type = "radio" class = "smbd_tax_post_type" <?php checked( $type, 'post' ); ?>>
822
- </td>
823
- <td>
824
- <label for="smbd_tax_post_type"><?php echo $type; ?> </label>
825
- </td>
826
- </tr>
827
- <?php
828
- }
829
- ?>
830
- </table>
831
-
832
- <h4><?php _e("Select the taxonomies whose post you want to delete", 'bulk-delete') ?></h4>
833
-
834
- <table class="optiontable">
835
- <?php
836
- foreach ($terms_array as $tax => $terms) {
837
- ?>
838
- <tr>
839
- <td scope="row" >
840
- <input name="smbd_taxs" value = "<?php echo $tax; ?>" type = "radio" class = "custom-tax">
841
- </td>
842
- <td>
843
- <label for="smbd_taxs"><?php echo $taxs[$tax]->labels->name; ?> </label>
844
- </td>
845
- </tr>
846
- <?php
847
- }
848
- ?>
849
- </table>
850
-
851
- <h4><?php _e("The selected taxonomy has the following terms. Select the terms whose post you want to delete", 'bulk-delete') ?></h4>
852
- <p><?php _e( 'Note: The post count below for each term is the total number of posts in that term, irrespective of post type', 'bulk-delete' ); ?></p>
853
- <?php
854
- foreach ($terms_array as $tax => $terms) {
855
- ?>
856
- <table class="optiontable terms_<?php echo $tax;?> terms">
857
- <?php
858
- foreach ($terms as $term) {
859
- ?>
860
- <tr>
861
- <td scope="row" >
862
- <input name="smbd_tax_terms[]" value = "<?php echo $term->slug; ?>" type = "checkbox" class = "terms" >
863
- </td>
864
- <td>
865
- <label for="smbd_tax_terms"><?php echo $term->name; ?> (<?php echo $term->count . " "; _e("Posts", 'bulk-delete'); ?>)</label>
866
- </td>
867
- </tr>
868
- <?php
869
- }
870
- ?>
871
- </table>
872
- <?php
873
- }
874
- ?>
875
- <table class="optiontable">
876
- <tr>
877
- <td colspan="2">
878
- <h4><?php _e("Choose your filtering options", 'bulk-delete'); ?></h4>
879
- </td>
880
- </tr>
881
-
882
- <tr>
883
- <td scope="row">
884
- <input name="smbd_taxs_restrict" id ="smbd_taxs_restrict" value = "true" type = "checkbox">
885
- </td>
886
- <td>
887
- <?php _e("Only restrict to posts which are ", 'bulk-delete');?>
888
- <select name="smbd_taxs_op" id="smbd_taxs_op" disabled>
889
- <option value ="<"><?php _e("older than", 'bulk-delete');?></option>
890
- <option value =">"><?php _e("posted within last", 'bulk-delete');?></option>
891
- </select>
892
- <input type ="textbox" name="smbd_taxs_days" id ="smbd_taxs_days" value ="0" maxlength="4" size="4" disabled /><?php _e("days", 'bulk-delete');?>
893
- </td>
894
- </tr>
895
-
896
- <tr>
897
- <td scope="row" colspan="2">
898
- <input name="smbd_taxs_force_delete" value = "false" type = "radio" checked="checked" /> <?php _e('Move to Trash', 'bulk-delete'); ?>
899
- <input name="smbd_taxs_force_delete" value = "true" type = "radio" /> <?php _e('Delete permanently', 'bulk-delete'); ?>
900
- </td>
901
- </tr>
902
-
903
- <tr>
904
- <td scope="row" colspan="2">
905
- <input name="smbd_taxs_private" value = "false" type = "radio" checked="checked" /> <?php _e('Public posts', 'bulk-delete'); ?>
906
- <input name="smbd_taxs_private" value = "true" type = "radio" /> <?php _e('Private Posts', 'bulk-delete'); ?>
907
- </td>
908
- </tr>
909
-
910
- <tr>
911
- <td scope="row">
912
- <input name="smbd_taxs_limit" id="smbd_taxs_limit" value = "true" type = "checkbox">
913
- </td>
914
- <td>
915
- <?php _e("Only delete first ", 'bulk-delete');?>
916
- <input type ="textbox" name="smbd_taxs_limit_to" id="smbd_taxs_limit_to" disabled value ="0" maxlength="4" size="4" /><?php _e("posts.", 'bulk-delete');?>
917
- <?php _e("Use this option if there are more than 1000 posts and the script timesout.", 'bulk-delete') ?>
918
- </td>
919
- </tr>
920
-
921
- <tr>
922
- <td scope="row" colspan="2">
923
- <input name="smbd_taxs_cron" value = "false" type = "radio" checked="checked" > <?php _e('Delete now', 'bulk-delete'); ?>
924
- <input name="smbd_taxs_cron" value = "true" type = "radio" id = "smbd_taxs_cron" disabled > <?php _e('Schedule', 'bulk-delete'); ?>
925
- <input name="smbd_taxs_cron_start" id = "smbd_taxs_cron_start" value = "now" type = "text" disabled><?php _e('repeat ', 'bulk-delete');?>
926
- <select name = "smbd_taxs_cron_freq" id = "smbd_taxs_cron_freq" disabled>
927
- <option value = "-1"><?php _e("Don't repeat", 'bulk-delete'); ?></option>
928
- <?php
929
- $schedules = wp_get_schedules();
930
- foreach($schedules as $key => $value) {
931
- ?>
932
- <option value = "<?php echo $key; ?>"><?php echo $value['display']; ?></option>
933
- <?php
934
- }
935
- ?>
936
- </select>
937
- <span class = "bd-taxs-pro" style = "color:red"><?php _e('Only available in Pro Addon', 'bulk-delete'); ?> <a href = "http://bulkwp.com/addons/scheduler-for-deleting-posts-by-taxonomy/?utm_source=wpadmin&utm_campaign=BulkDelete&utm_medium=buynow&utm_content=bd-stx">Buy now</a></span>
938
- </td>
939
- </tr>
940
-
941
- </table>
942
- </fieldset>
943
- <p class="submit">
944
- <button type="submit" name="bd_action" value = "delete_posts_by_taxonomy" class="button-primary"><?php _e("Bulk Delete ", 'bulk-delete') ?>&raquo;</button>
945
- </p>
946
- <!-- Custom tax end-->
947
- <?php
948
- } else {
949
- ?>
950
- <h4><?php _e("You don't have any posts assigned to custom taxonomies in this blog.", 'bulk-delete') ?></h4>
951
- <?php
952
- }
953
- }
954
-
955
- /**
956
- * Process Delete posts by Taxonomy Request
957
- *
958
- * @static
959
- * @since 5.0
960
- */
961
- public static function do_delete_posts_by_taxonomy() {
962
-
963
- $delete_options = array();
964
- $delete_options['post_type'] = array_get( $_POST, 'smbd_tax_post_type', 'post' );
965
- $delete_options['selected_taxs'] = array_get($_POST, 'smbd_taxs');
966
- $delete_options['selected_tax_terms'] = array_get($_POST, 'smbd_tax_terms');
967
- $delete_options['restrict'] = array_get($_POST, 'smbd_taxs_restrict', FALSE);
968
- $delete_options['private'] = array_get($_POST, 'smbd_taxs_private');
969
- $delete_options['limit_to'] = absint(array_get($_POST, 'smbd_taxs_limit_to', 0));
970
- $delete_options['force_delete'] = array_get($_POST, 'smbd_taxs_force_delete', 'false');
971
-
972
- $delete_options['taxs_op'] = array_get($_POST, 'smbd_taxs_op');
973
- $delete_options['taxs_days'] = array_get($_POST, 'smbd_taxs_days');
974
-
975
- if (array_get($_POST, 'smbd_taxs_cron', 'false') == 'true') {
976
- $freq = $_POST['smbd_taxs_cron_freq'];
977
- $time = strtotime($_POST['smbd_taxs_cron_start']) - ( get_option('gmt_offset') * 60 * 60 );
978
-
979
- if ($freq == -1) {
980
- wp_schedule_single_event($time, Bulk_Delete::CRON_HOOK_TAXONOMY, array($delete_options));
981
- } else {
982
- wp_schedule_event($time, $freq, Bulk_Delete::CRON_HOOK_TAXONOMY, array($delete_options));
983
- }
984
- $msg = __('Posts from the selected custom taxonomies are scheduled for deletion.', 'bulk-delete') . ' ' .
985
- sprintf( __( 'See the full list of <a href = "%s">scheduled tasks</a>' , 'bulk-delete' ), get_bloginfo( "wpurl" ) . '/wp-admin/admin.php?page=' . Bulk_Delete::CRON_PAGE_SLUG );
986
- } else {
987
- $deleted_count = self::delete_posts_by_taxonomy( $delete_options );
988
- $msg = sprintf( _n('Deleted %d post from the selected custom taxonomies', 'Deleted %d posts from the selected custom taxonomies' , $deleted_count, 'bulk-delete' ), $deleted_count);
989
- }
990
-
991
- add_settings_error(
992
- Bulk_Delete::POSTS_PAGE_SLUG,
993
- 'deleted-posts',
994
- $msg,
995
- 'updated'
996
- );
997
- }
998
-
999
- /**
1000
- * Delete posts by custom taxonomy
1001
- *
1002
- * @since 5.0
1003
- * @static
1004
- * @param array $delete_options Options for deleting posts
1005
- * @return int $posts_deleted Number of posts that were deleted
1006
- */
1007
- public static function delete_posts_by_taxonomy( $delete_options ) {
1008
-
1009
- // For compatibility reasons set default post type to 'post'
1010
- $post_type = array_get( $delete_options, 'post_type', 'post' );
1011
- $selected_taxs = $delete_options['selected_taxs'];
1012
- $selected_tax_terms = $delete_options['selected_tax_terms'];
1013
-
1014
- $options = array(
1015
- 'post_status' => 'publish',
1016
- 'post_type' => $post_type,
1017
- 'tax_query' => array(
1018
- array(
1019
- 'taxonomy' => $selected_taxs,
1020
- 'terms' => $selected_tax_terms,
1021
- 'field' => 'slug'
1022
- )
1023
- )
1024
- );
1025
-
1026
- $private = $delete_options['private'];
1027
-
1028
- if ($private == 'true') {
1029
- $options['post_status'] = 'private';
1030
- }
1031
-
1032
- $limit_to = $delete_options['limit_to'];
1033
-
1034
- if ($limit_to > 0) {
1035
- $options['showposts'] = $limit_to;
1036
- } else {
1037
- $options['nopaging'] = 'true';
1038
- }
1039
-
1040
- $force_delete = $delete_options['force_delete'];
1041
-
1042
- if ($force_delete == 'true') {
1043
- $force_delete = true;
1044
- } else {
1045
- $force_delete = false;
1046
- }
1047
-
1048
- if ($delete_options['restrict'] == "true") {
1049
- $options['op'] = $delete_options['taxs_op'];
1050
- $options['days'] = $delete_options['taxs_days'];
1051
-
1052
- if ( !class_exists( 'Bulk_Delete_By_Days' ) ) {
1053
- require_once Bulk_Delete::$PLUGIN_DIR . '/include/class-bulk-delete-by-days.php';
1054
- }
1055
- $bulk_Delete_By_Days = new Bulk_Delete_By_Days;
1056
- }
1057
-
1058
- $wp_query = new WP_Query();
1059
- $posts = $wp_query->query($options);
1060
-
1061
- foreach ($posts as $post) {
1062
- // $force delete parameter to custom post types doesn't work
1063
- if ( $force_delete ) {
1064
- wp_delete_post( $post->ID, TRUE );
1065
- } else {
1066
- wp_trash_post( $post->ID );
1067
- }
1068
- }
1069
-
1070
- return count( $posts );
1071
- }
1072
-
1073
-
1074
- /**
1075
- * Render delete by custom post type box
1076
- *
1077
- * @static
1078
- */
1079
- public static function render_delete_posts_by_post_type_box() {
1080
-
1081
- if ( Bulk_Delete_Util::is_posts_box_hidden(Bulk_Delete::BOX_POST_TYPE) ) {
1082
- printf( __( 'This section just got enabled. Kindly <a href = "%1$s">refresh</a> the page to fully enable it.', 'bulk-delete' ), 'admin.php?page=' . Bulk_Delete::POSTS_PAGE_SLUG );
1083
- return;
1084
- }
1085
-
1086
- $types_array = array();
1087
-
1088
- $types = get_post_types( array(
1089
- '_builtin' => false
1090
- ), 'names'
1091
- );
1092
-
1093
- if ( count( $types ) > 0 ) {
1094
- foreach ($types as $type) {
1095
- $post_count = wp_count_posts( $type );
1096
- if ( $post_count->publish > 0 ) {
1097
- $types_array["$type-publish"] = $post_count->publish;
1098
- }
1099
- if ( $post_count->future > 0 ) {
1100
- $types_array["$type-future"] = $post_count->future;
1101
- }
1102
- if ( $post_count->pending > 0 ) {
1103
- $types_array["$type-pending"] = $post_count->pending;
1104
- }
1105
- if ( $post_count->draft > 0 ) {
1106
- $types_array["$type-draft"] = $post_count->draft;
1107
- }
1108
- if ( $post_count->private > 0 ) {
1109
- $types_array["$type-private"] = $post_count->private;
1110
- }
1111
- }
1112
- }
1113
-
1114
- if ( count( $types_array ) > 0 ) {
1115
- ?>
1116
- <!-- Custom post type Start-->
1117
- <h4><?php _e( "Select the custom post type whose post you want to delete", 'bulk-delete' ) ?></h4>
1118
-
1119
- <fieldset class="options">
1120
- <table class="optiontable">
1121
- <?php
1122
- foreach ( $types_array as $type => $count ) {
1123
- ?>
1124
- <tr>
1125
- <td scope="row" >
1126
- <input name="smbd_types[]" value = "<?php echo $type; ?>" type = "checkbox">
1127
- </td>
1128
- <td>
1129
- <label for="smbd_types"><?php echo Bulk_Delete_Util::display_post_type_status( $type ), ' (', $count, ')'; ?></label>
1130
- </td>
1131
- </tr>
1132
- <?php
1133
- }
1134
- ?>
1135
- <tr>
1136
- <td colspan="2">
1137
- <h4><?php _e("Choose your filtering options", 'bulk-delete'); ?></h4>
1138
- </td>
1139
- </tr>
1140
-
1141
- <tr>
1142
- <td scope="row">
1143
- <input name="smbd_types_restrict" id ="smbd_types_restrict" value = "true" type = "checkbox">
1144
- </td>
1145
- <td>
1146
- <?php _e("Only restrict to posts which are ", 'bulk-delete');?>
1147
- <select name="smbd_types_op" id="smbd_types_op" disabled>
1148
- <option value ="<"><?php _e("older than", 'bulk-delete');?></option>
1149
- <option value =">"><?php _e("posted within last", 'bulk-delete');?></option>
1150
- </select>
1151
- <input type ="textbox" name="smbd_types_days" id ="smbd_types_days" value ="0" maxlength="4" size="4" disabled /><?php _e("days", 'bulk-delete');?>
1152
- </td>
1153
- </tr>
1154
-
1155
- <tr>
1156
- <td scope="row" colspan="2">
1157
- <input name="smbd_types_force_delete" value = "false" type = "radio" checked="checked" /> <?php _e('Move to Trash', 'bulk-delete'); ?>
1158
- <input name="smbd_types_force_delete" value = "true" type = "radio" /> <?php _e('Delete permanently', 'bulk-delete'); ?>
1159
- </td>
1160
- </tr>
1161
-
1162
- <tr>
1163
- <td scope="row">
1164
- <input name="smbd_types_limit" id="smbd_types_limit" value = "true" type = "checkbox">
1165
- </td>
1166
- <td>
1167
- <?php _e("Only delete first ", 'bulk-delete');?>
1168
- <input type ="textbox" name="smbd_types_limit_to" id="smbd_types_limit_to" disabled value ="0" maxlength="4" size="4" /><?php _e("posts.", 'bulk-delete');?>
1169
- <?php _e("Use this option if there are more than 1000 posts and the script timesout.", 'bulk-delete') ?>
1170
- </td>
1171
- </tr>
1172
-
1173
- <tr>
1174
- <td scope="row" colspan="2">
1175
- <input name="smbd_types_cron" value = "false" type = "radio" checked="checked" > <?php _e('Delete now', 'bulk-delete'); ?>
1176
- <input name="smbd_types_cron" value = "true" type = "radio" id = "smbd_types_cron" disabled > <?php _e('Schedule', 'bulk-delete'); ?>
1177
- <input name="smbd_types_cron_start" id = "smbd_types_cron_start" value = "now" type = "text" disabled><?php _e('repeat ', 'bulk-delete');?>
1178
- <select name = "smbd_types_cron_freq" id = "smbd_types_cron_freq" disabled>
1179
- <option value = "-1"><?php _e("Don't repeat", 'bulk-delete'); ?></option>
1180
- <?php
1181
- $schedules = wp_get_schedules();
1182
- foreach($schedules as $key => $value) {
1183
- ?>
1184
- <option value = "<?php echo $key; ?>"><?php echo $value['display']; ?></option>
1185
- <?php
1186
- }
1187
- ?>
1188
- </select>
1189
- <span class = "bd-types-pro" style = "color:red"><?php _e('Only available in Pro Addon', 'bulk-delete'); ?> <a href = "http://bulkwp.com/addons/scheduler-for-deleting-posts-by-post-type/?utm_source=wpadmin&utm_campaign=BulkDelete&utm_medium=buynow&utm_content=bd-spt">Buy now</a></span>
1190
- </td>
1191
- </tr>
1192
-
1193
- </table>
1194
- </fieldset>
1195
- <p class="submit">
1196
- <button type="submit" name="bd_action" value = "delete_posts_by_post_type" class="button-primary"><?php _e("Bulk Delete ", 'bulk-delete') ?>&raquo;</button>
1197
- </p>
1198
- <!-- Custom post type end-->
1199
- <?php
1200
- } else {
1201
- ?>
1202
- <h4><?php _e("You don't have any posts assigned to custom post types in this blog.", 'bulk-delete') ?></h4>
1203
- <?php
1204
- }
1205
- }
1206
-
1207
- /**
1208
- * Process request to delete posts by post type
1209
- *
1210
- * @static
1211
- * @since 5.0
1212
- */
1213
- public static function do_delete_posts_by_post_type() {
1214
-
1215
- $delete_options = array();
1216
-
1217
- $delete_options['selected_types'] = array_get( $_POST, 'smbd_types' );
1218
- $delete_options['restrict'] = array_get($_POST, 'smbd_types_restrict', FALSE);
1219
- $delete_options['limit_to'] = absint(array_get($_POST, 'smbd_types_limit_to', 0));
1220
- $delete_options['force_delete'] = array_get($_POST, 'smbd_types_force_delete', 'false');
1221
-
1222
- $delete_options['types_op'] = array_get($_POST, 'smbd_types_op');
1223
- $delete_options['types_days'] = array_get($_POST, 'smbd_types_days');
1224
-
1225
- if (array_get($_POST, 'smbd_types_cron', 'false') == 'true') {
1226
- $freq = $_POST['smbd_types_cron_freq'];
1227
- $time = strtotime($_POST['smbd_types_cron_start']) - ( get_option('gmt_offset') * 60 * 60 );
1228
-
1229
- if ($freq == -1) {
1230
- wp_schedule_single_event( $time, Bulk_Delete::CRON_HOOK_POST_TYPE, array( $delete_options ) );
1231
- } else {
1232
- wp_schedule_event( $time, $freq, Bulk_Delete::CRON_HOOK_POST_TYPE, array( $delete_options ) );
1233
- }
1234
-
1235
- $msg = __( 'Posts from the selected custom post type are scheduled for deletion.', 'bulk-delete') . ' ' .
1236
- sprintf( __( 'See the full list of <a href = "%s">scheduled tasks</a>' , 'bulk-delete' ), get_bloginfo( "wpurl" ) . '/wp-admin/admin.php?page=' . Bulk_Delete::CRON_PAGE_SLUG );
1237
- } else {
1238
- $deleted_count = self::delete_posts_by_post_type( $delete_options );
1239
- $msg = sprintf( _n( 'Deleted %d post from the selected custom post type', 'Deleted %d posts from the selected custom post type' , $deleted_count, 'bulk-delete' ), $deleted_count );
1240
- }
1241
-
1242
- add_settings_error(
1243
- Bulk_Delete::POSTS_PAGE_SLUG,
1244
- 'deleted-posts',
1245
- $msg,
1246
- 'updated'
1247
- );
1248
- }
1249
-
1250
- /**
1251
- * Delete posts by custom post type
1252
- *
1253
- * @static
1254
- * @since 5.0
1255
- * @param array $delete_options Options for deleting posts
1256
- * @return int $posts_deleted Number of posts that were deleted
1257
- */
1258
- public static function delete_posts_by_post_type( $delete_options ) {
1259
- $count = 0;
1260
- $selected_types = $delete_options['selected_types'];
1261
-
1262
- foreach ( $selected_types as $selected_type ) {
1263
-
1264
- $type_status = Bulk_Delete_Util::split_post_type_status( $selected_type );
1265
-
1266
- $type = $type_status['type'];
1267
- $status = $type_status['status'];
1268
-
1269
- $options = array(
1270
- 'post_status' => $status,
1271
- 'post_type' => $type
1272
- );
1273
-
1274
- $limit_to = $delete_options['limit_to'];
1275
-
1276
- if ( $limit_to > 0 ) {
1277
- $options['showposts'] = $limit_to;
1278
- } else {
1279
- $options['nopaging'] = 'true';
1280
- }
1281
-
1282
- $force_delete = $delete_options['force_delete'];
1283
-
1284
- if ( $force_delete == 'true' ) {
1285
- $force_delete = true;
1286
- } else {
1287
- $force_delete = false;
1288
- }
1289
-
1290
- if ($delete_options['restrict'] == "true") {
1291
- $options['op'] = $delete_options['types_op'];
1292
- $options['days'] = $delete_options['types_days'];
1293
-
1294
- if ( !class_exists( 'Bulk_Delete_By_Days' ) ) {
1295
- require_once Bulk_Delete::$PLUGIN_DIR . '/include/class-bulk-delete-by-days.php';
1296
- }
1297
- $bulk_Delete_By_Days = new Bulk_Delete_By_Days;
1298
- }
1299
-
1300
- $wp_query = new WP_Query();
1301
- $posts = $wp_query->query( $options );
1302
-
1303
- foreach ( $posts as $post ) {
1304
- // $force delete parameter to custom post types doesn't work
1305
- if ( $force_delete ) {
1306
- wp_delete_post( $post->ID, TRUE );
1307
- } else {
1308
- wp_trash_post( $post->ID );
1309
- }
1310
- }
1311
-
1312
- $count += count( $posts );
1313
- }
1314
-
1315
- return $count;
1316
- }
1317
-
1318
- /**
1319
- * Render delete by url box
1320
- *
1321
- * @static
1322
- */
1323
- public static function render_delete_posts_by_url_box() {
1324
-
1325
- if ( Bulk_Delete_Util::is_posts_box_hidden(Bulk_Delete::BOX_URL) ) {
1326
- printf( __( 'This section just got enabled. Kindly <a href = "%1$s">refresh</a> the page to fully enable it.', 'bulk-delete' ), 'admin.php?page=' . Bulk_Delete::POSTS_PAGE_SLUG );
1327
- return;
1328
- }
1329
- ?>
1330
- <!-- URLs start-->
1331
- <h4><?php _e( 'Delete posts and pages that have the following Permalink', 'bulk-delete' ); ?></h4>
1332
-
1333
- <fieldset class="options">
1334
- <table class="optiontable">
1335
- <tr>
1336
- <td scope="row">
1337
- <label for="smdb_specific_pages"><?php _e("Enter one post url (not post ids) per line", 'bulk-delete'); ?></label>
1338
- <br/>
1339
- <textarea style="width: 450px; height: 80px;" id="smdb_specific_pages_urls" name="smdb_specific_pages_urls" rows="5" columns="80" ></textarea>
1340
- </td>
1341
- </tr>
1342
-
1343
- <tr>
1344
- <td>
1345
- <h4><?php _e("Choose your filtering options", 'bulk-delete'); ?></h4>
1346
- </td>
1347
- </tr>
1348
-
1349
- <tr>
1350
- <td scope="row">
1351
- <input name="smbd_specific_force_delete" value = "false" type = "radio" checked="checked" /> <?php _e('Move to Trash', 'bulk-delete'); ?>
1352
- <input name="smbd_specific_force_delete" value = "true" type = "radio" /> <?php _e('Delete permanently', 'bulk-delete'); ?>
1353
- </td>
1354
- </tr>
1355
-
1356
- </table>
1357
- </fieldset>
1358
-
1359
- <p>
1360
- <button type="submit" name="bd_action" value = "delete_posts_by_url" class="button-primary"><?php _e("Bulk Delete ", 'bulk-delete') ?>&raquo;</button>
1361
- </p>
1362
- <!-- URLs end-->
1363
- <?php
1364
- }
1365
-
1366
- /**
1367
- * Delete posts by url
1368
- *
1369
- * @static
1370
- * @since 5.0
1371
- */
1372
- public static function do_delete_posts_by_url() {
1373
-
1374
- $force_delete = array_get($_POST, 'smbd_specific_force_delete');
1375
- if ($force_delete == 'true') {
1376
- $force_delete = true;
1377
- } else {
1378
- $force_delete = false;
1379
- }
1380
-
1381
- $urls = preg_split( '/\r\n|\r|\n/', array_get($_POST, 'smdb_specific_pages_urls') );
1382
- foreach ($urls as $url) {
1383
- $checkedurl = $url;
1384
- if (substr($checkedurl ,0,1) == '/') {
1385
- $checkedurl = get_site_url() . $checkedurl ;
1386
- }
1387
- $postid = url_to_postid( $checkedurl );
1388
- wp_delete_post($postid, $force_delete);
1389
- }
1390
-
1391
- $deleted_count = count( $url );
1392
- $msg = sprintf( _n( 'Deleted %d post with the specified urls', 'Deleted %d posts with the specified urls' , $deleted_count, 'bulk-delete' ), $deleted_count);
1393
-
1394
- add_settings_error(
1395
- Bulk_Delete::POSTS_PAGE_SLUG,
1396
- 'deleted-posts',
1397
- $msg,
1398
- 'updated'
1399
- );
1400
- }
1401
-
1402
- /**
1403
- * Render delete by post revisions box
1404
- *
1405
- * @static
1406
- */
1407
- public static function render_posts_by_revision_box() {
1408
-
1409
- if ( Bulk_Delete_Util::is_posts_box_hidden(Bulk_Delete::BOX_POST_REVISION) ) {
1410
- printf( __( 'This section just got enabled. Kindly <a href = "%1$s">refresh</a> the page to fully enable it.', 'bulk-delete' ), 'admin.php?page=' . Bulk_Delete::POSTS_PAGE_SLUG );
1411
- return;
1412
- }
1413
-
1414
- global $wpdb;
1415
-
1416
- $revisions = $wpdb->get_var("select count(*) from $wpdb->posts where post_type = 'revision'");
1417
- ?>
1418
- <!-- Post Revisions start-->
1419
- <h4><?php _e("Select the posts which you want to delete", 'bulk-delete'); ?></h4>
1420
-
1421
- <fieldset class="options">
1422
- <table class="optiontable">
1423
- <tr>
1424
- <td>
1425
- <input name="smbd_revisions" id ="smbd_revisions" value = "revisions" type = "checkbox" />
1426
- <label for="smbd_revisions"><?php _e("All Revisions", 'bulk-delete'); ?> (<?php echo $revisions . " "; _e("Revisions", 'bulk-delete'); ?>)</label>
1427
- </td>
1428
- </tr>
1429
-
1430
- </table>
1431
- </fieldset>
1432
-
1433
- <p>
1434
- <button type="submit" name="bd_action" value = "delete_posts_by_revision" class="button-primary"><?php _e("Bulk Delete ", 'bulk-delete') ?>&raquo;</button>
1435
- </p>
1436
- <!-- Post Revisions end-->
1437
- <?php
1438
- }
1439
-
1440
- /**
1441
- * Process delete revisions request
1442
- *
1443
- * @static
1444
- * @since 5.0
1445
- */
1446
- public static function do_delete_posts_by_revision() {
1447
- $delete_options['revisions'] = array_get( $_POST, 'smbd_revisions' );
1448
- $deleted_count = self::delete_posts_by_revision( $delete_options );
1449
-
1450
- $msg = sprintf( _n( 'Deleted %d post revision', 'Deleted %d post revisions' , $deleted_count, 'bulk-delete' ), $deleted_count );
1451
-
1452
- add_settings_error(
1453
- Bulk_Delete::POSTS_PAGE_SLUG,
1454
- 'deleted-posts',
1455
- $msg,
1456
- 'updated'
1457
- );
1458
- }
1459
-
1460
- /**
1461
- * Delete all post revisions
1462
- *
1463
- * @since 5.0
1464
- * @static
1465
- */
1466
- public static function delete_posts_by_revision( $delete_options ) {
1467
- global $wpdb;
1468
-
1469
- // Revisions
1470
- if ("revisions" == $delete_options['revisions']) {
1471
- $revisions = $wpdb->get_results("select ID from $wpdb->posts where post_type = 'revision'");
1472
-
1473
- foreach ($revisions as $revision) {
1474
- wp_delete_post( $revision->ID );
1475
- }
1476
-
1477
- return count( $revisions );
1478
- }
1479
-
1480
- return 0;
1481
- }
1482
-
1483
- /**
1484
- * Render delete posts by custom field box
1485
- *
1486
- * @static
1487
- */
1488
- public static function render_delete_posts_by_custom_field_box() {
1489
-
1490
- if ( Bulk_Delete_Util::is_posts_box_hidden( Bulk_Delete::BOX_CUSTOM_FIELD ) ) {
1491
- printf( __( 'This section just got enabled. Kindly <a href = "%1$s">refresh</a> the page to fully enable it.', 'bulk-delete' ), 'admin.php?page=' . Bulk_Delete::POSTS_PAGE_SLUG );
1492
- return;
1493
- }
1494
-
1495
- if ( !class_exists( 'Bulk_Delete_Posts_By_Custom_Field' ) ) {
1496
- ?>
1497
- <!-- Custom Field box start-->
1498
- <p>
1499
- <span class = "bd-post-custom-field-pro" style = "color:red">
1500
- <?php _e( 'You need "Bulk Delete Posts by Custom Field" Addon, to delete post by custom field.', 'bulk-delete' ); ?>
1501
- <a href = "http://bulkwp.com/addons/bulk-delete-posts-by-custom-field/?utm_source=wpadmin&utm_campaign=BulkDelete&utm_medium=buynow&utm_content=bd-cf">Buy now</a>
1502
- </span>
1503
- </p>
1504
- <!-- Custom Field box end-->
1505
- <?php
1506
- } else {
1507
- Bulk_Delete_Posts_By_Custom_Field::render_delete_posts_by_custom_field_box();
1508
- }
1509
- }
1510
-
1511
- /**
1512
- * Render posts by title box
1513
- *
1514
- * @since 5.0
1515
- * @static
1516
- */
1517
- public static function render_delete_posts_by_title_box() {
1518
-
1519
- if ( Bulk_Delete_Util::is_posts_box_hidden( Bulk_Delete::BOX_TITLE ) ) {
1520
- printf( __( 'This section just got enabled. Kindly <a href = "%1$s">refresh</a> the page to fully enable it.', 'bulk-delete' ), 'admin.php?page=' . Bulk_Delete::POSTS_PAGE_SLUG );
1521
- return;
1522
- }
1523
-
1524
- if ( !class_exists( 'Bulk_Delete_Posts_By_Title' ) ) {
1525
- ?>
1526
- <!-- Title box start-->
1527
- <p>
1528
- <span class = "bd-post-title-pro" style = "color:red">
1529
- <?php _e( 'You need "Bulk Delete Posts by Title" Addon, to delete post by title.', 'bulk-delete' ); ?>
1530
- <a href = "http://bulkwp.com/addons/bulk-delete-posts-by-title/?utm_source=wpadmin&utm_campaign=BulkDelete&utm_medium=buynow&utm_content=bd-ti">Buy now</a>
1531
- </span>
1532
- </p>
1533
- <!-- Title box end-->
1534
- <?php
1535
- } else {
1536
- Bulk_Delete_Posts_By_Title::render_delete_posts_by_title_box();
1537
- }
1538
- }
1539
-
1540
- /**
1541
- * Render delete posts by duplicate title box
1542
- *
1543
- * @since 5.0
1544
- * @static
1545
- * @access public
1546
- */
1547
- public static function render_delete_posts_by_duplicate_title_box() {
1548
-
1549
- if ( Bulk_Delete_Util::is_posts_box_hidden( Bulk_Delete::BOX_DUPLICATE_TITLE ) ) {
1550
- printf( __( 'This section just got enabled. Kindly <a href = "%1$s">refresh</a> the page to fully enable it.', 'bulk-delete' ), 'admin.php?page=' . Bulk_Delete::POSTS_PAGE_SLUG );
1551
- return;
1552
- }
1553
-
1554
- if ( !class_exists( 'Bulk_Delete_Posts_By_Duplicate_Title' ) ) {
1555
- ?>
1556
- <!-- Duplicate Title box start-->
1557
- <p>
1558
- <span class = "bd-post-title-pro" style = "color:red">
1559
- <?php _e( 'You need "Bulk Delete Posts by Duplicate Title" Addon, to delete post by duplicate title.', 'bulk-delete' ); ?>
1560
- <a href = "http://bulkwp.com/addons/bulk-delete-posts-by-duplicate-title/?utm_source=wpadmin&utm_campaign=BulkDelete&utm_medium=buynow&utm_content=bd-dti">Buy now</a>
1561
- </span>
1562
- </p>
1563
- <!-- Duplicate Title box end-->
1564
- <?php
1565
- } else {
1566
- Bulk_Delete_Posts_By_Duplicate_Title::render_delete_posts_by_duplicate_title_box();
1567
- }
1568
- }
1569
-
1570
- /**
1571
- * Delete posts by user role
1572
- *
1573
- * @static
1574
- * @since 5.2
1575
- */
1576
- public static function render_delete_posts_by_user_role_box() {
1577
-
1578
- if ( Bulk_Delete_Util::is_posts_box_hidden( Bulk_Delete::BOX_POST_BY_ROLE ) ) {
1579
- printf( __( 'This section just got enabled. Kindly <a href = "%1$s">refresh</a> the page to fully enable it.', 'bulk-delete' ), 'admin.php?page=' . Bulk_Delete::POSTS_PAGE_SLUG );
1580
- return;
1581
- }
1582
- if ( !class_exists( 'Bulk_Delete_Posts_By_User_Role' ) ) {
1583
- ?>
1584
- <!-- Posts by user role start-->
1585
- <p>
1586
- <span class = "bd-post-by-role-pro" style = "color:red">
1587
- <?php _e( 'You need "Bulk Delete Posts by User Role" Addon, to delete post based on User Role', 'bulk-delete' ); ?>
1588
- <a href = "http://bulkwp.com/addons/bulk-delete-posts-by-user-role/?utm_source=wpadmin&utm_campaign=BulkDelete&utm_medium=buynow&utm_content=bd-ur">Buy now</a>
1589
- </span>
1590
- </p>
1591
- <!-- Posts by user role end-->
1592
- <?php
1593
- } else {
1594
- Bulk_Delete_Posts_By_User_Role::render_delete_posts_by_user_role_box();
1595
- }
1596
- }
1597
-
1598
- /**
1599
- * Render delete posts from trash box
1600
- *
1601
- * @since 5.1
1602
- * @static
1603
- */
1604
- public static function render_delete_posts_from_trash() {
1605
- if ( Bulk_Delete_Util::is_posts_box_hidden( Bulk_Delete::BOX_POST_FROM_TRASH ) ) {
1606
- printf( __( 'This section just got enabled. Kindly <a href = "%1$s">refresh</a> the page to fully enable it.', 'bulk-delete' ), 'admin.php?page=' . Bulk_Delete::POSTS_PAGE_SLUG );
1607
- return;
1608
- }
1609
-
1610
- if ( !class_exists( 'Bulk_Delete_From_Trash' ) ) {
1611
- ?>
1612
- <!-- Posts In Trash box start-->
1613
- <p>
1614
- <span class = "bd-post-trash-pro" style = "color:red">
1615
- <?php _e( 'You need "Bulk Delete From Trash" Addon, to delete post in Trash.', 'bulk-delete' ); ?>
1616
- <a href = "http://bulkwp.com/addons/bulk-delete-from-trash/?utm_source=wpadmin&utm_campaign=BulkDelete&utm_medium=buynow&utm_content=bd-th">Buy now</a>
1617
- </span>
1618
- </p>
1619
- <!-- Posts In Trash box end-->
1620
- <?php
1621
- } else {
1622
- /**
1623
- * Render delete posts from trash box
1624
- *
1625
- * @since 5.4
1626
- */
1627
- do_action( 'bd_render_delete_posts_from_trash' );
1628
- }
1629
- }
1630
-
1631
- /**
1632
- * Filter JS Array and add validation hooks
1633
- *
1634
- * @since 5.4
1635
- * @static
1636
- * @param array $js_array JavaScript Array
1637
- * @return array Modified JavaScript Array
1638
- */
1639
- public static function filter_js_array( $js_array ) {
1640
- $js_array['msg']['deletePostsWarning'] = __( 'Are you sure you want to delete all the posts based on the selected option?', 'bulk-delete' );
1641
- $js_array['msg']['selectPostOption'] = __( 'Please select posts from at least one option', 'bulk-delete' );
1642
-
1643
- $js_array['validators']['delete_posts_by_url'] = 'validateUrl';
1644
- $js_array['error_msg']['delete_posts_by_url'] = 'enterUrl';
1645
- $js_array['msg']['enterUrl'] = __( 'Please enter at least one post url', 'bulk-delete' );
1646
-
1647
- $js_array['dt_iterators'][] = '_cats';
1648
- $js_array['dt_iterators'][] = '_tags';
1649
- $js_array['dt_iterators'][] = '_taxs';
1650
- $js_array['dt_iterators'][] = '_types';
1651
- $js_array['dt_iterators'][] = '_post_status';
1652
- return $js_array;
1653
- }
1654
-
1655
- /**
1656
- * Process delete cron job request.
1657
- * This should ideally go in a separate class. But I was
1658
- * lazy to create a separate class for a single function
1659
- *
1660
- * @since 5.0
1661
- * @static
1662
- */
1663
- public static function do_delete_cron() {
1664
- if ( check_admin_referer( 'sm-bulk-delete-cron', 'sm-bulk-delete-cron-nonce' ) ) {
1665
- $cron_id = absint($_GET['cron_id']);
1666
- $cron_items = Bulk_Delete_Util::get_cron_schedules();
1667
- wp_unschedule_event($cron_items[$cron_id]['timestamp'], $cron_items[$cron_id]['type'], $cron_items[$cron_id]['args']);
1668
-
1669
- $msg = __('The selected scheduled job was successfully deleted ', 'bulk-delete');
1670
-
1671
- add_settings_error(
1672
- Bulk_Delete::CRON_PAGE_SLUG,
1673
- 'deleted-cron',
1674
- $msg,
1675
- 'updated'
1676
- );
1677
- }
1678
- }
1679
- }
1680
-
1681
- // hooks
1682
- add_action( 'bd_delete_posts_by_status' , array( 'Bulk_Delete_Posts' , 'do_delete_posts_by_status' ) );
1683
- add_action( 'bd_delete_posts_by_category' , array( 'Bulk_Delete_Posts' , 'do_delete_posts_by_category' ) );
1684
- add_action( 'bd_delete_posts_by_tag' , array( 'Bulk_Delete_Posts' , 'do_delete_posts_by_tag' ) );
1685
- add_action( 'bd_delete_posts_by_taxonomy' , array( 'Bulk_Delete_Posts' , 'do_delete_posts_by_taxonomy' ) );
1686
- add_action( 'bd_delete_posts_by_post_type' , array( 'Bulk_Delete_Posts' , 'do_delete_posts_by_post_type' ) );
1687
- add_action( 'bd_delete_posts_by_url' , array( 'Bulk_Delete_Posts' , 'do_delete_posts_by_url' ) );
1688
- add_action( 'bd_delete_posts_by_revision' , array( 'Bulk_Delete_Posts' , 'do_delete_posts_by_revision' ) );
1689
-
1690
- add_action( 'bd_delete_cron' , array( 'Bulk_Delete_Posts' , 'do_delete_cron' ) );
1691
- add_filter( 'bd_javascript_array' , array( 'Bulk_Delete_Posts' , 'filter_js_array' ) );
1692
- ?>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
include/class-bulk-delete-users.php DELETED
@@ -1,248 +0,0 @@
1
- <?php
2
- /**
3
- * Utility class for deleting users
4
- *
5
- * @package Bulk_Delete
6
- * @subpackage Users
7
- * @author Sudar
8
- */
9
- class Bulk_Delete_Users {
10
-
11
- /**
12
- * Render delete users box
13
- */
14
- public static function render_delete_users_by_role_box() {
15
-
16
- if ( Bulk_Delete_Util::is_users_box_hidden( Bulk_Delete::BOX_USERS ) ) {
17
- printf( __( 'This section just got enabled. Kindly <a href = "%1$s">refresh</a> the page to fully enable it.', 'bulk-delete' ), 'admin.php?page=' . Bulk_Delete::USERS_PAGE_SLUG );
18
- return;
19
- }
20
- ?>
21
- <!-- Users Start-->
22
- <h4><?php _e( 'Select the user roles from which you want to delete users', 'bulk-delete' ); ?></h4>
23
-
24
- <fieldset class="options">
25
- <table class="optiontable">
26
- <?php
27
- $users_count = count_users();
28
- foreach( $users_count['avail_roles'] as $role => $count ) {
29
- ?>
30
- <tr>
31
- <td scope="row" >
32
- <input name="smbdu_roles[]" value = "<?php echo $role; ?>" type = "checkbox">
33
- <label for="smbdu_roles"><?php echo $role; ?> (<?php echo $count . " "; _e( 'Users', 'bulk-delete' ); ?>)</label>
34
- </td>
35
- </tr>
36
- <?php
37
- }
38
- ?>
39
- <tr>
40
- <td scope="row">
41
- <h4><?php _e( 'Choose your filtering options', 'bulk-delete' ); ?></h4>
42
- </td>
43
- </tr>
44
-
45
- <?php
46
- if ( !Bulk_Delete_Util::is_simple_login_log_present() ) {
47
- $disabled = "disabled";
48
- } else {
49
- $disabled = '';
50
- }
51
- ?>
52
- <tr>
53
- <td scope="row">
54
- <input name="smbdu_login_restrict" id="smbdu_login_restrict" value = "true" type = "checkbox" <?php echo $disabled; ?>>
55
- <?php _e( 'Only restrict to users who have not logged in the last ', 'bulk-delete' );?>
56
- <input type ="textbox" name="smbdu_login_days" id="smbdu_login_days" value ="0" maxlength="4" size="4" <?php echo $disabled; ?> ><?php _e( 'days', 'bulk-delete' );?>
57
- <?php
58
- if ( !Bulk_Delete_Util::is_simple_login_log_present() ) {
59
- ?>
60
- <span style = "color:red">
61
- <?php _e( 'Need Simple Login Log Plugin', 'bulk-delete' ); ?> <a href = "http://wordpress.org/plugins/simple-login-log/">Install now</a>
62
- </span>
63
- <?php
64
- }
65
- ?>
66
- </td>
67
- </tr>
68
-
69
- <tr>
70
- <td scope="row">
71
- <input name="smbdu_role_no_posts" id="smbdu_role_no_posts" value = "true" type = "checkbox">
72
- <?php _e( "Only if user doesn't have any post. Only posts from 'post' post type would be considered.", 'bulk-delete' ); ?>
73
- </td>
74
- </tr>
75
-
76
- <tr>
77
- <td scope="row">
78
- <input name="smbdu_userrole_limit" id="smbdu_userrole_limit" value = "true" type = "checkbox">
79
- <?php _e( 'Only delete first ', 'bulk-delete' );?>
80
- <input type="textbox" name="smbdu_userrole_limit_to" id="smbdu_userrole_limit_to" disabled value ="0" maxlength="4" size="4">
81
- <?php _e( 'users.', 'bulk-delete' );?>
82
- <?php _e( 'Use this option if there are more than 1000 users or the script timesout.', 'bulk-delete' ) ?>
83
- </td>
84
- </tr>
85
-
86
- <tr>
87
- <td scope="row">
88
- <input name="smbdu_userrole_cron" value = "false" type = "radio" checked="checked"> <?php _e( 'Delete now', 'bulk-delete' ); ?>
89
- <input name="smbdu_userrole_cron" value = "true" type = "radio" id = "smbdu_userrole_cron" disabled > <?php _e( 'Schedule', 'bulk-delete' ); ?>
90
- <input name="smbdu_userrole_cron_start" id = "smbdu_userrole_cron_start" value = "now" type = "text" disabled><?php _e( 'repeat ', 'bulk-delete' );?>
91
- <select name = "smbdu_userrole_cron_freq" id = "smbdu_userrole_cron_freq" disabled>
92
- <option value = "-1"><?php _e( "Don't repeat", 'bulk-delete' ); ?></option>
93
- <?php
94
- $schedules = wp_get_schedules();
95
- foreach($schedules as $key => $value) {
96
- ?>
97
- <option value = "<?php echo $key; ?>"><?php echo $value['display']; ?></option>
98
- <?php
99
- }
100
- ?>
101
- </select>
102
- <span class = "bdu-users-by-role-pro" style = "color:red"><?php _e( 'Only available in Pro Addon', 'bulk-delete' ); ?> <a href = "http://bulkwp.com/addons/scheduler-for-deleting-users-by-role/?utm_source=wpadmin&utm_campaign=BulkDelete&utm_medium=buynow&utm_content=bd-u-ur">Buy now</a></span>
103
- </td>
104
- </tr>
105
-
106
- <tr>
107
- <td scope="row">
108
- <?php _e( 'Enter time in Y-m-d H:i:s format or enter now to use current time', 'bulk-delete' );?>
109
- </td>
110
- </tr>
111
-
112
- </table>
113
- </fieldset>
114
-
115
- <p>
116
- <button type="submit" name="bd_action" value = "delete_users_by_role" class="button-primary"><?php _e( 'Bulk Delete ', 'bulk-delete' ) ?>&raquo;</button>
117
- </p>
118
- <!-- Users end-->
119
- <?php
120
- }
121
-
122
- /**
123
- * Process the request for deleting users by role
124
- *
125
- * @static
126
- * @since 5.0
127
- */
128
- public static function do_delete_users_by_role() {
129
-
130
- $delete_options = array();
131
- $delete_options['selected_roles'] = array_get( $_POST, 'smbdu_roles' );
132
- $delete_options['no_posts'] = array_get( $_POST, 'smbdu_role_no_posts', FALSE );
133
-
134
- $delete_options['login_restrict'] = array_get( $_POST, 'smbdu_login_restrict', FALSE );
135
- $delete_options['login_days'] = array_get( $_POST, 'smbdu_login_days' );
136
- $delete_options['limit_to'] = absint( array_get( $_POST, 'smbdu_userrole_limit_to', 0 ) );
137
-
138
- if (array_get( $_POST, 'smbdu_userrole_cron', 'false' ) == 'true' ) {
139
- $freq = $_POST['smbdu_userrole_cron_freq'];
140
- $time = strtotime( $_POST['smbdu_userrole_cron_start'] ) - ( get_option( 'gmt_offset' ) * 60 * 60 );
141
-
142
- if ( $freq == -1 ) {
143
- wp_schedule_single_event( $time, Bulk_Delete::CRON_HOOK_USER_ROLE, array( $delete_options ) );
144
- } else {
145
- wp_schedule_event( $time, $freq , Bulk_Delete::CRON_HOOK_USER_ROLE, array( $delete_options ) );
146
- }
147
-
148
- $msg = __( 'Users from the selected userrole are scheduled for deletion.', 'bulk-delete' ) . ' ' .
149
- sprintf( __( 'See the full list of <a href = "%s">scheduled tasks</a>' , 'bulk-delete' ), get_bloginfo( "wpurl" ) . '/wp-admin/admin.php?page=' . Bulk_Delete::CRON_PAGE_SLUG );
150
- } else {
151
- $deleted_count = self::delete_users_by_role( $delete_options );
152
- $msg = sprintf( _n('Deleted %d user from the selected roles', 'Deleted %d users from the selected role' , $deleted_count, 'bulk-delete' ), $deleted_count );
153
- }
154
-
155
- add_settings_error(
156
- Bulk_Delete::USERS_PAGE_SLUG,
157
- 'deleted-users',
158
- $msg,
159
- 'updated'
160
- );
161
- }
162
-
163
- /**
164
- * Delete users by user role
165
- *
166
- * @static
167
- */
168
- public static function delete_users_by_role( $delete_options ) {
169
-
170
- if( !function_exists( 'wp_delete_user' ) ) {
171
- require_once( ABSPATH . 'wp-admin/includes/user.php' );
172
- }
173
-
174
- $count = 0;
175
-
176
- foreach ( $delete_options['selected_roles'] as $role ) {
177
-
178
- $options = array();
179
- $options['role'] = $role;
180
- if ( $delete_options['limit_to'] > 0 ) {
181
- $options['number'] = $limit_to;
182
- }
183
-
184
- $users = get_users( $options );
185
-
186
- foreach ( $users as $user ) {
187
- if ( $delete_options['no_posts'] == TRUE && count_user_posts ( $user->ID ) > 0 ) {
188
- continue;
189
- }
190
-
191
- if ( $delete_options['login_restrict'] == TRUE ) {
192
- $login_days = $delete_options['login_days'];
193
- $last_login = self::get_last_login( $user->ID );
194
-
195
- if ( $last_login != NULL ) {
196
- if ( strtotime( $last_login ) > strtotime( '-' . $login_days . 'days' ) ) {
197
- continue;
198
- }
199
- } else {
200
- continue;
201
- }
202
- }
203
-
204
- wp_delete_user( $user->ID );
205
- $count ++;
206
- }
207
- }
208
-
209
- return $count;
210
- }
211
-
212
- /**
213
- * Filter JS Array and add validation hooks
214
- *
215
- * @since 5.4
216
- * @static
217
- * @param array $js_array JavaScript Array
218
- * @return array Modified JavaScript Array
219
- */
220
- public static function filter_js_array( $js_array ) {
221
- $js_array['dt_iterators'][] = 'u_userrole';
222
-
223
- $js_array['pre_action_msg']['delete_users_by_role'] = 'deleteUsersWarning';
224
- $js_array['msg']['deleteUsersWarning'] = __( 'Are you sure you want to delete all the users from the selected user role?', 'bulk-delete' );
225
-
226
- $js_array['error_msg']['delete_users_by_role'] = 'selectOneUserRole';
227
- $js_array['msg']['selectOneUserRole'] = __( 'Select at least one user role from which users should be deleted', 'bulk-delete' );
228
-
229
- return $js_array;
230
- }
231
-
232
- /**
233
- * Find the last login date/time of a user
234
- *
235
- * @static
236
- * @access private
237
- */
238
- private static function get_last_login( $user_id ) {
239
- global $wpdb;
240
-
241
- return $wpdb->get_var( $wpdb->prepare( "SELECT time FROM {$wpdb->prefix}" . Bulk_Delete_Util::SIMPLE_LOGIN_LOG_TABLE .
242
- " WHERE uid = %d ORDER BY time DESC LIMIT 1", $user_id ) );
243
- }
244
- }
245
-
246
- add_action( 'bd_delete_users_by_role', array( 'Bulk_Delete_Users', 'do_delete_users_by_role' ) );
247
- add_filter( 'bd_javascript_array', array( 'Bulk_Delete_Users' , 'filter_js_array' ) );
248
- ?>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
include/class-bulk-delete-util.php DELETED
@@ -1,232 +0,0 @@
1
- <?php
2
- /**
3
- * Utility class
4
- *
5
- * @package Bulk_Delete
6
- * @subpackage Util
7
- * @author Sudar
8
- */
9
- class Bulk_Delete_Util {
10
-
11
- // simple login log
12
- const SIMPLE_LOGIN_LOG_TABLE = 'simple_login_log';
13
-
14
- // Meta boxes
15
- const VISIBLE_POST_BOXES = 'metaboxhidden_toplevel_page_bulk-delete-posts';
16
- const VISIBLE_PAGE_BOXES = 'metaboxhidden_bulk-delete_page_bulk-delete-pages';
17
- const VISIBLE_USER_BOXES = 'metaboxhidden_bulk-delete_page_bulk-delete-users';
18
-
19
- /**
20
- * Find out if Simple Login Log is installed or not
21
- * http://wordpress.org/plugins/simple-login-log/
22
- *
23
- * @static
24
- * @access public
25
- * @return bool True if plugin is installed, False otherwise
26
- */
27
- public static function is_simple_login_log_present() {
28
- global $wpdb;
29
-
30
- if( $wpdb->get_row( "SHOW TABLES LIKE '{$wpdb->prefix}" . self::SIMPLE_LOGIN_LOG_TABLE . "'" ) ) {
31
- return TRUE;
32
- }
33
-
34
- return FALSE;
35
- }
36
-
37
- /**
38
- * Check whether the meta box in posts page is hidden or not
39
- *
40
- * @static
41
- * @access public
42
- * @param string $box The name of the box
43
- * @return bool True if the box is hidden, False otherwise
44
- */
45
- public static function is_posts_box_hidden( $box ) {
46
- $hidden_boxes = self::get_posts_hidden_boxes();
47
- return ( is_array( $hidden_boxes ) && in_array( $box, $hidden_boxes ) );
48
- }
49
-
50
- /**
51
- * Get the list of hidden boxes in posts page
52
- *
53
- * @static
54
- * @access public
55
- * @return array The list of hidden meta boxes
56
- */
57
- public static function get_posts_hidden_boxes() {
58
- $current_user = wp_get_current_user();
59
- return get_user_meta( $current_user->ID, self::VISIBLE_POST_BOXES, TRUE );
60
- }
61
-
62
- /**
63
- * Check whether the meta box in pages page is hidden or not
64
- *
65
- * @since 5.0
66
- * @static
67
- * @access public
68
- * @param string $box The name of the box to check
69
- * @return bool True if the box is hidden, False otherwise
70
- */
71
- public static function is_pages_box_hidden( $box ) {
72
- $hidden_boxes = self::get_pages_hidden_boxes();
73
- return ( is_array( $hidden_boxes ) && in_array( $box, $hidden_boxes ) );
74
- }
75
-
76
- /**
77
- * Get the list of hidden boxes in posts page
78
- *
79
- * @since 5.0
80
- * @static
81
- * @access public
82
- * @return the array of hidden meta boxes
83
- */
84
- public static function get_pages_hidden_boxes() {
85
- $current_user = wp_get_current_user();
86
- return get_user_meta( $current_user->ID, self::VISIBLE_PAGE_BOXES, TRUE );
87
- }
88
-
89
- /**
90
- * Check whether the meta box in users page is hidden or not
91
- *
92
- * @static
93
- * @access public
94
- * @param string $box The name of the box to check
95
- * @return bool True if the box is hidden, False otherwise
96
- */
97
- public static function is_users_box_hidden( $box ) {
98
- $hidden_boxes = self::get_users_hidden_boxes();
99
- return ( is_array( $hidden_boxes ) && in_array( $box, $hidden_boxes ) );
100
- }
101
-
102
- /**
103
- * Get the list of hidden boxes in users page
104
- *
105
- * @static
106
- * @access public
107
- * @return array The array of hidden meta boxes
108
- */
109
- public static function get_users_hidden_boxes() {
110
- $current_user = wp_get_current_user();
111
- return get_user_meta( $current_user->ID, self::VISIBLE_USER_BOXES, TRUE );
112
- }
113
-
114
- /**
115
- * Get the list of cron schedules
116
- *
117
- * @static
118
- * @access public
119
- * @return array The list of cron schedules
120
- */
121
- public static function get_cron_schedules() {
122
-
123
- $cron_items = array();
124
- $cron = _get_cron_array();
125
- $date_format = _x( 'M j, Y @ G:i', 'Cron table date format', 'bulk-delete' );
126
- $i = 0;
127
-
128
- foreach ( $cron as $timestamp => $cronhooks ) {
129
- foreach ( (array) $cronhooks as $hook => $events ) {
130
- if (substr($hook, 0, 15) == 'do-bulk-delete-') {
131
- $cron_item = array();
132
-
133
- foreach ( (array) $events as $key => $event ) {
134
- $cron_item['timestamp'] = $timestamp;
135
- $cron_item['due'] = date_i18n( $date_format, $timestamp + ( get_option('gmt_offset') * 60 * 60 ) );
136
- $cron_item['schedule'] = $event['schedule'];
137
- $cron_item['type'] = $hook;
138
- $cron_item['args'] = $event['args'];
139
- $cron_item['id'] = $i;
140
- }
141
-
142
- $cron_items[$i] = $cron_item;
143
- $i++;
144
- }
145
- }
146
- }
147
- return $cron_items;
148
- }
149
-
150
- /**
151
- * Generate display name from post type and status
152
- *
153
- * @static
154
- * @access public
155
- */
156
- public static function display_post_type_status( $str ) {
157
- $type_status = self::split_post_type_status( $str );
158
-
159
- $type = $type_status['type'];
160
- $status = $type_status['status'];
161
-
162
- switch ( $status ) {
163
- case 'private':
164
- return $type . ' - Private Posts';
165
- break;
166
- case 'future':
167
- return $type . ' - Scheduled Posts';
168
- break;
169
- case 'draft':
170
- return $type . ' - Draft Posts';
171
- break;
172
- case 'pending':
173
- return $type . ' - Pending Posts';
174
- break;
175
- case 'publish':
176
- return $type . ' - Published Posts';
177
- break;
178
- }
179
- }
180
-
181
- /**
182
- * Split post type and status
183
- *
184
- * @static
185
- * @access public
186
- */
187
- public static function split_post_type_status( $str ) {
188
- $type_status = array();
189
-
190
- $str_arr = explode( '-', $str );
191
-
192
- if ( count( $str_arr ) > 1 ) {
193
- $type_status['status'] = end( $str_arr );
194
- $type_status['type'] = implode( '-', array_slice( $str_arr, 0, -1 ) );
195
- } else {
196
- $type_status['status'] = 'publish';
197
- $type_status['type'] = $str;
198
- }
199
-
200
- return $type_status;
201
- }
202
- }
203
-
204
- /**
205
- * Get a value from an array based on key.
206
- * If key is present returns the value, else returns the default value
207
- *
208
- * @param array $array Array from which value has to be retrieved
209
- * @param string $key Key, whose value to be retrieved
210
- * @param string $default Optional. Default value to be returned, if the key is not found
211
- * @return mixed Value if key is present, else the default value
212
- */
213
- if ( ! function_exists( 'array_get' ) ) {
214
- function array_get( $array, $key, $default = NULL ) {
215
- return isset( $array[ $key ] ) ? $array[ $key ] : $default;
216
- }
217
- }
218
-
219
- /**
220
- * Get a value from an array based on key and convert it into bool.
221
- *
222
- * @param array $array Array from which value has to be retrieved
223
- * @param string $key Key, whose value to be retrieved
224
- * @param string $default Optional. Default value to be returned, if the key is not found
225
- * @return mixed Boolean converted Value if key is present, else the default value
226
- */
227
- if ( ! function_exists( 'array_get_bool' ) ) {
228
- function array_get_bool( $array, $key, $default = NULL ) {
229
- return filter_var( array_get( $array, $key, $default ), FILTER_VALIDATE_BOOLEAN );
230
- }
231
- }
232
- ?>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
include/class-cron-list-table.php DELETED
@@ -1,141 +0,0 @@
1
- <?php
2
- /**
3
- * Table to show cron list
4
- *
5
- * @package Bulk_Delete
6
- * @subpackage Cron
7
- * @author Sudar
8
- */
9
- class Cron_List_Table extends WP_List_Table {
10
-
11
- /**
12
- * Constructor, we override the parent to pass our own arguments
13
- * We usually focus on three parameters: singular and plural labels, as well as whether the class supports AJAX.
14
- */
15
- function __construct() {
16
- parent::__construct( array(
17
- 'singular' => 'cron_list', //Singular label
18
- 'plural' => 'cron_lists', //plural label, also this well be one of the table css class
19
- 'ajax' => false //We won't support Ajax for this table
20
- ) );
21
- }
22
-
23
- /**
24
- * Add extra markup in the toolbars before or after the list
25
- *
26
- * @param string $which Whether the markup should appear after (bottom) or before (top) the list
27
- */
28
- function extra_tablenav( $which ) {
29
- if ( $which == "top" ){
30
- //The code that goes before the table is here
31
- echo '<p>';
32
- _e('This is the list of jobs that are currently scheduled for auto deleting posts in Bulk Delete Plugin.', 'bulk-delete');
33
- echo '</p>';
34
- }
35
- if ( $which == "bottom" ){
36
- //The code that goes after the table is there
37
- echo '<p>&nbsp;</p>';
38
- echo '<p>';
39
- echo '<strong>';
40
- _e('Note: ', 'bulk-delete');
41
- echo '</strong>';
42
- _e('Scheduling auto post or user deletion is available only when you buy pro addons.', 'bulk-delete');
43
- echo '</p>';
44
-
45
- BD_License::display_available_addon_list();
46
- }
47
- }
48
-
49
- /**
50
- * Define the columns that are going to be used in the table
51
- * @return array $columns, the array of columns to use with the table
52
- */
53
- function get_columns() {
54
- return $columns= array(
55
- 'col_cron_due'=>__('Next Due', 'bulk-delete'),
56
- 'col_cron_schedule'=>__('Schedule', 'bulk-delete'),
57
- 'col_cron_type'=>__('Type', 'bulk-delete'),
58
- 'col_cron_options'=>__('Options', 'bulk-delete')
59
- );
60
- }
61
-
62
- /**
63
- * Decide which columns to activate the sorting functionality on
64
- *
65
- * @return array $sortable, the array of columns that can be sorted by the user
66
- */
67
- public function get_sortable_columns() {
68
- return $sortable = array(
69
- 'col_cron_type' => array( 'cron_type', true )
70
- );
71
- }
72
-
73
- /**
74
- * Prepare the table with different parameters, pagination, columns and table elements
75
- */
76
- function prepare_items() {
77
- $cron_items = Bulk_Delete_Util::get_cron_schedules();
78
- $totalitems = count($cron_items);
79
-
80
- //How many to display per page?
81
- $perpage = 50;
82
-
83
- //How many pages do we have in total?
84
- $totalpages = ceil($totalitems/$perpage);
85
-
86
- /* -- Register the pagination -- */
87
- $this->set_pagination_args( array(
88
- "total_items" => $totalitems,
89
- "total_pages" => $totalpages,
90
- "per_page" => $perpage,
91
- ) );
92
- //The pagination links are automatically built according to those parameters
93
-
94
- /* — Register the Columns — */
95
- $columns = $this->get_columns();
96
- $hidden = array();
97
- $sortable = $this->get_sortable_columns();
98
- $this->_column_headers = array($columns, $hidden, $sortable);
99
-
100
- $this->items = $cron_items;
101
- }
102
-
103
- function column_col_cron_due($item) {
104
- //Build row actions
105
- $actions = array(
106
- 'delete' => sprintf( '<a href="?page=%s&bd_action=%s&cron_id=%s&%s=%s">%s</a>',
107
- $_REQUEST['page'],
108
- 'delete_cron',
109
- $item['id'],
110
- 'sm-bulk-delete-cron-nonce',
111
- wp_create_nonce( 'sm-bulk-delete-cron' ),
112
- __( 'Delete', 'bulk-delete' )
113
- ),
114
- );
115
-
116
- //Return the title contents
117
- return sprintf('%1$s <span style="color:silver">(%2$s)</span>%3$s',
118
- /*$1%s*/ $item['due'],
119
- /*$2%s*/ ($item['timestamp'] + get_option('gmt_offset') * 60 * 60 ),
120
- /*$3%s*/ $this->row_actions($actions)
121
- );
122
- }
123
-
124
- function column_col_cron_schedule($item) {
125
- echo $item['schedule'];
126
- }
127
-
128
- function column_col_cron_type($item) {
129
- echo $item['type'];
130
- }
131
-
132
- function column_col_cron_options($item) {
133
- // TODO: Make it pretty
134
- print_r ($item['args']);
135
- }
136
-
137
- function no_items() {
138
- _e('You have not scheduled any bulk delete jobs.', 'bulk-delete');
139
- }
140
- }
141
- ?>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
include/class-license-list-table.php DELETED
@@ -1,165 +0,0 @@
1
- <?php
2
- /**
3
- * Table to show the list of addon licenses
4
- *
5
- * @package Bulk_Delete
6
- * @subpackage Addon
7
- * @author Sudar
8
- * @since 5.0
9
- */
10
- class License_List_Table extends WP_List_Table {
11
-
12
- /**
13
- * Constructor, setup labels
14
- *
15
- * @since 5.0
16
- */
17
- function __construct() {
18
- parent::__construct( array(
19
- 'singular' => 'license_list', // Singular label
20
- 'plural' => 'license_lists', // plural label, also this well be one of the table css class
21
- 'ajax' => false // We won't support Ajax for this table
22
- ) );
23
- }
24
-
25
- /**
26
- * Add extra markup in the toolbars before or after the list
27
- *
28
- * @since 5.0
29
- * @param string $which Whether the markup should be after (bottom) or before (top) the list
30
- * @uses Bulk_Delete_Adddon::display_available_addon_list() Display the list of available addons
31
- */
32
- function extra_tablenav( $which ) {
33
- if ( $which == "top" ) {
34
- echo '<p>';
35
- _e( 'This is the list of addon license that are currently registered with the plugin.', 'bulk-delete' );
36
- echo '</p>';
37
- }
38
- }
39
-
40
- /**
41
- * Define the list of columns that will be used in the table
42
- *
43
- * @since 5.0
44
- * @return array $columns The list of columns in the table
45
- */
46
- function get_columns() {
47
- return $columns = array(
48
- 'col_addon_name' => __( 'Addon Name', 'bulk-delete' ),
49
- 'col_license' => __( 'License Code', 'bulk-delete' ),
50
- 'col_license_validity' => __( 'Validity', 'bulk-delete' ),
51
- 'col_expires' => __( 'Expires', 'bulk-delete' )
52
- );
53
- }
54
-
55
- /**
56
- * Defines columns that can be sorted
57
- *
58
- * @since 5.0
59
- * @return array $sortable List of columns that can be sorted
60
- */
61
- public function get_sortable_columns() {
62
- return $sortable = array(
63
- 'col_addon_name' => array( 'addon_name', FALSE )
64
- );
65
- }
66
-
67
- /**
68
- * Prepare the table
69
- *
70
- * @since 5.0
71
- */
72
- function prepare_items() {
73
- $columns = $this->get_columns();
74
- $hidden = array();
75
- $sortable = $this->get_sortable_columns();
76
-
77
- $this->_column_headers = array( $columns, $hidden, $sortable );
78
-
79
- $this->items = BD_License::get_licenses();
80
- }
81
-
82
- /**
83
- * Display the col_addon_name column
84
- *
85
- * @since 5.0
86
- * @param array $item Single row of data
87
- */
88
- function column_col_addon_name( $item ) {
89
- $validity = $item['validity'];
90
- $action_label = __( 'Delete', 'bulk-delete' );
91
- $action_name = 'delete_license';
92
-
93
- if ( 'valid' == $validity ) {
94
- $action_label = __( 'Deactivate', 'bulk-delete' );
95
- $action_name = 'deactivate_license';
96
- }
97
-
98
- // Build row actions
99
- $actions = array(
100
- 'deactivate' => sprintf( '<a href="?page=%s&bd_action=%s&addon-code=%s&%s=%s">%s</a>',
101
- $_REQUEST['page'],
102
- $action_name,
103
- $item['addon-code'],
104
- 'bd-deactivate-license-nonce',
105
- wp_create_nonce( 'bd-deactivate-license' ),
106
- $action_label
107
- ),
108
- );
109
-
110
- // Return the title contents
111
- return sprintf('%1$s%2$s',
112
- /*$1%s*/ $item['addon-name'],
113
- /*$2%s*/ $this->row_actions( $actions )
114
- );
115
- }
116
-
117
- /**
118
- * Display the col_license column
119
- *
120
- * @since 5.0
121
- * @param array $item Single row of data
122
- */
123
- function column_col_license( $item ) {
124
- return $item['license'];
125
- }
126
-
127
- /**
128
- * Display the col_license_validity column
129
- *
130
- * @since 5.0
131
- * @param array $item Single row of data
132
- */
133
- function column_col_license_validity( $item ) {
134
- $validity = $item['validity'];
135
- if ( 'valid' == $validity ) {
136
- return '<span style="color:green;">' . $validity . '</span>';
137
- } else {
138
- return '<span style="color:red;">' . $validity . '</span>';
139
- }
140
- }
141
-
142
- /**
143
- * Display the col_expires column
144
- *
145
- * @since 5.0
146
- * @param array $item Single row of data
147
- */
148
- function column_col_expires( $item ) {
149
- if ( key_exists( 'expires', $item ) ) {
150
- return $item['expires'];
151
- } else {
152
- return __( 'N/A', 'bulk-delete' );
153
- }
154
- }
155
-
156
- /**
157
- * Define the message that will be shown when the table is empty
158
- *
159
- * @since 5.0
160
- */
161
- function no_items() {
162
- _e( "You don't have any valid addon license yet.", 'bulk-delete' );
163
- }
164
- }
165
- ?>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
include/compatibility/simple-login-log.php ADDED
@@ -0,0 +1,40 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Code to enable compatibility with other plugins.
4
+ *
5
+ * @since 5.5
6
+ * @author Sudar
7
+ * @package BulkDelete\Util\Compatibility
8
+ */
9
+
10
+ defined( 'ABSPATH' ) || exit; // Exit if accessed directly
11
+
12
+ /**
13
+ * Find out if Simple Login Log is installed or not.
14
+ * http://wordpress.org/plugins/simple-login-log/
15
+ *
16
+ * @since 5.5
17
+ * @return bool True if plugin is installed, False otherwise
18
+ */
19
+ function bd_is_simple_login_log_present() {
20
+ global $wpdb;
21
+ $simple_login_log_table = 'simple_login_log';
22
+
23
+ return (bool) $wpdb->get_row( "SHOW TABLES LIKE '{$wpdb->prefix}{$simple_login_log_table}'" );
24
+ }
25
+
26
+ /**
27
+ * Find the last login date/time of a user.
28
+ *
29
+ * @since 5.5
30
+ * @param int $user_id
31
+ * @return string
32
+ */
33
+ function bd_get_last_login( $user_id ) {
34
+ global $wpdb;
35
+
36
+ $simple_login_log_table = 'simple_login_log';
37
+
38
+ return $wpdb->get_var( $wpdb->prepare( "SELECT time FROM {$wpdb->prefix}{$simple_login_log_table} WHERE uid = %d ORDER BY time DESC LIMIT 1", $user_id ) );
39
+ }
40
+ ?>
include/cron/class-cron-list-table.php ADDED
@@ -0,0 +1,161 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Table to show cron list
4
+ *
5
+ * @author Sudar
6
+ * @package BulkDelete\Cron
7
+ */
8
+
9
+ defined( 'ABSPATH' ) || exit; // Exit if accessed directly
10
+
11
+ class Cron_List_Table extends WP_List_Table {
12
+
13
+ /**
14
+ * Constructor, we override the parent to pass our own arguments
15
+ * We usually focus on three parameters: singular and plural labels, as well as whether the class supports AJAX.
16
+ */
17
+ public function __construct() {
18
+ parent::__construct( array(
19
+ 'singular' => 'cron_list', //Singular label
20
+ 'plural' => 'cron_lists', //plural label, also this well be one of the table css class
21
+ 'ajax' => false //We won't support Ajax for this table
22
+ ) );
23
+ }
24
+
25
+ /**
26
+ * Add extra markup in the toolbars before or after the list
27
+ *
28
+ * @param string $which Whether the markup should appear after (bottom) or before (top) the list
29
+ */
30
+ public function extra_tablenav( $which ) {
31
+ if ( 'top' == $which ) {
32
+ //The code that goes before the table is here
33
+ echo '<p>';
34
+ _e( 'This is the list of jobs that are currently scheduled for auto deleting posts in Bulk Delete Plugin.', 'bulk-delete' );
35
+ echo ' <strong>';
36
+ _e( 'Note: ', 'bulk-delete' );
37
+ echo '</strong>';
38
+ _e( 'Scheduling auto post or user deletion is available only when you buy pro addons.', 'bulk-delete' );
39
+ echo '</p>';
40
+ }
41
+ }
42
+
43
+ /**
44
+ * Define the columns that are going to be used in the table.
45
+ *
46
+ * @return array Array of columns to use with the table
47
+ */
48
+ public function get_columns() {
49
+ return array(
50
+ 'col_cron_due' => __( 'Next Due', 'bulk-delete' ),
51
+ 'col_cron_schedule' => __( 'Schedule', 'bulk-delete' ),
52
+ 'col_cron_type' => __( 'Type', 'bulk-delete' ),
53
+ 'col_cron_options' => __( 'Options', 'bulk-delete' ),
54
+ );
55
+ }
56
+
57
+ /**
58
+ * Decide which columns to activate the sorting functionality on.
59
+ *
60
+ * @return array Array of columns that can be sorted by the user
61
+ */
62
+ public function get_sortable_columns() {
63
+ return array(
64
+ 'col_cron_type' => array( 'cron_type', true )
65
+ );
66
+ }
67
+
68
+ /**
69
+ * Prepare the table with different parameters, pagination, columns and table elements
70
+ */
71
+ public function prepare_items() {
72
+ $cron_items = BD_Util::get_cron_schedules();
73
+ $totalitems = count( $cron_items );
74
+
75
+ //How many to display per page?
76
+ $perpage = 50;
77
+
78
+ //How many pages do we have in total?
79
+ $totalpages = ceil( $totalitems/$perpage );
80
+
81
+ /* -- Register the pagination -- */
82
+ $this->set_pagination_args( array(
83
+ 'total_items' => $totalitems,
84
+ 'total_pages' => $totalpages,
85
+ 'per_page' => $perpage,
86
+ ) );
87
+
88
+ //The pagination links are automatically built according to those parameters
89
+
90
+ /* — Register the Columns — */
91
+ $columns = $this->get_columns();
92
+ $hidden = array();
93
+ $sortable = $this->get_sortable_columns();
94
+ $this->_column_headers = array( $columns, $hidden, $sortable );
95
+
96
+ $this->items = $cron_items;
97
+ }
98
+
99
+ /**
100
+ * Display cron due date column.
101
+ *
102
+ * @param array $item
103
+ * @return string
104
+ */
105
+ public function column_col_cron_due( $item ) {
106
+ //Build row actions
107
+ $actions = array(
108
+ 'delete' => sprintf( '<a href="?page=%s&bd_action=%s&cron_id=%s&%s=%s">%s</a>',
109
+ $_REQUEST['page'],
110
+ 'delete_cron',
111
+ $item['id'],
112
+ 'sm-bulk-delete-cron-nonce',
113
+ wp_create_nonce( 'sm-bulk-delete-cron' ),
114
+ __( 'Delete', 'bulk-delete' )
115
+ ),
116
+ );
117
+
118
+ //Return the title contents
119
+ return sprintf( '%1$s <span style="color:silver">(%2$s)</span>%3$s',
120
+ /*$1%s*/ $item['due'],
121
+ /*$2%s*/ ( $item['timestamp'] + get_option( 'gmt_offset' ) * 60 * 60 ),
122
+ /*$3%s*/ $this->row_actions( $actions )
123
+ );
124
+ }
125
+
126
+ /**
127
+ * Display cron schedule column.
128
+ *
129
+ * @param array $item
130
+ */
131
+ public function column_col_cron_schedule( $item ) {
132
+ echo $item['schedule'];
133
+ }
134
+
135
+ /**
136
+ * Display cron type column.
137
+ *
138
+ * @param array $item
139
+ */
140
+ public function column_col_cron_type( $item ) {
141
+ echo $item['type'];
142
+ }
143
+
144
+ /**
145
+ * Display cron options column.
146
+ *
147
+ * @param array $item
148
+ */
149
+ public function column_col_cron_options( $item ) {
150
+ // TODO: Make it pretty
151
+ print_r( $item['args'] );
152
+ }
153
+
154
+ /**
155
+ *
156
+ */
157
+ public function no_items() {
158
+ _e( 'You have not scheduled any bulk delete jobs.', 'bulk-delete' );
159
+ }
160
+ }
161
+ ?>
include/deprecated/class-bulk-delete-users.php ADDED
@@ -0,0 +1,24 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Deprecated Class.
4
+ * It is still hear for compatibility reasons and most probably will be removed in v6.0.
5
+ *
6
+ * @author Sudar
7
+ * @package BulkDelete\Deprecated
8
+ */
9
+
10
+ defined( 'ABSPATH' ) || exit; // Exit if accessed directly
11
+
12
+ class Bulk_Delete_Users {
13
+
14
+ /**
15
+ * Wire up proper class for backward compatibility.
16
+ *
17
+ * @since 5.5
18
+ */
19
+ public static function delete_users_by_role( $delete_options ) {
20
+ $factory = Bulk_Delete_Users_By_User_Role::factory();
21
+ return $factory->delete( $delete_options );
22
+ }
23
+ }
24
+ ?>
include/deprecated/deprecated.php ADDED
@@ -0,0 +1,62 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Deprecated and backward compatibility code.
4
+ * Don't depend on the code in this file. It would be removed in future versions of the plugin.
5
+ *
6
+ * @author Sudar
7
+ * @package BulkDelete\Util\Deprecated
8
+ * @since 5.5
9
+ */
10
+
11
+ defined( 'ABSPATH' ) || exit; // Exit if accessed directly
12
+
13
+ /**
14
+ * Backward compatibility for delete options.
15
+ *
16
+ * @since 5.5
17
+ * @param array $options Old options.
18
+ * @return array New options.
19
+ */
20
+ function bd_delete_options_compatibility( $options ) {
21
+ // Convert bool keys to boolean
22
+ $bool_keys = array( 'restrict', 'force_delete', 'private' );
23
+ foreach ( $bool_keys as $key ) {
24
+ if ( array_key_exists( $key, $options ) ) {
25
+ $options[ $key ] = bd_to_bool( $options[ $key ] );
26
+ }
27
+ }
28
+
29
+ // convert old date comparison operators
30
+ if ( array_key_exists( 'date_op', $options ) && array_key_exists( 'days', $options ) ) {
31
+ if ( '<' == $options['date_op'] ) {
32
+ $options['date_op'] = 'before';
33
+ } else if ( '>' == $options['date_op'] ) {
34
+ $options['date_op'] = 'after';
35
+ }
36
+ }
37
+
38
+ return $options;
39
+ }
40
+ add_filter( 'bd_delete_options', 'bd_delete_options_compatibility' );
41
+
42
+ /**
43
+ * Enable cron for old pro addons that required separate JavaScript.
44
+ * This will be removed in v6.0
45
+ *
46
+ * @since 5.5
47
+ * @param array $js_array JavaScript Array
48
+ * @return array Modified JavaScript Array
49
+ */
50
+ function bd_enable_cron_for_old_addons( $js_array ) {
51
+ if ( ! function_exists( 'is_plugin_active' ) ) {
52
+ require_once( ABSPATH . 'wp-admin/includes/plugin.php' );
53
+ }
54
+
55
+ if ( is_plugin_active( 'bulk-delete-scheduler-for-deleting-users-by-role/bulk-delete-scheduler-for-deleting-users-by-role.php' ) ) {
56
+ $js_array['pro_iterators'][] = 'u_role';
57
+ }
58
+
59
+ return $js_array;
60
+ }
61
+ add_filter( 'bd_javascript_array', 'bd_enable_cron_for_old_addons' );
62
+ ?>
include/libraries/EDD_SL_Plugin_Updater.php CHANGED
@@ -3,174 +3,336 @@
3
  // uncomment this line for testing
4
  //set_site_transient( 'update_plugins', null );
5
 
 
 
 
6
  /**
7
  * Allows plugins to use their own update API.
8
  *
9
  * @author Pippin Williamson
10
- * @version 1.2
11
  */
12
  class EDD_SL_Plugin_Updater {
13
- private $api_url = '';
14
- private $api_data = array();
15
- private $name = '';
16
- private $slug = '';
17
- private $do_check = false;
18
-
19
- /**
20
- * Class constructor.
21
- *
22
- * @uses plugin_basename()
23
- * @uses hook()
24
- *
25
- * @param string $_api_url The URL pointing to the custom API endpoint.
26
- * @param string $_plugin_file Path to the plugin file.
27
- * @param array $_api_data Optional data to send with API calls.
28
- * @return void
29
- */
30
- function __construct( $_api_url, $_plugin_file, $_api_data = null ) {
31
- $this->api_url = trailingslashit( $_api_url );
32
- $this->api_data = rawurlencode_deep( $_api_data );
33
- $this->name = plugin_basename( $_plugin_file );
34
- $this->slug = basename( $_plugin_file, '.php');
35
- $this->version = $_api_data['version'];
36
-
37
- // Set up hooks.
38
- $this->hook();
39
- }
40
-
41
- /**
42
- * Set up WordPress filters to hook into WP's update process.
43
- *
44
- * @uses add_filter()
45
- *
46
- * @return void
47
- */
48
- private function hook() {
49
- add_filter( 'pre_set_site_transient_update_plugins', array( $this, 'pre_set_site_transient_update_plugins_filter' ) );
50
- add_filter( 'plugins_api', array( $this, 'plugins_api_filter' ), 10, 3 );
51
- add_filter( 'http_request_args', array( $this, 'http_request_args' ), 10, 2 );
52
- }
53
-
54
- /**
55
- * Check for Updates at the defined API endpoint and modify the update array.
56
- *
57
- * This function dives into the update API just when WordPress creates its update array,
58
- * then adds a custom API call and injects the custom plugin data retrieved from the API.
59
- * It is reassembled from parts of the native WordPress plugin update code.
60
- * See wp-includes/update.php line 121 for the original wp_update_plugins() function.
61
- *
62
- * @uses api_request()
63
- *
64
- * @param array $_transient_data Update array build by WordPress.
65
- * @return array Modified update array with custom plugin data.
66
- */
67
- function pre_set_site_transient_update_plugins_filter( $_transient_data ) {
68
-
69
- if( empty( $_transient_data ) || ! $this->do_check ) {
70
-
71
- // This ensures that the custom API request only runs on the second time that WP fires the update check
72
- $this->do_check = true;
73
-
74
- return $_transient_data;
75
- }
76
-
77
- $to_send = array( 'slug' => $this->slug );
78
-
79
- $api_response = $this->api_request( 'plugin_latest_version', $to_send );
80
-
81
- if( false !== $api_response && is_object( $api_response ) && isset( $api_response->new_version ) ) {
82
-
83
- if( version_compare( $this->version, $api_response->new_version, '<' ) ) {
84
- $_transient_data->response[$this->name] = $api_response;
85
- }
86
- }
87
- return $_transient_data;
88
- }
89
-
90
-
91
- /**
92
- * Updates information on the "View version x.x details" page with custom data.
93
- *
94
- * @uses api_request()
95
- *
96
- * @param mixed $_data
97
- * @param string $_action
98
- * @param object $_args
99
- * @return object $_data
100
- */
101
- function plugins_api_filter( $_data, $_action = '', $_args = null ) {
102
- if ( ( $_action != 'plugin_information' ) || !isset( $_args->slug ) || ( $_args->slug != $this->slug ) ) return $_data;
103
-
104
- $to_send = array( 'slug' => $this->slug );
105
-
106
- $api_response = $this->api_request( 'plugin_information', $to_send );
107
- if ( false !== $api_response ) $_data = $api_response;
108
-
109
- return $_data;
110
- }
111
-
112
-
113
- /**
114
- * Disable SSL verification in order to prevent download update failures
115
- *
116
- * @param array $args
117
- * @param string $url
118
- * @return object $array
119
- */
120
- function http_request_args( $args, $url ) {
121
- // If it is an https request and we are performing a package download, disable ssl verification
122
- if( strpos( $url, 'https://' ) !== false && strpos( $url, 'edd_action=package_download' ) ) {
123
- $args['sslverify'] = false;
124
- }
125
- return $args;
126
- }
127
-
128
- /**
129
- * Calls the API and, if successfull, returns the object delivered by the API.
130
- *
131
- * @uses get_bloginfo()
132
- * @uses wp_remote_post()
133
- * @uses is_wp_error()
134
- *
135
- * @param string $_action The requested action.
136
- * @param array $_data Parameters for the API action.
137
- * @return false||object
138
- */
139
- private function api_request( $_action, $_data ) {
140
-
141
- global $wp_version;
142
-
143
- $data = array_merge( $this->api_data, $_data );
144
-
145
- if( $data['slug'] != $this->slug )
146
- return;
147
-
148
- if( empty( $data['license'] ) )
149
- return;
150
-
151
- $api_params = array(
152
- 'edd_action' => 'get_version',
153
- 'license' => $data['license'],
154
- 'name' => $data['item_name'],
155
- 'slug' => $this->slug,
156
- 'author' => $data['author'],
157
- 'url' => home_url()
158
- );
159
- $request = wp_remote_post( $this->api_url, array( 'timeout' => 15, 'sslverify' => false, 'body' => $api_params ) );
160
-
161
- if ( ! is_wp_error( $request ) ):
162
- $request = json_decode( wp_remote_retrieve_body( $request ) );
163
- if( $request && isset( $request->sections ) )
164
- $request->sections = maybe_unserialize( $request->sections );
165
-
166
- if ( $request && isset( $request->license_check ) && 'site_inactive' == $request->license_check ) {
167
- // if the license is not valid anymore
168
- do_action( 'bd_validate_license', urldecode( $data['addon_code'] ), urldecode( $data['item_name'] ) );
169
  }
170
 
171
- return $request;
172
- else:
173
- return false;
174
- endif;
175
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
176
  }
3
  // uncomment this line for testing
4
  //set_site_transient( 'update_plugins', null );
5
 
6
+ // Exit if accessed directly
7
+ if ( ! defined( 'ABSPATH' ) ) exit;
8
+
9
  /**
10
  * Allows plugins to use their own update API.
11
  *
12
  * @author Pippin Williamson
13
+ * @version 1.6
14
  */
15
  class EDD_SL_Plugin_Updater {
16
+ private $api_url = '';
17
+ private $api_data = array();
18
+ private $name = '';
19
+ private $slug = '';
20
+ private $version = '';
21
+
22
+ /**
23
+ * Class constructor.
24
+ *
25
+ * @uses plugin_basename()
26
+ * @uses hook()
27
+ *
28
+ * @param string $_api_url The URL pointing to the custom API endpoint.
29
+ * @param string $_plugin_file Path to the plugin file.
30
+ * @param array $_api_data Optional data to send with API calls.
31
+ */
32
+ function __construct( $_api_url, $_plugin_file, $_api_data = null ) {
33
+ $this->api_url = trailingslashit( $_api_url );
34
+ $this->api_data = $_api_data;
35
+ $this->name = plugin_basename( $_plugin_file );
36
+ $this->slug = basename( $_plugin_file, '.php' );
37
+ $this->version = $_api_data['version'];
38
+
39
+ // Set up hooks.
40
+ $this->init();
41
+ add_action( 'admin_init', array( $this, 'show_changelog' ) );
42
+ }
43
+
44
+ /**
45
+ * Set up WordPress filters to hook into WP's update process.
46
+ *
47
+ * @uses add_filter()
48
+ *
49
+ * @return void
50
+ */
51
+ public function init() {
52
+
53
+ add_filter( 'pre_set_site_transient_update_plugins', array( $this, 'check_update' ) );
54
+ add_filter( 'plugins_api', array( $this, 'plugins_api_filter' ), 10, 3 );
55
+
56
+ add_action( 'after_plugin_row_' . $this->name, array( $this, 'show_update_notification' ), 10, 2 );
57
+ }
58
+
59
+ /**
60
+ * Check for Updates at the defined API endpoint and modify the update array.
61
+ *
62
+ * This function dives into the update API just when WordPress creates its update array,
63
+ * then adds a custom API call and injects the custom plugin data retrieved from the API.
64
+ * It is reassembled from parts of the native WordPress plugin update code.
65
+ * See wp-includes/update.php line 121 for the original wp_update_plugins() function.
66
+ *
67
+ * @uses api_request()
68
+ *
69
+ * @param array $_transient_data Update array build by WordPress.
70
+ * @return array Modified update array with custom plugin data.
71
+ */
72
+ function check_update( $_transient_data ) {
73
+
74
+ global $pagenow;
75
+
76
+ if( ! is_object( $_transient_data ) ) {
77
+ $_transient_data = new stdClass;
78
+ }
79
+
80
+ if( 'plugins.php' == $pagenow && is_multisite() ) {
81
+ return $_transient_data;
82
+ }
83
+
84
+ if ( empty( $_transient_data->response ) || empty( $_transient_data->response[ $this->name ] ) ) {
85
+
86
+ $version_info = $this->api_request( 'plugin_latest_version', array( 'slug' => $this->slug ) );
87
+
88
+ if ( false !== $version_info && is_object( $version_info ) && isset( $version_info->new_version ) ) {
89
+
90
+ if( version_compare( $this->version, $version_info->new_version, '<' ) ) {
91
+
92
+ $_transient_data->response[ $this->name ] = $version_info;
93
+
94
+ }
95
+
96
+ $_transient_data->last_checked = time();
97
+ $_transient_data->checked[ $this->name ] = $this->version;
98
+
99
+ }
100
+
101
+ }
102
+
103
+ return $_transient_data;
104
+ }
105
+
106
+ /**
107
+ * show update nofication row -- needed for multisite subsites, because WP won't tell you otherwise!
108
+ *
109
+ * @param string $file
110
+ * @param array $plugin
111
+ */
112
+ public function show_update_notification( $file, $plugin ) {
113
+
114
+ if( ! current_user_can( 'update_plugins' ) ) {
115
+ return;
116
+ }
117
+
118
+ if( ! is_multisite() ) {
119
+ return;
120
+ }
121
+
122
+ if ( $this->name != $file ) {
123
+ return;
124
+ }
125
+
126
+ // Remove our filter on the site transient
127
+ remove_filter( 'pre_set_site_transient_update_plugins', array( $this, 'check_update' ), 10 );
128
+
129
+ $update_cache = get_site_transient( 'update_plugins' );
130
+
131
+ if ( ! is_object( $update_cache ) || empty( $update_cache->response ) || empty( $update_cache->response[ $this->name ] ) ) {
132
+
133
+ $cache_key = md5( 'edd_plugin_' .sanitize_key( $this->name ) . '_version_info' );
134
+ $version_info = get_transient( $cache_key );
135
+
136
+ if( false === $version_info ) {
137
+
138
+ $version_info = $this->api_request( 'plugin_latest_version', array( 'slug' => $this->slug ) );
139
+
140
+ set_transient( $cache_key, $version_info, 3600 );
141
+ }
142
+
143
+
144
+ if( ! is_object( $version_info ) ) {
145
+ return;
146
+ }
147
+
148
+ if( version_compare( $this->version, $version_info->new_version, '<' ) ) {
149
+
150
+ $update_cache->response[ $this->name ] = $version_info;
151
+
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
152
  }
153
 
154
+ $update_cache->last_checked = time();
155
+ $update_cache->checked[ $this->name ] = $this->version;
156
+
157
+ set_site_transient( 'update_plugins', $update_cache );
158
+
159
+ } else {
160
+
161
+ $version_info = $update_cache->response[ $this->name ];
162
+
163
+ }
164
+
165
+ // Restore our filter
166
+ add_filter( 'pre_set_site_transient_update_plugins', array( $this, 'check_update' ) );
167
+
168
+ if ( ! empty( $update_cache->response[ $this->name ] ) && version_compare( $this->version, $version_info->new_version, '<' ) ) {
169
+
170
+ // build a plugin list row, with update notification
171
+ $wp_list_table = _get_list_table( 'WP_Plugins_List_Table' );
172
+ echo '<tr class="plugin-update-tr"><td colspan="' . $wp_list_table->get_column_count() . '" class="plugin-update colspanchange"><div class="update-message">';
173
+
174
+ $changelog_link = self_admin_url( 'index.php?edd_sl_action=view_plugin_changelog&plugin=' . $this->name . '&slug=' . $this->slug . '&TB_iframe=true&width=772&height=911' );
175
+
176
+ if ( empty( $version_info->download_link ) ) {
177
+ printf(
178
+ __( 'There is a new version of %1$s available. <a target="_blank" class="thickbox" href="%2$s">View version %3$s details</a>.', 'edd' ),
179
+ esc_html( $version_info->name ),
180
+ esc_url( $changelog_link ),
181
+ esc_html( $version_info->new_version )
182
+ );
183
+ } else {
184
+ printf(
185
+ __( 'There is a new version of %1$s available. <a target="_blank" class="thickbox" href="%2$s">View version %3$s details</a> or <a href="%4$s">update now</a>.', 'edd' ),
186
+ esc_html( $version_info->name ),
187
+ esc_url( $changelog_link ),
188
+ esc_html( $version_info->new_version ),
189
+ esc_url( wp_nonce_url( self_admin_url( 'update.php?action=upgrade-plugin&plugin=' ) . $this->name, 'upgrade-plugin_' . $this->name ) )
190
+ );
191
+ }
192
+
193
+ echo '</div></td></tr>';
194
+ }
195
+ }
196
+
197
+
198
+ /**
199
+ * Updates information on the "View version x.x details" page with custom data.
200
+ *
201
+ * @uses api_request()
202
+ *
203
+ * @param mixed $_data
204
+ * @param string $_action
205
+ * @param object $_args
206
+ * @return object $_data
207
+ */
208
+ function plugins_api_filter( $_data, $_action = '', $_args = null ) {
209
+
210
+
211
+ if ( $_action != 'plugin_information' ) {
212
+
213
+ return $_data;
214
+
215
+ }
216
+
217
+ if ( ! isset( $_args->slug ) || ( $_args->slug != $this->slug ) ) {
218
+
219
+ return $_data;
220
+
221
+ }
222
+
223
+ $to_send = array(
224
+ 'slug' => $this->slug,
225
+ 'is_ssl' => is_ssl(),
226
+ 'fields' => array(
227
+ 'banners' => false, // These will be supported soon hopefully
228
+ 'reviews' => false
229
+ )
230
+ );
231
+
232
+ $api_response = $this->api_request( 'plugin_information', $to_send );
233
+
234
+ if ( false !== $api_response ) {
235
+ $_data = $api_response;
236
+ }
237
+
238
+ return $_data;
239
+ }
240
+
241
+
242
+ /**
243
+ * Disable SSL verification in order to prevent download update failures
244
+ *
245
+ * @param array $args
246
+ * @param string $url
247
+ * @return object $array
248
+ */
249
+ function http_request_args( $args, $url ) {
250
+ // If it is an https request and we are performing a package download, disable ssl verification
251
+ if ( strpos( $url, 'https://' ) !== false && strpos( $url, 'edd_action=package_download' ) ) {
252
+ $args['sslverify'] = false;
253
+ }
254
+ return $args;
255
+ }
256
+
257
+ /**
258
+ * Calls the API and, if successfull, returns the object delivered by the API.
259
+ *
260
+ * @uses get_bloginfo()
261
+ * @uses wp_remote_post()
262
+ * @uses is_wp_error()
263
+ *
264
+ * @param string $_action The requested action.
265
+ * @param array $_data Parameters for the API action.
266
+ * @return false|object
267
+ */
268
+ private function api_request( $_action, $_data ) {
269
+
270
+ global $wp_version;
271
+
272
+ $data = array_merge( $this->api_data, $_data );
273
+
274
+ if ( $data['slug'] != $this->slug )
275
+ return;
276
+
277
+ if ( empty( $data['license'] ) )
278
+ return;
279
+
280
+ if( $this->api_url == home_url() ) {
281
+ return false; // Don't allow a plugin to ping itself
282
+ }
283
+
284
+ $api_params = array(
285
+ 'edd_action' => 'get_version',
286
+ 'license' => $data['license'],
287
+ 'item_name' => isset( $data['item_name'] ) ? $data['item_name'] : false,
288
+ 'item_id' => isset( $data['item_id'] ) ? $data['item_id'] : false,
289
+ 'slug' => $data['slug'],
290
+ 'author' => $data['author'],
291
+ 'url' => home_url()
292
+ );
293
+
294
+ $request = wp_remote_post( $this->api_url, array( 'timeout' => 15, 'sslverify' => false, 'body' => $api_params ) );
295
+
296
+ if ( ! is_wp_error( $request ) ) {
297
+ $request = json_decode( wp_remote_retrieve_body( $request ) );
298
+ }
299
+
300
+ if ( $request && isset( $request->sections ) ) {
301
+ $request->sections = maybe_unserialize( $request->sections );
302
+ } else {
303
+ $request = false;
304
+ }
305
+
306
+ return $request;
307
+ }
308
+
309
+ public function show_changelog() {
310
+
311
+
312
+ if( empty( $_REQUEST['edd_sl_action'] ) || 'view_plugin_changelog' != $_REQUEST['edd_sl_action'] ) {
313
+ return;
314
+ }
315
+
316
+ if( empty( $_REQUEST['plugin'] ) ) {
317
+ return;
318
+ }
319
+
320
+ if( empty( $_REQUEST['slug'] ) ) {
321
+ return;
322
+ }
323
+
324
+ if( ! current_user_can( 'update_plugins' ) ) {
325
+ wp_die( __( 'You do not have permission to install plugin updates', 'edd' ), __( 'Error', 'edd' ), array( 'response' => 403 ) );
326
+ }
327
+
328
+ $response = $this->api_request( 'plugin_latest_version', array( 'slug' => $_REQUEST['slug'] ) );
329
+
330
+ if( $response && isset( $response->sections['changelog'] ) ) {
331
+ echo '<div style="background:#fff;padding:10px;">' . $response->sections['changelog'] . '</div>';
332
+ }
333
+
334
+
335
+ exit;
336
+ }
337
+
338
  }
include/libraries/browser.php DELETED
@@ -1,1082 +0,0 @@
1
- <?php
2
- /**
3
- * Modified to remove var
4
- * Chris Christoff on 12/26/2012
5
- * Changes: Changes vars to publics
6
- *
7
- * Modified to work for EDD by
8
- * Chris Christoff on 12/23/2012
9
- * Changes: Removed the browser string return and added spacing. Also removed return HTML formatting.
10
- *
11
- * Modified to add formatted User Agent string for EDD System Info by
12
- * Chris Christoff on 12/23/2012
13
- * Changes: Split user string and add formatting so we can print a nicely
14
- * formatted user agent string on the EDD System Info
15
- *
16
- * File: Browser.php
17
- * Author: Chris Schuld (http://chrisschuld.com/)
18
- * Last Modified: August 20th, 2010
19
- * @version 1.9
20
- * @package PegasusPHP
21
- *
22
- * Copyright (C) 2008-2010 Chris Schuld (chris@chrisschuld.com)
23
- *
24
- * This program is free software; you can redistribute it and/or
25
- * modify it under the terms of the GNU General Public License as
26
- * published by the Free Software Foundation; either version 2 of
27
- * the License, or (at your option) any later version.
28
- *
29
- * This program is distributed in the hope that it will be useful,
30
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
31
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
32
- * GNU General Public License for more details at:
33
- * http://www.gnu.org/copyleft/gpl.html
34
- *
35
- *
36
- * Typical Usage:
37
- *
38
- * $browser = new Browser();
39
- * if( $browser->getBrowser() == Browser::BROWSER_FIREFOX && $browser->getVersion() >= 2 ) {
40
- * echo 'You have FireFox version 2 or greater';
41
- * }
42
- *
43
- * User Agents Sampled from: http://www.useragentstring.com/
44
- *
45
- * This implementation is based on the original work from Gary White
46
- * http://apptools.com/phptools/browser/
47
- *
48
- * UPDATES:
49
- *
50
- * 2010-08-20 (v1.9):
51
- * + Added MSN Explorer Browser (legacy)
52
- * + Added Bing/MSN Robot (Thanks Rob MacDonald)
53
- * + Added the Android Platform (PLATFORM_ANDROID)
54
- * + Fixed issue with Android 1.6/2.2 (Thanks Tom Hirashima)
55
- *
56
- * 2010-04-27 (v1.8):
57
- * + Added iPad Support
58
- *
59
- * 2010-03-07 (v1.7):
60
- * + *MAJOR* Rebuild (preg_match and other "slow" routine removal(s))
61
- * + Almost allof Gary's original code has been replaced
62
- * + Large PHPUNIT testing environment created to validate new releases and additions
63
- * + Added FreeBSD Platform
64
- * + Added OpenBSD Platform
65
- * + Added NetBSD Platform
66
- * + Added SunOS Platform
67
- * + Added OpenSolaris Platform
68
- * + Added support of the Iceweazel Browser
69
- * + Added isChromeFrame() call to check if chromeframe is in use
70
- * + Moved the Opera check in front of the Firefox check due to legacy Opera User Agents
71
- * + Added the __toString() method (Thanks Deano)
72
- *
73
- * 2009-11-15:
74
- * + Updated the checkes for Firefox
75
- * + Added the NOKIA platform
76
- * + Added Checks for the NOKIA brower(s)
77
- *
78
- * 2009-11-08:
79
- * + PHP 5.3 Support
80
- * + Added support for BlackBerry OS and BlackBerry browser
81
- * + Added support for the Opera Mini browser
82
- * + Added additional documenation
83
- * + Added support for isRobot() and isMobile()
84
- * + Added support for Opera version 10
85
- * + Added support for deprecated Netscape Navigator version 9
86
- * + Added support for IceCat
87
- * + Added support for Shiretoko
88
- *
89
- * 2010-04-27 (v1.8):
90
- * + Added iPad Support
91
- *
92
- * 2009-08-18:
93
- * + Updated to support PHP 5.3 - removed all deprecated function calls
94
- * + Updated to remove all double quotes (") -- converted to single quotes (')
95
- *
96
- * 2009-04-27:
97
- * + Updated the IE check to remove a typo and bug (thanks John)
98
- *
99
- * 2009-04-22:
100
- * + Added detection for GoogleBot
101
- * + Added detection for the W3C Validator.
102
- * + Added detection for Yahoo! Slurp
103
- *
104
- * 2009-03-14:
105
- * + Added detection for iPods.
106
- * + Added Platform detection for iPhones
107
- * + Added Platform detection for iPods
108
- *
109
- * 2009-02-16: (Rick Hale)
110
- * + Added version detection for Android phones.
111
- *
112
- * 2008-12-09:
113
- * + Removed unused constant
114
- *
115
- * 2008-11-07:
116
- * + Added Google's Chrome to the detection list
117
- * + Added isBrowser(string) to the list of functions special thanks to
118
- * Daniel 'mavrick' Lang for the function concept (http://mavrick.id.au)
119
- *
120
- *
121
- * Gary White noted: "Since browser detection is so unreliable, I am
122
- * no longer maintaining this script. You are free to use and or
123
- * modify/update it as you want, however the author assumes no
124
- * responsibility for the accuracy of the detected values."
125
- *
126
- * Anyone experienced with Gary's script might be interested in these notes:
127
- *
128
- * Added class constants
129
- * Added detection and version detection for Google's Chrome
130
- * Updated the version detection for Amaya
131
- * Updated the version detection for Firefox
132
- * Updated the version detection for Lynx
133
- * Updated the version detection for WebTV
134
- * Updated the version detection for NetPositive
135
- * Updated the version detection for IE
136
- * Updated the version detection for OmniWeb
137
- * Updated the version detection for iCab
138
- * Updated the version detection for Safari
139
- * Updated Safari to remove mobile devices (iPhone)
140
- * Added detection for iPhone
141
- * Added detection for robots
142
- * Added detection for mobile devices
143
- * Added detection for BlackBerry
144
- * Removed Netscape checks (matches heavily with firefox & mozilla)
145
- *
146
- */
147
-
148
- class Browser {
149
- public $_agent = '';
150
- public $_browser_name = '';
151
- public $_version = '';
152
- public $_platform = '';
153
- public $_os = '';
154
- public $_is_aol = false;
155
- public $_is_mobile = false;
156
- public $_is_robot = false;
157
- public $_aol_version = '';
158
-
159
- public $BROWSER_UNKNOWN = 'unknown';
160
- public $VERSION_UNKNOWN = 'unknown';
161
-
162
- public $BROWSER_OPERA = 'Opera'; // Http://www.opera.com/
163
- public $BROWSER_OPERA_MINI = 'Opera Mini'; // Http://www.opera.com/mini/
164
- public $BROWSER_WEBTV = 'WebTV'; // Http://www.webtv.net/pc/
165
- public $BROWSER_IE = 'Internet Explorer'; // Http://www.microsoft.com/ie/
166
- public $BROWSER_POCKET_IE = 'Pocket Internet Explorer'; // Http://en.wikipedia.org/wiki/Internet_Explorer_Mobile
167
- public $BROWSER_KONQUEROR = 'Konqueror'; // Http://www.konqueror.org/
168
- public $BROWSER_ICAB = 'iCab'; // Http://www.icab.de/
169
- public $BROWSER_OMNIWEB = 'OmniWeb'; // Http://www.omnigroup.com/applications/omniweb/
170
- public $BROWSER_FIREBIRD = 'Firebird'; // Http://www.ibphoenix.com/
171
- public $BROWSER_FIREFOX = 'Firefox'; // Http://www.mozilla.com/en-US/firefox/firefox.html
172
- public $BROWSER_ICEWEASEL = 'Iceweasel'; // Http://www.geticeweasel.org/
173
- public $BROWSER_SHIRETOKO = 'Shiretoko'; // Http://wiki.mozilla.org/Projects/shiretoko
174
- public $BROWSER_MOZILLA = 'Mozilla'; // Http://www.mozilla.com/en-US/
175
- public $BROWSER_AMAYA = 'Amaya'; // Http://www.w3.org/Amaya/
176
- public $BROWSER_LYNX = 'Lynx'; // Http://en.wikipedia.org/wiki/Lynx
177
- public $BROWSER_SAFARI = 'Safari'; // Http://apple.com
178
- public $BROWSER_IPHONE = 'iPhone'; // Http://apple.com
179
- public $BROWSER_IPOD = 'iPod'; // Http://apple.com
180
- public $BROWSER_IPAD = 'iPad'; // Http://apple.com
181
- public $BROWSER_CHROME = 'Chrome'; // Http://www.google.com/chrome
182
- public $BROWSER_ANDROID = 'Android'; // Http://www.android.com/
183
- public $BROWSER_GOOGLEBOT = 'GoogleBot'; // Http://en.wikipedia.org/wiki/Googlebot
184
- public $BROWSER_SLURP = 'Yahoo! Slurp'; // Http://en.wikipedia.org/wiki/Yahoo!_Slurp
185
- public $BROWSER_W3CVALIDATOR = 'W3C Validator'; // Http://validator.w3.org/
186
- public $BROWSER_BLACKBERRY = 'BlackBerry'; // Http://www.blackberry.com/
187
- public $BROWSER_ICECAT = 'IceCat'; // Http://en.wikipedia.org/wiki/GNU_IceCat
188
- public $BROWSER_NOKIA_S60 = 'Nokia S60 OSS Browser'; // Http://en.wikipedia.org/wiki/Web_Browser_for_S60
189
- public $BROWSER_NOKIA = 'Nokia Browser'; // * all other WAP-based browsers on the Nokia Platform
190
- public $BROWSER_MSN = 'MSN Browser'; // Http://explorer.msn.com/
191
- public $BROWSER_MSNBOT = 'MSN Bot'; // Http://search.msn.com/msnbot.htm
192
- // Http://en.wikipedia.org/wiki/Msnbot (used for Bing as well)
193
-
194
- public $BROWSER_NETSCAPE_NAVIGATOR = 'Netscape Navigator'; // Http://browser.netscape.com/ (DEPRECATED)
195
- public $BROWSER_GALEON = 'Galeon'; // Http://galeon.sourceforge.net/ (DEPRECATED)
196
- public $BROWSER_NETPOSITIVE = 'NetPositive'; // Http://en.wikipedia.org/wiki/NetPositive (DEPRECATED)
197
- public $BROWSER_PHOENIX = 'Phoenix'; // Http://en.wikipedia.org/wiki/History_of_Mozilla_Firefox (DEPRECATED)
198
-
199
- public $PLATFORM_UNKNOWN = 'unknown';
200
- public $PLATFORM_WINDOWS = 'Windows';
201
- public $PLATFORM_WINDOWS_CE = 'Windows CE';
202
- public $PLATFORM_APPLE = 'Apple';
203
- public $PLATFORM_LINUX = 'Linux';
204
- public $PLATFORM_OS2 = 'OS/2';
205
- public $PLATFORM_BEOS = 'BeOS';
206
- public $PLATFORM_IPHONE = 'iPhone';
207
- public $PLATFORM_IPOD = 'iPod';
208
- public $PLATFORM_IPAD = 'iPad';
209
- public $PLATFORM_BLACKBERRY = 'BlackBerry';
210
- public $PLATFORM_NOKIA = 'Nokia';
211
- public $PLATFORM_FREEBSD = 'FreeBSD';
212
- public $PLATFORM_OPENBSD = 'OpenBSD';
213
- public $PLATFORM_NETBSD = 'NetBSD';
214
- public $PLATFORM_SUNOS = 'SunOS';
215
- public $PLATFORM_OPENSOLARIS = 'OpenSolaris';
216
- public $PLATFORM_ANDROID = 'Android';
217
-
218
- public $OPERATING_SYSTEM_UNKNOWN = 'unknown';
219
-
220
- function Browser($useragent="") {
221
- $this->reset();
222
- if( $useragent != "" ) {
223
- $this->setUserAgent($useragent);
224
- }
225
- else {
226
- $this->determine();
227
- }
228
- }
229
-
230
- /**
231
- * Reset all properties
232
- */
233
- function reset() {
234
- $this->_agent = isset($_SERVER['HTTP_USER_AGENT']) ? $_SERVER['HTTP_USER_AGENT'] : "";
235
- $this->_browser_name = $this->BROWSER_UNKNOWN;
236
- $this->_version = $this->VERSION_UNKNOWN;
237
- $this->_platform = $this->PLATFORM_UNKNOWN;
238
- $this->_os = $this->OPERATING_SYSTEM_UNKNOWN;
239
- $this->_is_aol = false;
240
- $this->_is_mobile = false;
241
- $this->_is_robot = false;
242
- $this->_aol_version = $this->VERSION_UNKNOWN;
243
- }
244
-
245
- /**
246
- * Check to see if the specific browser is valid
247
- * @param string $browserName
248
- * @return True if the browser is the specified browser
249
- */
250
- function isBrowser($browserName) { return( 0 == strcasecmp($this->_browser_name, trim($browserName))); }
251
-
252
- /**
253
- * The name of the browser. All return types are from the class contants
254
- * @return string Name of the browser
255
- */
256
- function getBrowser() { return $this->_browser_name; }
257
- /**
258
- * Set the name of the browser
259
- * @param $browser The name of the Browser
260
- */
261
- function setBrowser($browser) { return $this->_browser_name = $browser; }
262
- /**
263
- * The name of the platform. All return types are from the class contants
264
- * @return string Name of the browser
265
- */
266
- function getPlatform() { return $this->_platform; }
267
- /**
268
- * Set the name of the platform
269
- * @param $platform The name of the Platform
270
- */
271
- function setPlatform($platform) { return $this->_platform = $platform; }
272
- /**
273
- * The version of the browser.
274
- * @return string Version of the browser (will only contain alpha-numeric characters and a period)
275
- */
276
- function getVersion() { return $this->_version; }
277
- /**
278
- * Set the version of the browser
279
- * @param $version The version of the Browser
280
- */
281
- function setVersion($version) { $this->_version = preg_replace('/[^0-9,.,a-z,A-Z-]/','',$version); }
282
- /**
283
- * The version of AOL.
284
- * @return string Version of AOL (will only contain alpha-numeric characters and a period)
285
- */
286
- function getAolVersion() { return $this->_aol_version; }
287
- /**
288
- * Set the version of AOL
289
- * @param $version The version of AOL
290
- */
291
- function setAolVersion($version) { $this->_aol_version = preg_replace('/[^0-9,.,a-z,A-Z]/','',$version); }
292
- /**
293
- * Is the browser from AOL?
294
- * @return boolean True if the browser is from AOL otherwise false
295
- */
296
- function isAol() { return $this->_is_aol; }
297
- /**
298
- * Is the browser from a mobile device?
299
- * @return boolean True if the browser is from a mobile device otherwise false
300
- */
301
- function isMobile() { return $this->_is_mobile; }
302
- /**
303
- * Is the browser from a robot (ex Slurp,GoogleBot)?
304
- * @return boolean True if the browser is from a robot otherwise false
305
- */
306
- function isRobot() { return $this->_is_robot; }
307
- /**
308
- * Set the browser to be from AOL
309
- * @param $isAol
310
- */
311
- function setAol($isAol) { $this->_is_aol = $isAol; }
312
- /**
313
- * Set the Browser to be mobile
314
- * @param boolean $value is the browser a mobile brower or not
315
- */
316
- function setMobile($value=true) { $this->_is_mobile = $value; }
317
- /**
318
- * Set the Browser to be a robot
319
- * @param boolean $value is the browser a robot or not
320
- */
321
- function setRobot($value=true) { $this->_is_robot = $value; }
322
- /**
323
- * Get the user agent value in use to determine the browser
324
- * @return string The user agent from the HTTP header
325
- */
326
- function getUserAgent() { return $this->_agent; }
327
- /**
328
- * Set the user agent value (the construction will use the HTTP header value - this will overwrite it)
329
- * @param $agent_string The value for the User Agent
330
- */
331
- function setUserAgent($agent_string) {
332
- $this->reset();
333
- $this->_agent = $agent_string;
334
- $this->determine();
335
- }
336
- /**
337
- * Used to determine if the browser is actually "chromeframe"
338
- * @since 1.7
339
- * @return boolean True if the browser is using chromeframe
340
- */
341
- function isChromeFrame() {
342
- return( strpos($this->_agent,"chromeframe") !== false );
343
- }
344
- /**
345
- * Returns a formatted string with a summary of the details of the browser.
346
- * @return string formatted string with a summary of the browser
347
- */
348
- function __toString() {
349
- $text1 = $this->getUserAgent(); //grabs the UA (user agent) string
350
- $UAline1 = substr($text1, 0, 32); //the first line we print should only be the first 32 characters of the UA string
351
- $text2 = $this->getUserAgent();//now we grab it again and save it to a string
352
- $towrapUA = str_replace($UAline1, '', $text2);//the rest of the printoff (other than first line) is equivolent
353
- // To the whole string minus the part we printed off. IE
354
- // User Agent: thefirst32charactersfromUAline1
355
- // the rest of it is now stored in
356
- // $text2 to be printed off
357
- // But we need to add spaces before each line that is split other than line 1
358
- $space = '';
359
- for($i = 0; $i < 25; $i++) {
360
- $space .= ' ';
361
- }
362
- // Now we split the remaining string of UA ($text2) into lines that are prefixed by spaces for formatting
363
- $wordwrapped = chunk_split($towrapUA, 32, "\n $space");
364
- return "Platform: {$this->getPlatform()} \n".
365
- "Browser Name: {$this->getBrowser()} \n" .
366
- "Browser Version: {$this->getVersion()} \n" .
367
- "User Agent String: $UAline1 \n\t\t\t " .
368
- "$wordwrapped";
369
- }
370
- /**
371
- * Protected routine to calculate and determine what the browser is in use (including platform)
372
- */
373
- function determine() {
374
- $this->checkPlatform();
375
- $this->checkBrowsers();
376
- $this->checkForAol();
377
- }
378
- /**
379
- * Protected routine to determine the browser type
380
- * @return boolean True if the browser was detected otherwise false
381
- */
382
- function checkBrowsers() {
383
- return (
384
- // Well-known, well-used
385
- // Special Notes:
386
- // (1) Opera must be checked before FireFox due to the odd
387
- // user agents used in some older versions of Opera
388
- // (2) WebTV is strapped onto Internet Explorer so we must
389
- // check for WebTV before IE
390
- // (3) (deprecated) Galeon is based on Firefox and needs to be
391
- // tested before Firefox is tested
392
- // (4) OmniWeb is based on Safari so OmniWeb check must occur
393
- // before Safari
394
- // (5) Netscape 9+ is based on Firefox so Netscape checks
395
- // before FireFox are necessary
396
- $this->checkBrowserWebTv() ||
397
- $this->checkBrowserInternetExplorer() ||
398
- $this->checkBrowserOpera() ||
399
- $this->checkBrowserGaleon() ||
400
- $this->checkBrowserNetscapeNavigator9Plus() ||
401
- $this->checkBrowserFirefox() ||
402
- $this->checkBrowserChrome() ||
403
- $this->checkBrowserOmniWeb() ||
404
-
405
- // Common mobile
406
- $this->checkBrowserAndroid() ||
407
- $this->checkBrowseriPad() ||
408
- $this->checkBrowseriPod() ||
409
- $this->checkBrowseriPhone() ||
410
- $this->checkBrowserBlackBerry() ||
411
- $this->checkBrowserNokia() ||
412
-
413
- // Common bots
414
- $this->checkBrowserGoogleBot() ||
415
- $this->checkBrowserMSNBot() ||
416
- $this->checkBrowserSlurp() ||
417
-
418
- // WebKit base check (post mobile and others)
419
- $this->checkBrowserSafari() ||
420
-
421
- // Everyone else
422
- $this->checkBrowserNetPositive() ||
423
- $this->checkBrowserFirebird() ||
424
- $this->checkBrowserKonqueror() ||
425
- $this->checkBrowserIcab() ||
426
- $this->checkBrowserPhoenix() ||
427
- $this->checkBrowserAmaya() ||
428
- $this->checkBrowserLynx() ||
429
-
430
- $this->checkBrowserShiretoko() ||
431
- $this->checkBrowserIceCat() ||
432
- $this->checkBrowserW3CValidator() ||
433
- $this->checkBrowserMozilla() /* Mozilla is such an open standard that you must check it last */
434
- );
435
- }
436
-
437
- /**
438
- * Determine if the user is using a BlackBerry (last updated 1.7)
439
- * @return boolean True if the browser is the BlackBerry browser otherwise false
440
- */
441
- function checkBrowserBlackBerry() {
442
- if( stripos($this->_agent,'blackberry') !== false ) {
443
- $aresult = explode("/",stristr($this->_agent,"BlackBerry"));
444
- $aversion = explode(' ',$aresult[1]);
445
- $this->setVersion($aversion[0]);
446
- $this->_browser_name = $this->BROWSER_BLACKBERRY;
447
- $this->setMobile(true);
448
- return true;
449
- }
450
- return false;
451
- }
452
-
453
- /**
454
- * Determine if the user is using an AOL User Agent (last updated 1.7)
455
- * @return boolean True if the browser is from AOL otherwise false
456
- */
457
- function checkForAol() {
458
- $this->setAol(false);
459
- $this->setAolVersion($this->VERSION_UNKNOWN);
460
-
461
- if( stripos($this->_agent,'aol') !== false ) {
462
- $aversion = explode(' ',stristr($this->_agent, 'AOL'));
463
- $this->setAol(true);
464
- $this->setAolVersion(preg_replace('/[^0-9\.a-z]/i', '', $aversion[1]));
465
- return true;
466
- }
467
- return false;
468
- }
469
-
470
- /**
471
- * Determine if the browser is the GoogleBot or not (last updated 1.7)
472
- * @return boolean True if the browser is the GoogletBot otherwise false
473
- */
474
- function checkBrowserGoogleBot() {
475
- if( stripos($this->_agent,'googlebot') !== false ) {
476
- $aresult = explode('/',stristr($this->_agent,'googlebot'));
477
- $aversion = explode(' ',$aresult[1]);
478
- $this->setVersion(str_replace(';','',$aversion[0]));
479
- $this->_browser_name = $this->BROWSER_GOOGLEBOT;
480
- $this->setRobot(true);
481
- return true;
482
- }
483
- return false;
484
- }
485
-
486
- /**
487
- * Determine if the browser is the MSNBot or not (last updated 1.9)
488
- * @return boolean True if the browser is the MSNBot otherwise false
489
- */
490
- function checkBrowserMSNBot() {
491
- if( stripos($this->_agent,"msnbot") !== false ) {
492
- $aresult = explode("/",stristr($this->_agent,"msnbot"));
493
- $aversion = explode(" ",$aresult[1]);
494
- $this->setVersion(str_replace(";","",$aversion[0]));
495
- $this->_browser_name = $this->BROWSER_MSNBOT;
496
- $this->setRobot(true);
497
- return true;
498
- }
499
- return false;
500
- }
501
-
502
- /**
503
- * Determine if the browser is the W3C Validator or not (last updated 1.7)
504
- * @return boolean True if the browser is the W3C Validator otherwise false
505
- */
506
- function checkBrowserW3CValidator() {
507
- if( stripos($this->_agent,'W3C-checklink') !== false ) {
508
- $aresult = explode('/',stristr($this->_agent,'W3C-checklink'));
509
- $aversion = explode(' ',$aresult[1]);
510
- $this->setVersion($aversion[0]);
511
- $this->_browser_name = $this->BROWSER_W3CVALIDATOR;
512
- return true;
513
- }
514
- else if( stripos($this->_agent,'W3C_Validator') !== false ) {
515
- // Some of the Validator versions do not delineate w/ a slash - add it back in
516
- $ua = str_replace("W3C_Validator ", "W3C_Validator/", $this->_agent);
517
- $aresult = explode('/',stristr($ua,'W3C_Validator'));
518
- $aversion = explode(' ',$aresult[1]);
519
- $this->setVersion($aversion[0]);
520
- $this->_browser_name = $this->BROWSER_W3CVALIDATOR;
521
- return true;
522
- }
523
- return false;
524
- }
525
-
526
- /**
527
- * Determine if the browser is the Yahoo! Slurp Robot or not (last updated 1.7)
528
- * @return boolean True if the browser is the Yahoo! Slurp Robot otherwise false
529
- */
530
- function checkBrowserSlurp() {
531
- if( stripos($this->_agent,'slurp') !== false ) {
532
- $aresult = explode('/',stristr($this->_agent,'Slurp'));
533
- $aversion = explode(' ',$aresult[1]);
534
- $this->setVersion($aversion[0]);
535
- $this->_browser_name = $this->BROWSER_SLURP;
536
- $this->setRobot(true);
537
- $this->setMobile(false);
538
- return true;
539
- }
540
- return false;
541
- }
542
-
543
- /**
544
- * Determine if the browser is Internet Explorer or not (last updated 1.7)
545
- * @return boolean True if the browser is Internet Explorer otherwise false
546
- */
547
- function checkBrowserInternetExplorer() {
548
-
549
- // Test for v1 - v1.5 IE
550
- if( stripos($this->_agent,'microsoft internet explorer') !== false ) {
551
- $this->setBrowser($this->BROWSER_IE);
552
- $this->setVersion('1.0');
553
- $aresult = stristr($this->_agent, '/');
554
- if( preg_match('/308|425|426|474|0b1/i', $aresult) ) {
555
- $this->setVersion('1.5');
556
- }
557
- return true;
558
- }
559
- // Test for versions > 1.5
560
- else if( stripos($this->_agent,'msie') !== false && stripos($this->_agent,'opera') === false ) {
561
- // See if the browser is the odd MSN Explorer
562
- if( stripos($this->_agent,'msnb') !== false ) {
563
- $aresult = explode(' ',stristr(str_replace(';','; ',$this->_agent),'MSN'));
564
- $this->setBrowser( $this->BROWSER_MSN );
565
- $this->setVersion(str_replace(array('(',')',';'),'',$aresult[1]));
566
- return true;
567
- }
568
- $aresult = explode(' ',stristr(str_replace(';','; ',$this->_agent),'msie'));
569
- $this->setBrowser( $this->BROWSER_IE );
570
- $this->setVersion(str_replace(array('(',')',';'),'',$aresult[1]));
571
- return true;
572
- }
573
- // Test for Pocket IE
574
- else if( stripos($this->_agent,'mspie') !== false || stripos($this->_agent,'pocket') !== false ) {
575
- $aresult = explode(' ',stristr($this->_agent,'mspie'));
576
- $this->setPlatform( $this->PLATFORM_WINDOWS_CE );
577
- $this->setBrowser( $this->BROWSER_POCKET_IE );
578
- $this->setMobile(true);
579
-
580
- if( stripos($this->_agent,'mspie') !== false ) {
581
- $this->setVersion($aresult[1]);
582
- }
583
- else {
584
- $aversion = explode('/',$this->_agent);
585
- $this->setVersion($aversion[1]);
586
- }
587
- return true;
588
- }
589
- return false;
590
- }
591
-
592
- /**
593
- * Determine if the browser is Opera or not (last updated 1.7)
594
- * @return boolean True if the browser is Opera otherwise false
595
- */
596
- function checkBrowserOpera() {
597
- if( stripos($this->_agent,'opera mini') !== false ) {
598
- $resultant = stristr($this->_agent, 'opera mini');
599
- if( preg_match('/\//',$resultant) ) {
600
- $aresult = explode('/',$resultant);
601
- $aversion = explode(' ',$aresult[1]);
602
- $this->setVersion($aversion[0]);
603
- }
604
- else {
605
- $aversion = explode(' ',stristr($resultant,'opera mini'));
606
- $this->setVersion($aversion[1]);
607
- }
608
- $this->_browser_name = $this->BROWSER_OPERA_MINI;
609
- $this->setMobile(true);
610
- return true;
611
- }
612
- else if( stripos($this->_agent,'opera') !== false ) {
613
- $resultant = stristr($this->_agent, 'opera');
614
- if( preg_match('/Version\/(10.*)$/',$resultant,$matches) ) {
615
- $this->setVersion($matches[1]);
616
- }
617
- else if( preg_match('/\//',$resultant) ) {
618
- $aresult = explode('/',str_replace("("," ",$resultant));
619
- $aversion = explode(' ',$aresult[1]);
620
- $this->setVersion($aversion[0]);
621
- }
622
- else {
623
- $aversion = explode(' ',stristr($resultant,'opera'));
624
- $this->setVersion(isset($aversion[1])?$aversion[1]:"");
625
- }
626
- $this->_browser_name = $this->BROWSER_OPERA;
627
- return true;
628
- }
629
- return false;
630
- }
631
-
632
- /**
633
- * Determine if the browser is Chrome or not (last updated 1.7)
634
- * @return boolean True if the browser is Chrome otherwise false
635
- */
636
- function checkBrowserChrome() {
637
- if( stripos($this->_agent,'Chrome') !== false ) {
638
- $aresult = explode('/',stristr($this->_agent,'Chrome'));
639
- $aversion = explode(' ',$aresult[1]);
640
- $this->setVersion($aversion[0]);
641
- $this->setBrowser($this->BROWSER_CHROME);
642
- return true;
643
- }
644
- return false;
645
- }
646
-
647
-
648
- /**
649
- * Determine if the browser is WebTv or not (last updated 1.7)
650
- * @return boolean True if the browser is WebTv otherwise false
651
- */
652
- function checkBrowserWebTv() {
653
- if( stripos($this->_agent,'webtv') !== false ) {
654
- $aresult = explode('/',stristr($this->_agent,'webtv'));
655
- $aversion = explode(' ',$aresult[1]);
656
- $this->setVersion($aversion[0]);
657
- $this->setBrowser($this->BROWSER_WEBTV);
658
- return true;
659
- }
660
- return false;
661
- }
662
-
663
- /**
664
- * Determine if the browser is NetPositive or not (last updated 1.7)
665
- * @return boolean True if the browser is NetPositive otherwise false
666
- */
667
- function checkBrowserNetPositive() {
668
- if( stripos($this->_agent,'NetPositive') !== false ) {
669
- $aresult = explode('/',stristr($this->_agent,'NetPositive'));
670
- $aversion = explode(' ',$aresult[1]);
671
- $this->setVersion(str_replace(array('(',')',';'),'',$aversion[0]));
672
- $this->setBrowser($this->BROWSER_NETPOSITIVE);
673
- return true;
674
- }
675
- return false;
676
- }
677
-
678
- /**
679
- * Determine if the browser is Galeon or not (last updated 1.7)
680
- * @return boolean True if the browser is Galeon otherwise false
681
- */
682
- function checkBrowserGaleon() {
683
- if( stripos($this->_agent,'galeon') !== false ) {
684
- $aresult = explode(' ',stristr($this->_agent,'galeon'));
685
- $aversion = explode('/',$aresult[0]);
686
- $this->setVersion($aversion[1]);
687
- $this->setBrowser($this->BROWSER_GALEON);
688
- return true;
689
- }
690
- return false;
691
- }
692
-
693
- /**
694
- * Determine if the browser is Konqueror or not (last updated 1.7)
695
- * @return boolean True if the browser is Konqueror otherwise false
696
- */
697
- function checkBrowserKonqueror() {
698
- if( stripos($this->_agent,'Konqueror') !== false ) {
699
- $aresult = explode(' ',stristr($this->_agent,'Konqueror'));
700
- $aversion = explode('/',$aresult[0]);
701
- $this->setVersion($aversion[1]);
702
- $this->setBrowser($this->BROWSER_KONQUEROR);
703
- return true;
704
- }
705
- return false;
706
- }
707
-
708
- /**
709
- * Determine if the browser is iCab or not (last updated 1.7)
710
- * @return boolean True if the browser is iCab otherwise false
711
- */
712
- function checkBrowserIcab() {
713
- if( stripos($this->_agent,'icab') !== false ) {
714
- $aversion = explode(' ',stristr(str_replace('/',' ',$this->_agent),'icab'));
715
- $this->setVersion($aversion[1]);
716
- $this->setBrowser($this->BROWSER_ICAB);
717
- return true;
718
- }
719
- return false;
720
- }
721
-
722
- /**
723
- * Determine if the browser is OmniWeb or not (last updated 1.7)
724
- * @return boolean True if the browser is OmniWeb otherwise false
725
- */
726
- function checkBrowserOmniWeb() {
727
- if( stripos($this->_agent,'omniweb') !== false ) {
728
- $aresult = explode('/',stristr($this->_agent,'omniweb'));
729
- $aversion = explode(' ',isset($aresult[1])?$aresult[1]:"");
730
- $this->setVersion($aversion[0]);
731
- $this->setBrowser($this->BROWSER_OMNIWEB);
732
- return true;
733
- }
734
- return false;
735
- }
736
-
737
- /**
738
- * Determine if the browser is Phoenix or not (last updated 1.7)
739
- * @return boolean True if the browser is Phoenix otherwise false
740
- */
741
- function checkBrowserPhoenix() {
742
- if( stripos($this->_agent,'Phoenix') !== false ) {
743
- $aversion = explode('/',stristr($this->_agent,'Phoenix'));
744
- $this->setVersion($aversion[1]);
745
- $this->setBrowser($this->BROWSER_PHOENIX);
746
- return true;
747
- }
748
- return false;
749
- }
750
-
751
- /**
752
- * Determine if the browser is Firebird or not (last updated 1.7)
753
- * @return boolean True if the browser is Firebird otherwise false
754
- */
755
- function checkBrowserFirebird() {
756
- if( stripos($this->_agent,'Firebird') !== false ) {
757
- $aversion = explode('/',stristr($this->_agent,'Firebird'));
758
- $this->setVersion($aversion[1]);
759
- $this->setBrowser($this->BROWSER_FIREBIRD);
760
- return true;
761
- }
762
- return false;
763
- }
764
-
765
- /**
766
- * Determine if the browser is Netscape Navigator 9+ or not (last updated 1.7)
767
- * NOTE: (http://browser.netscape.com/ - Official support ended on March 1st, 2008)
768
- * @return boolean True if the browser is Netscape Navigator 9+ otherwise false
769
- */
770
- function checkBrowserNetscapeNavigator9Plus() {
771
- if( stripos($this->_agent,'Firefox') !== false && preg_match('/Navigator\/([^ ]*)/i',$this->_agent,$matches) ) {
772
- $this->setVersion($matches[1]);
773
- $this->setBrowser($this->BROWSER_NETSCAPE_NAVIGATOR);
774
- return true;
775
- }
776
- else if( stripos($this->_agent,'Firefox') === false && preg_match('/Netscape6?\/([^ ]*)/i',$this->_agent,$matches) ) {
777
- $this->setVersion($matches[1]);
778
- $this->setBrowser($this->BROWSER_NETSCAPE_NAVIGATOR);
779
- return true;
780
- }
781
- return false;
782
- }
783
-
784
- /**
785
- * Determine if the browser is Shiretoko or not (https://wiki.mozilla.org/Projects/shiretoko) (last updated 1.7)
786
- * @return boolean True if the browser is Shiretoko otherwise false
787
- */
788
- function checkBrowserShiretoko() {
789
- if( stripos($this->_agent,'Mozilla') !== false && preg_match('/Shiretoko\/([^ ]*)/i',$this->_agent,$matches) ) {
790
- $this->setVersion($matches[1]);
791
- $this->setBrowser($this->BROWSER_SHIRETOKO);
792
- return true;
793
- }
794
- return false;
795
- }
796
-
797
- /**
798
- * Determine if the browser is Ice Cat or not (http://en.wikipedia.org/wiki/GNU_IceCat) (last updated 1.7)
799
- * @return boolean True if the browser is Ice Cat otherwise false
800
- */
801
- function checkBrowserIceCat() {
802
- if( stripos($this->_agent,'Mozilla') !== false && preg_match('/IceCat\/([^ ]*)/i',$this->_agent,$matches) ) {
803
- $this->setVersion($matches[1]);
804
- $this->setBrowser($this->BROWSER_ICECAT);
805
- return true;
806
- }
807
- return false;
808
- }
809
-
810
- /**
811
- * Determine if the browser is Nokia or not (last updated 1.7)
812
- * @return boolean True if the browser is Nokia otherwise false
813
- */
814
- function checkBrowserNokia() {
815
- if( preg_match("/Nokia([^\/]+)\/([^ SP]+)/i",$this->_agent,$matches) ) {
816
- $this->setVersion($matches[2]);
817
- if( stripos($this->_agent,'Series60') !== false || strpos($this->_agent,'S60') !== false ) {
818
- $this->setBrowser($this->BROWSER_NOKIA_S60);
819
- }
820
- else {
821
- $this->setBrowser( $this->BROWSER_NOKIA );
822
- }
823
- $this->setMobile(true);
824
- return true;
825
- }
826
- return false;
827
- }
828
-
829
- /**
830
- * Determine if the browser is Firefox or not (last updated 1.7)
831
- * @return boolean True if the browser is Firefox otherwise false
832
- */
833
- function checkBrowserFirefox() {
834
- if( stripos($this->_agent,'safari') === false ) {
835
- if( preg_match("/Firefox[\/ \(]([^ ;\)]+)/i",$this->_agent,$matches) ) {
836
- $this->setVersion($matches[1]);
837
- $this->setBrowser($this->BROWSER_FIREFOX);
838
- return true;
839
- }
840
- else if( preg_match("/Firefox$/i",$this->_agent,$matches) ) {
841
- $this->setVersion("");
842
- $this->setBrowser($this->BROWSER_FIREFOX);
843
- return true;
844
- }
845
- }
846
- return false;
847
- }
848
-
849
- /**
850
- * Determine if the browser is Firefox or not (last updated 1.7)
851
- * @return boolean True if the browser is Firefox otherwise false
852
- */
853
- function checkBrowserIceweasel() {
854
- if( stripos($this->_agent,'Iceweasel') !== false ) {
855
- $aresult = explode('/',stristr($this->_agent,'Iceweasel'));
856
- $aversion = explode(' ',$aresult[1]);
857
- $this->setVersion($aversion[0]);
858
- $this->setBrowser($this->BROWSER_ICEWEASEL);
859
- return true;
860
- }
861
- return false;
862
- }
863
- /**
864
- * Determine if the browser is Mozilla or not (last updated 1.7)
865
- * @return boolean True if the browser is Mozilla otherwise false
866
- */
867
- function checkBrowserMozilla() {
868
- if( stripos($this->_agent,'mozilla') !== false && preg_match('/rv:[0-9].[0-9][a-b]?/i',$this->_agent) && stripos($this->_agent,'netscape') === false) {
869
- $aversion = explode(' ',stristr($this->_agent,'rv:'));
870
- preg_match('/rv:[0-9].[0-9][a-b]?/i',$this->_agent,$aversion);
871
- $this->setVersion(str_replace('rv:','',$aversion[0]));
872
- $this->setBrowser($this->BROWSER_MOZILLA);
873
- return true;
874
- }
875
- else if( stripos($this->_agent,'mozilla') !== false && preg_match('/rv:[0-9]\.[0-9]/i',$this->_agent) && stripos($this->_agent,'netscape') === false ) {
876
- $aversion = explode('',stristr($this->_agent,'rv:'));
877
- $this->setVersion(str_replace('rv:','',$aversion[0]));
878
- $this->setBrowser($this->BROWSER_MOZILLA);
879
- return true;
880
- }
881
- else if( stripos($this->_agent,'mozilla') !== false && preg_match('/mozilla\/([^ ]*)/i',$this->_agent,$matches) && stripos($this->_agent,'netscape') === false ) {
882
- $this->setVersion($matches[1]);
883
- $this->setBrowser($this->BROWSER_MOZILLA);
884
- return true;
885
- }
886
- return false;
887
- }
888
-
889
- /**
890
- * Determine if the browser is Lynx or not (last updated 1.7)
891
- * @return boolean True if the browser is Lynx otherwise false
892
- */
893
- function checkBrowserLynx() {
894
- if( stripos($this->_agent,'lynx') !== false ) {
895
- $aresult = explode('/',stristr($this->_agent,'Lynx'));
896
- $aversion = explode(' ',(isset($aresult[1])?$aresult[1]:""));
897
- $this->setVersion($aversion[0]);
898
- $this->setBrowser($this->BROWSER_LYNX);
899
- return true;
900
- }
901
- return false;
902
- }
903
-
904
- /**
905
- * Determine if the browser is Amaya or not (last updated 1.7)
906
- * @return boolean True if the browser is Amaya otherwise false
907
- */
908
- function checkBrowserAmaya() {
909
- if( stripos($this->_agent,'amaya') !== false ) {
910
- $aresult = explode('/',stristr($this->_agent,'Amaya'));
911
- $aversion = explode(' ',$aresult[1]);
912
- $this->setVersion($aversion[0]);
913
- $this->setBrowser($this->BROWSER_AMAYA);
914
- return true;
915
- }
916
- return false;
917
- }
918
-
919
- /**
920
- * Determine if the browser is Safari or not (last updated 1.7)
921
- * @return boolean True if the browser is Safari otherwise false
922
- */
923
- function checkBrowserSafari() {
924
- if( stripos($this->_agent,'Safari') !== false && stripos($this->_agent,'iPhone') === false && stripos($this->_agent,'iPod') === false ) {
925
- $aresult = explode('/',stristr($this->_agent,'Version'));
926
- if( isset($aresult[1]) ) {
927
- $aversion = explode(' ',$aresult[1]);
928
- $this->setVersion($aversion[0]);
929
- }
930
- else {
931
- $this->setVersion($this->VERSION_UNKNOWN);
932
- }
933
- $this->setBrowser($this->BROWSER_SAFARI);
934
- return true;
935
- }
936
- return false;
937
- }
938
-
939
- /**
940
- * Determine if the browser is iPhone or not (last updated 1.7)
941
- * @return boolean True if the browser is iPhone otherwise false
942
- */
943
- function checkBrowseriPhone() {
944
- if( stripos($this->_agent,'iPhone') !== false ) {
945
- $aresult = explode('/',stristr($this->_agent,'Version'));
946
- if( isset($aresult[1]) ) {
947
- $aversion = explode(' ',$aresult[1]);
948
- $this->setVersion($aversion[0]);
949
- }
950
- else {
951
- $this->setVersion($this->VERSION_UNKNOWN);
952
- }
953
- $this->setMobile(true);
954
- $this->setBrowser($this->BROWSER_IPHONE);
955
- return true;
956
- }
957
- return false;
958
- }
959
-
960
- /**
961
- * Determine if the browser is iPod or not (last updated 1.7)
962
- * @return boolean True if the browser is iPod otherwise false
963
- */
964
- function checkBrowseriPad() {
965
- if( stripos($this->_agent,'iPad') !== false ) {
966
- $aresult = explode('/',stristr($this->_agent,'Version'));
967
- if( isset($aresult[1]) ) {
968
- $aversion = explode(' ',$aresult[1]);
969
- $this->setVersion($aversion[0]);
970
- }
971
- else {
972
- $this->setVersion($this->VERSION_UNKNOWN);
973
- }
974
- $this->setMobile(true);
975
- $this->setBrowser($this->BROWSER_IPAD);
976
- return true;
977
- }
978
- return false;
979
- }
980
-
981
- /**
982
- * Determine if the browser is iPod or not (last updated 1.7)
983
- * @return boolean True if the browser is iPod otherwise false
984
- */
985
- function checkBrowseriPod() {
986
- if( stripos($this->_agent,'iPod') !== false ) {
987
- $aresult = explode('/',stristr($this->_agent,'Version'));
988
- if( isset($aresult[1]) ) {
989
- $aversion = explode(' ',$aresult[1]);
990
- $this->setVersion($aversion[0]);
991
- }
992
- else {
993
- $this->setVersion($this->VERSION_UNKNOWN);
994
- }
995
- $this->setMobile(true);
996
- $this->setBrowser($this->BROWSER_IPOD);
997
- return true;
998
- }
999
- return false;
1000
- }
1001
-
1002
- /**
1003
- * Determine if the browser is Android or not (last updated 1.7)
1004
- * @return boolean True if the browser is Android otherwise false
1005
- */
1006
- function checkBrowserAndroid() {
1007
- if( stripos($this->_agent,'Android') !== false ) {
1008
- $aresult = explode(' ',stristr($this->_agent,'Android'));
1009
- if( isset($aresult[1]) ) {
1010
- $aversion = explode(' ',$aresult[1]);
1011
- $this->setVersion($aversion[0]);
1012
- }
1013
- else {
1014
- $this->setVersion($this->VERSION_UNKNOWN);
1015
- }
1016
- $this->setMobile(true);
1017
- $this->setBrowser($this->BROWSER_ANDROID);
1018
- return true;
1019
- }
1020
- return false;
1021
- }
1022
-
1023
- /**
1024
- * Determine the user's platform (last updated 1.7)
1025
- */
1026
- function checkPlatform() {
1027
- if( stripos($this->_agent, 'windows') !== false ) {
1028
- $this->_platform = $this->PLATFORM_WINDOWS;
1029
- }
1030
- else if( stripos($this->_agent, 'iPad') !== false ) {
1031
- $this->_platform = $this->PLATFORM_IPAD;
1032
- }
1033
- else if( stripos($this->_agent, 'iPod') !== false ) {
1034
- $this->_platform = $this->PLATFORM_IPOD;
1035
- }
1036
- else if( stripos($this->_agent, 'iPhone') !== false ) {
1037
- $this->_platform = $this->PLATFORM_IPHONE;
1038
- }
1039
- elseif( stripos($this->_agent, 'mac') !== false ) {
1040
- $this->_platform = $this->PLATFORM_APPLE;
1041
- }
1042
- elseif( stripos($this->_agent, 'android') !== false ) {
1043
- $this->_platform = $this->PLATFORM_ANDROID;
1044
- }
1045
- elseif( stripos($this->_agent, 'linux') !== false ) {
1046
- $this->_platform = $this->PLATFORM_LINUX;
1047
- }
1048
- else if( stripos($this->_agent, 'Nokia') !== false ) {
1049
- $this->_platform = $this->PLATFORM_NOKIA;
1050
- }
1051
- else if( stripos($this->_agent, 'BlackBerry') !== false ) {
1052
- $this->_platform = $this->PLATFORM_BLACKBERRY;
1053
- }
1054
- elseif( stripos($this->_agent,'FreeBSD') !== false ) {
1055
- $this->_platform = $this->PLATFORM_FREEBSD;
1056
- }
1057
- elseif( stripos($this->_agent,'OpenBSD') !== false ) {
1058
- $this->_platform = $this->PLATFORM_OPENBSD;
1059
- }
1060
- elseif( stripos($this->_agent,'NetBSD') !== false ) {
1061
- $this->_platform = $this->PLATFORM_NETBSD;
1062
- }
1063
- elseif( stripos($this->_agent, 'OpenSolaris') !== false ) {
1064
- $this->_platform = $this->PLATFORM_OPENSOLARIS;
1065
- }
1066
- elseif( stripos($this->_agent, 'SunOS') !== false ) {
1067
- $this->_platform = $this->PLATFORM_SUNOS;
1068
- }
1069
- elseif( stripos($this->_agent, 'OS\/2') !== false ) {
1070
- $this->_platform = $this->PLATFORM_OS2;
1071
- }
1072
- elseif( stripos($this->_agent, 'BeOS') !== false ) {
1073
- $this->_platform = $this->PLATFORM_BEOS;
1074
- }
1075
- elseif( stripos($this->_agent, 'win') !== false ) {
1076
- $this->_platform = $this->PLATFORM_WINDOWS;
1077
- }
1078
-
1079
- }
1080
- }
1081
-
1082
- ?>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
include/license/class-bd-edd-api-wrapper.php ADDED
@@ -0,0 +1,156 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Wrapper for EDD API
4
+ *
5
+ * @since 5.0
6
+ * @author Sudar
7
+ * @package BulkDelete\License
8
+ */
9
+
10
+ defined( 'ABSPATH' ) || exit; // Exit if accessed directly
11
+
12
+ class BD_EDD_API_Wrapper {
13
+
14
+ /**
15
+ * Store url
16
+ *
17
+ * @since 5.0
18
+ */
19
+ const STORE_URL = 'http://bulkwp.com';
20
+
21
+ /**
22
+ * Check license
23
+ *
24
+ * @since 5.0
25
+ * @static
26
+ * @param string $addon Addon name
27
+ * @param string $license The license code
28
+ * @return array|false False if request fails, API response otherwise
29
+ */
30
+ public static function check_license( $addon, $license ) {
31
+ $api_params = array(
32
+ 'edd_action' => 'check_license',
33
+ 'license' => trim( $license ),
34
+ 'item_name' => urlencode( $addon ),
35
+ 'url' => home_url(),
36
+ );
37
+
38
+ $license_data = array(
39
+ 'license' => $license,
40
+ 'item_name' => $addon,
41
+ 'validity' => 'invalid',
42
+ );
43
+
44
+ $response = self::call_edd_api( $api_params );
45
+
46
+ if ( $response && isset( $response->license ) ) {
47
+ if ( 'valid' == $response->license ) {
48
+ $license_data['license'] = $license;
49
+ $license_data['validity'] = 'valid';
50
+ $license_data['expires'] = $response->expires;
51
+ $license_data['addon-name'] = $response->item_name;
52
+ } elseif ( 'invalid' == $response->license ) {
53
+ $license_data['validity'] = 'invalid';
54
+ } elseif ( 'site_inactive' == $response->license ) {
55
+ $license_data['validity'] = 'invalid';
56
+ }
57
+
58
+ return $license_data;
59
+ }
60
+
61
+ return false;
62
+ }
63
+
64
+ /**
65
+ * Activate license
66
+ *
67
+ * @since 5.0
68
+ * @static
69
+ * @param string $addon The addon that needs to be activated
70
+ * @param string $license The license code
71
+ * @return array|false False if request fails, License info otherwise
72
+ */
73
+ public static function activate_license( $addon, $license ) {
74
+ $api_params = array(
75
+ 'edd_action' => 'activate_license',
76
+ 'license' => trim( $license ),
77
+ 'item_name' => urlencode( $addon ),
78
+ 'url' => home_url(),
79
+ );
80
+
81
+ $response = self::call_edd_api( $api_params );
82
+
83
+ if ( $response && isset( $response->success ) ) {
84
+ if ( 'true' == $response->success ) {
85
+ return array(
86
+ 'license' => $license,
87
+ 'validity' => 'valid',
88
+ 'expires' => $response->expires,
89
+ 'addon-name' => $response->item_name,
90
+ );
91
+ } else {
92
+ $err_response = array(
93
+ 'validity' => 'invalid',
94
+ );
95
+
96
+ if ( isset( $response->error ) ) {
97
+ $err_response['error'] = $response->error;
98
+ }
99
+
100
+ return $err_response;
101
+ }
102
+ }
103
+
104
+ return false;
105
+ }
106
+
107
+ /**
108
+ * Deactivate License
109
+ *
110
+ * @since 5.0
111
+ * @static
112
+ * @param string $addon The addon that needs to be deactivated
113
+ * @param string $license The license code
114
+ * @return bool True if deactivated, False otherwise
115
+ */
116
+ public static function deactivate_license( $addon, $license ) {
117
+ $api_params = array(
118
+ 'edd_action' => 'deactivate_license',
119
+ 'license' => trim( $license ),
120
+ 'item_name' => urlencode( $addon ),
121
+ 'url' => home_url(),
122
+ );
123
+
124
+ $response = self::call_edd_api( $api_params );
125
+
126
+ if ( $response && isset( $response->license ) ) {
127
+ if ( 'deactivated' == $response->license ) {
128
+ return true;
129
+ }
130
+ }
131
+
132
+ return false;
133
+ }
134
+
135
+ /**
136
+ * Call the EDD API
137
+ *
138
+ * @since 5.0
139
+ * @static
140
+ * @access private
141
+ * @param array $api_params Parameters for API
142
+ * @return bool|array $license_data False if request fails, API response otherwise
143
+ */
144
+ private static function call_edd_api( $api_params ) {
145
+ $response = wp_remote_get( add_query_arg( $api_params, self::STORE_URL ), array( 'timeout' => 15, 'sslverify' => false ) );
146
+
147
+ // make sure the response came back okay
148
+ if ( is_wp_error( $response ) ) {
149
+ return false;
150
+ }
151
+
152
+ $license_object = json_decode( wp_remote_retrieve_body( $response ) );
153
+ return $license_object;
154
+ }
155
+ }
156
+ ?>
include/license/class-bd-license-handler.php ADDED
@@ -0,0 +1,300 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * License Handler for Bulk Delete Addons
4
+ *
5
+ * @since 5.0
6
+ * @author Sudar
7
+ * @package BulkDelete/License
8
+ */
9
+
10
+ defined( 'ABSPATH' ) || exit; // Exit if accessed directly
11
+
12
+ class BD_License_Handler {
13
+
14
+ /**
15
+ * Name of the addon
16
+ *
17
+ * @since 5.0
18
+ */
19
+ private $addon_name;
20
+
21
+ /**
22
+ * Code of the addon
23
+ *
24
+ * @since 5.0
25
+ */
26
+ private $addon_code;
27
+
28
+ /**
29
+ * Version of the plugin
30
+ *
31
+ * @since 5.0
32
+ */
33
+ private $version;
34
+
35
+ /**
36
+ * plugin file name
37
+ *
38
+ * @since 5.0
39
+ */
40
+ private $plugin_file;
41
+
42
+ /**
43
+ * Plugin base name
44
+ *
45
+ * @since 5.5
46
+ */
47
+ private $plugin_basename;
48
+
49
+ /**
50
+ * Author of the plugin
51
+ *
52
+ * @since 5.0
53
+ */
54
+ private $author;
55
+
56
+ /**
57
+ * Instance of the updater class.
58
+ *
59
+ * @since 5.5
60
+ */
61
+ private $updater;
62
+
63
+ /**
64
+ * Notice Message.
65
+ *
66
+ * @since 5.5
67
+ */
68
+ private $notice_msg = '';
69
+
70
+ /**
71
+ * Constructor
72
+ *
73
+ * @since 5.0
74
+ *
75
+ * @param string $addon_name Name of the addon
76
+ * @param string $addon_code Code of the addon
77
+ * @param string $version Version of the addon
78
+ * @param string $plugin_file Addon file name
79
+ * @param string $author (optional) Author of the addon
80
+ */
81
+ public function __construct( $addon_name, $addon_code, $version, $plugin_file, $author = 'Sudar Muthu' ) {
82
+ $this->addon_name = $addon_name;
83
+ $this->addon_code = $addon_code;
84
+ $this->version = $version;
85
+ $this->plugin_file = $plugin_file;
86
+ $this->plugin_basename = plugin_basename( $plugin_file );
87
+ $this->author = $author;
88
+
89
+ $this->hooks();
90
+ }
91
+
92
+ /**
93
+ * setup hooks
94
+ *
95
+ * @access private
96
+ * @since 5.0
97
+ */
98
+ private function hooks() {
99
+ add_action( 'admin_init', array( $this, 'check_license' ), 0 );
100
+ add_action( 'admin_notices', array( $this, 'show_admin_notices' ) );
101
+ add_action( 'after_plugin_row_' . $this->plugin_basename, array( $this, 'plugin_row' ), 11, 3 );
102
+
103
+ add_action( 'bd_license_form' , array( $this, 'display_license_form' ) );
104
+ add_action( 'bd_license_field', array( $this, 'add_license_field' ) );
105
+ add_filter( 'bd_license_input', array( $this, 'parse_license_input' ), 1 );
106
+ }
107
+
108
+ /**
109
+ * Check whether the license is valid for the addon.
110
+ *
111
+ * If the license is not valid then add a notice about it.
112
+ * If it is valid then hook the plugin updater.
113
+ *
114
+ * @since 5.5
115
+ */
116
+ public function check_license() {
117
+ if ( defined( 'DOING_AJAX' ) && DOING_AJAX ) {
118
+ return;
119
+ }
120
+
121
+ $campaign_args = array(
122
+ 'utm_source' => 'wpadmin',
123
+ 'utm_campaign' => 'BulkDelete',
124
+ 'utm_medium' => 'header-notice',
125
+ 'utm_content' => strtolower( $this->addon_code ),
126
+ );
127
+ $addon_url = bd_get_addon_url( $this->addon_name, $campaign_args );
128
+
129
+ $license_code = BD_License::get_license_code( $this->addon_code );
130
+
131
+ if ( false == $license_code ) {
132
+ $this->notice_msg = sprintf( __( '"%1$s" addon is installed but not activated. To activate the addon, please <a href="%2$s">enter your license key</a>. If you don\'t have a license key, then you can <a href="%3$s" target="_blank">purchase one</a>.', 'bulk-delete' ), $this->addon_name, esc_url( get_bloginfo( 'wpurl' ) . '/wp-admin/admin.php?page=' . Bulk_Delete::ADDON_PAGE_SLUG ), esc_url( $addon_url ) );
133
+ } else {
134
+ if ( BD_License::has_valid_license( $this->addon_name, $this->addon_code ) ) {
135
+ if ( false != $license_code ) {
136
+ $this->hook_updater( $license_code );
137
+ }
138
+ } else {
139
+ $this->notice_msg = sprintf( __( 'The license for "%1$s" addon is either invalid or has expired. Please <a href="%2$s" target="_blank">renew the license</a> or <a href="%3$s">enter a new license key</a> to receive updates and support.', 'bulk-delete' ), $this->addon_name, esc_url( $addon_url ), esc_url( get_bloginfo( 'wpurl' ) . '/wp-admin/admin.php?page=' . Bulk_Delete::ADDON_PAGE_SLUG ) );
140
+ }
141
+ }
142
+ }
143
+
144
+ /**
145
+ * Start the updater.
146
+ *
147
+ * @since 5.0
148
+ * @access private
149
+ * @param string $license_code License Code
150
+ */
151
+ private function hook_updater( $license_code ) {
152
+ if ( ! class_exists( 'EDD_SL_Plugin_Updater' ) ) {
153
+ require_once Bulk_Delete::$PLUGIN_DIR . '/include/libraries/EDD_SL_Plugin_Updater.php';
154
+ }
155
+
156
+ $this->updater = new EDD_SL_Plugin_Updater( BD_EDD_API_Wrapper::STORE_URL, $this->plugin_file, array(
157
+ 'version' => $this->version,
158
+ 'license' => $license_code,
159
+ 'item_name' => $this->addon_name,
160
+ 'addon_code' => $this->addon_code,
161
+ 'author' => $this->author,
162
+ 'url' => home_url()
163
+ )
164
+ );
165
+ }
166
+
167
+ /**
168
+ * Display notification at the top of all admin pages.
169
+ *
170
+ * @since 5.5
171
+ */
172
+ public function show_admin_notices() {
173
+ if ( '' != $this->notice_msg ) {
174
+ printf( '<div class="error"><p><strong>%s</strong></p></div>', $this->notice_msg );
175
+ }
176
+ }
177
+
178
+ /**
179
+ * Display license information about addon in plugin list table.
180
+ *
181
+ * @since 5.5
182
+ * @param string $plugin_file Path to the plugin file, relative to the plugins directory.
183
+ * @param array $plugin_data An array of plugin data.
184
+ * @param string $status Status of the plugin.
185
+ */
186
+ public function plugin_row( $plugin_file, $plugin_data, $status ) {
187
+ if ( $plugin_file != $this->plugin_basename ) {
188
+ return;
189
+ }
190
+
191
+ $campaign_args = array(
192
+ 'utm_source' => 'wpadmin',
193
+ 'utm_campaign' => 'BulkDelete',
194
+ 'utm_medium' => 'plugin-page',
195
+ 'utm_content' => strtolower( $this->addon_code ),
196
+ );
197
+ $addon_url = bd_get_addon_url( $this->addon_name, $campaign_args );
198
+
199
+ $license_code = BD_License::get_license_code( $this->addon_code );
200
+ if ( false == $license_code ) {
201
+ $plugin_row_msg = sprintf( __( 'Addon is not activated. To activate the addon, please <a href="%1$s">enter your license key</a>. If you don\'t have a license key, then you can <a href="%2$s" target="_blank">purchase one</a>.', 'bulk-delete' ), esc_url( get_bloginfo( 'wpurl' ) . '/wp-admin/admin.php?page=' . Bulk_Delete::ADDON_PAGE_SLUG ), esc_url( $addon_url ) );
202
+ ?>
203
+ <tr class="plugin-update-tr">
204
+ <td colspan="3" class="plugin-update">
205
+ <div class="update-message"><span class="bd-licence-activate-notice"><?php echo $plugin_row_msg; ?></span></div>
206
+ </td>
207
+ </tr>
208
+ <?php
209
+ } else {
210
+ if ( ! BD_License::has_valid_license( $this->addon_name, $this->addon_code ) ) {
211
+ $plugin_row_msg = sprintf( __( 'The license for this addon is either invalid or has expired. Please <a href="%1$s" target="_blank">renew the license</a> or <a href="%2$s">enter a new license key</a> to receive updates and support.', 'bulk-delete' ), esc_url( $addon_url ), esc_url( get_bloginfo( 'wpurl' ) . '/wp-admin/admin.php?page=' . Bulk_Delete::ADDON_PAGE_SLUG ) );
212
+ ?>
213
+ <tr class="plugin-update-tr">
214
+ <td colspan="3" class="plugin-update">
215
+ <div class="update-message"><span class="bd-licence-activate-notice"><?php echo $plugin_row_msg; ?></span></div>
216
+ </td>
217
+ </tr>
218
+ <?php
219
+ }
220
+ }
221
+ }
222
+
223
+ /**
224
+ * Decide whether to display the license form or not
225
+ *
226
+ * @since 5.0
227
+ */
228
+ public function display_license_form() {
229
+ if ( ! BD_License::has_valid_license( $this->addon_name, $this->addon_code ) ) {
230
+ $bd = BULK_DELETE();
231
+ $bd->display_activate_license_form = true;
232
+ }
233
+ }
234
+
235
+ /**
236
+ * Add the license field to license form
237
+ *
238
+ * @since 5.0
239
+ */
240
+ public function add_license_field() {
241
+ if ( ! BD_License::has_valid_license( $this->addon_name, $this->addon_code ) ) {
242
+ add_settings_field(
243
+ $this->addon_code, // ID
244
+ '"' . $this->addon_name . '" ' . __( 'Addon License Key', 'bulk-delete' ), // Title
245
+ array( $this, 'print_license_key_field' ), // Callback
246
+ Bulk_Delete::ADDON_PAGE_SLUG, // Page
247
+ Bulk_Delete::SETTING_SECTION_ID // Section
248
+ );
249
+ }
250
+ }
251
+
252
+ /**
253
+ * Print the license field
254
+ *
255
+ * @since 5.0
256
+ */
257
+ public function print_license_key_field() {
258
+ if ( ! BD_License::has_valid_license( $this->addon_name, $this->addon_code ) ) {
259
+ printf(
260
+ '<input type="text" id="%s" name="%s[%s]" placeholder="%s" size="40">',
261
+ $this->addon_code,
262
+ Bulk_Delete::SETTING_OPTION_NAME,
263
+ $this->addon_code,
264
+ __( 'Enter license key', 'bulk-delete' )
265
+ );
266
+ }
267
+ }
268
+
269
+ /**
270
+ * Parse the license key and activate it if needed.
271
+ * If the key is invalid, then don't save it in the setting option
272
+ *
273
+ * @since 5.0
274
+ * @param array $input
275
+ * @return array
276
+ */
277
+ public function parse_license_input( $input ) {
278
+ if ( is_array( $input ) && key_exists( $this->addon_code, $input ) ) {
279
+ $license_code = trim( $input[ $this->addon_code ] );
280
+
281
+ if ( ! empty( $license_code ) ) {
282
+ if ( ! BD_License::has_valid_license( $this->addon_name, $this->addon_code ) ) {
283
+ $activated = BD_License::activate_license( $this->addon_name, $this->addon_code, $license_code );
284
+ if ( ! $activated ) {
285
+ unset( $input[ $this->addon_code ] );
286
+ }
287
+ }
288
+ } else {
289
+ unset( $input[ $this->addon_code ] );
290
+ }
291
+ } else {
292
+ if ( BD_License::has_valid_license( $this->addon_name, $this->addon_code ) ) {
293
+ $license_code = BD_License::get_license_code( $this->addon_code );
294
+ $input[ $this->addon_code ] = $license_code;
295
+ }
296
+ }
297
+ return $input;
298
+ }
299
+ }
300
+ ?>
include/license/class-bd-license.php ADDED
@@ -0,0 +1,355 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Addon license related functions
4
+ *
5
+ * @since 5.0
6
+ * @author Sudar
7
+ * @package BulkDelete\License
8
+ */
9
+
10
+ defined( 'ABSPATH' ) || exit; // Exit if accessed directly
11
+
12
+ class BD_License {
13
+
14
+ /**
15
+ * Output addon page content
16
+ *
17
+ * @since 5.0
18
+ * @static
19
+ */
20
+ public static function display_addon_page() {
21
+ if ( ! class_exists( 'WP_List_Table' ) ) {
22
+ require_once ABSPATH . WPINC . '/class-wp-list-table.php';
23
+ }
24
+
25
+ if ( ! class_exists( 'License_List_Table' ) ) {
26
+ require_once Bulk_Delete::$PLUGIN_DIR . '/include/license/class-license-list-table.php';
27
+ }
28
+
29
+ $license_list_table = new License_List_Table();
30
+ $license_list_table->prepare_items();
31
+ ?>
32
+ <div class="wrap">
33
+ <h2><?php _e( 'Addon Licenses', 'bulk-delete' );?></h2>
34
+ <?php settings_errors(); ?>
35
+ <form method="post" action="options.php">
36
+ <?php
37
+ $license_list_table->display();
38
+ do_action( 'bd_license_form' );
39
+ bd_display_available_addon_list();
40
+ ?>
41
+ </form>
42
+ </div>
43
+ <?php
44
+ /**
45
+ * Runs just before displaying the footer text in the "Addon" admin page.
46
+ *
47
+ * This action is primarily for adding extra content in the footer of "Addon" admin page.
48
+ *
49
+ * @since 5.0
50
+ */
51
+ do_action( 'bd_admin_footer_addon_page' );
52
+ }
53
+
54
+ /**
55
+ * Display License form
56
+ *
57
+ * @since 5.0
58
+ * @static
59
+ */
60
+ public static function display_activate_license_form() {
61
+ $bd = BULK_DELETE();
62
+ if ( isset( $bd->display_activate_license_form ) && true === $bd->display_activate_license_form ) {
63
+ // This prints out all hidden setting fields
64
+ settings_fields( Bulk_Delete::SETTING_OPTION_GROUP );
65
+ do_settings_sections( Bulk_Delete::ADDON_PAGE_SLUG );
66
+ submit_button( __( 'Activate License', 'bulk-delete' ) );
67
+ }
68
+ }
69
+
70
+ /**
71
+ * Check if an addon has a valid license or not
72
+ *
73
+ * @since 5.0
74
+ * @static
75
+ * @param string $addon_name Addon Name
76
+ * @param string $addon_code Addon short Name
77
+ * @return bool True if addon has a valid license, False otherwise
78
+ */
79
+ public static function has_valid_license( $addon_name, $addon_code ) {
80
+ $key = Bulk_Delete::LICENSE_CACHE_KEY_PREFIX . $addon_code;
81
+ $license_data = get_option( $key, false );
82
+
83
+ if ( ! $license_data ) {
84
+ // if data about license is not present, then fetch it.
85
+ // ideally this should not happen
86
+ $licenses = get_option( Bulk_Delete::SETTING_OPTION_NAME );
87
+ if ( is_array( $licenses ) && key_exists( $addon_code, $licenses ) ) {
88
+ $license_data = BD_EDD_API_Wrapper::check_license( $addon_name, $licenses[ $addon_code ] );
89
+ update_option( $key, $license_data );
90
+ }
91
+ }
92
+
93
+ // TODO Encapsulate below code into a separate function
94
+ if ( $license_data && is_array( $license_data ) && key_exists( 'validity', $license_data ) ) {
95
+ if ( 'valid' == $license_data['validity'] ) {
96
+ if ( strtotime( 'now' ) < strtotime( $license_data['expires'] ) ) {
97
+ return true;
98
+ } else {
99
+ $license_data['validity'] = 'expired';
100
+ update_option( $key, $license_data );
101
+ }
102
+ }
103
+ }
104
+
105
+ return false;
106
+ }
107
+
108
+ /**
109
+ * Get the list of all licenses information to be displayed in the license page
110
+ *
111
+ * @since 5.0
112
+ * @static
113
+ * @return array $license_data License information
114
+ */
115
+ public static function get_licenses() {
116
+ $licenses = get_option( Bulk_Delete::SETTING_OPTION_NAME );
117
+ $license_data = array();
118
+
119
+ if ( is_array( $licenses ) ) {
120
+ foreach ( $licenses as $addon_code => $license ) {
121
+ $license_data[ $addon_code ] = self::get_license( $addon_code );
122
+ }
123
+ }
124
+
125
+ return $license_data;
126
+ }
127
+
128
+ /**
129
+ * Retrieve license information about an addon
130
+ *
131
+ * @since 5.0
132
+ * @static
133
+ * @param string $addon_code Addon short name
134
+ * @return object $license_data License information
135
+ */
136
+ public static function get_license( $addon_code ) {
137
+ $key = Bulk_Delete::LICENSE_CACHE_KEY_PREFIX . $addon_code;
138
+ $license_data = get_option( $key, false );
139
+
140
+ if ( $license_data && is_array( $license_data ) && key_exists( 'validity', $license_data ) ) {
141
+ if ( 'valid' == $license_data['validity'] ) {
142
+ if ( strtotime( 'now' ) < strtotime( $license_data['expires'] ) ) {
143
+ // valid license
144
+ } else {
145
+ $license_data['validity'] = 'expired';
146
+ update_option( $key, $license_data );
147
+ }
148
+ }
149
+ }
150
+
151
+ return $license_data;
152
+ }
153
+
154
+ /**
155
+ * Get license code of an addon
156
+ *
157
+ * @since 5.0
158
+ * @static
159
+ * @param string $addon_code Addon code
160
+ * @return bool|string License code of the addon, False otherwise
161
+ */
162
+ public static function get_license_code( $addon_code ) {
163
+ $licenses = get_option( Bulk_Delete::SETTING_OPTION_NAME );
164
+
165
+ if ( is_array( $licenses ) && key_exists( $addon_code, $licenses ) ) {
166
+ return $licenses[ $addon_code ];
167
+ }
168
+ else {
169
+ return false;
170
+ }
171
+ }
172
+
173
+ /**
174
+ * Deactivate license
175
+ *
176
+ * @since 5.0
177
+ * @static
178
+ */
179
+ public static function deactivate_license() {
180
+ if ( check_admin_referer( 'bd-deactivate-license', 'bd-deactivate-license-nonce' ) ) {
181
+ $msg = array( 'msg' => '', 'type' => 'error' );
182
+ $addon_code = $_GET['addon-code'];
183
+ $license_data = self::get_license( $addon_code );
184
+
185
+ $license = $license_data['license'];
186
+ $addon_name = $license_data['addon-name'];
187
+
188
+ $deactivated = BD_EDD_API_Wrapper::deactivate_license( $addon_name, $license );
189
+
190
+ if ( $deactivated ) {
191
+ self::delete_license_from_cache( $addon_code );
192
+ $msg['msg'] = sprintf( __( 'The license key for "%s" addon was successfully deactivated', 'bulk-delete' ), $addon_name );
193
+ $msg['type'] = 'updated';
194
+
195
+ } else {
196
+ self::validate_license( $addon_code, $addon_name );
197
+ $msg['msg'] = sprintf( __( 'There was some problem while trying to deactivate license key for "%s" addon. Kindly try again', 'bulk-delete' ), $addon_name );
198
+ }
199
+
200
+ add_settings_error(
201
+ Bulk_Delete::ADDON_PAGE_SLUG,
202
+ 'license-deactivation',
203
+ $msg['msg'],
204
+ $msg['type']
205
+ );
206
+ }
207
+ }
208
+
209
+ /**
210
+ * Delete license
211
+ *
212
+ * @since 5.0
213
+ * @static
214
+ */
215
+ public static function delete_license() {
216
+ if ( check_admin_referer( 'bd-deactivate-license', 'bd-deactivate-license-nonce' ) ) {
217
+ $msg = array( 'msg' => '', 'type' => 'updated' );
218
+ $addon_code = $_GET['addon-code'];
219
+
220
+ self::delete_license_from_cache( $addon_code );
221
+
222
+ $msg['msg'] = __( 'The license key was successfully deleted', 'bulk-delete' );
223
+
224
+ add_settings_error(
225
+ Bulk_Delete::ADDON_PAGE_SLUG,
226
+ 'license-deleted',
227
+ $msg['msg'],
228
+ $msg['type']
229
+ );
230
+ }
231
+ }
232
+
233
+ /**
234
+ * Delete license information from cache
235
+ *
236
+ * @since 5.0
237
+ * @static
238
+ * @param string $addon_code Addon code
239
+ */
240
+ private static function delete_license_from_cache( $addon_code ) {
241
+ $key = Bulk_Delete::LICENSE_CACHE_KEY_PREFIX . $addon_code;
242
+ delete_option( $key );
243
+
244
+ $licenses = get_option( Bulk_Delete::SETTING_OPTION_NAME );
245
+
246
+ if ( is_array( $licenses ) && key_exists( $addon_code, $licenses ) ) {
247
+ unset( $licenses[ $addon_code ] );
248
+ }
249
+ update_option( Bulk_Delete::SETTING_OPTION_NAME, $licenses );
250
+ }
251
+
252
+ /**
253
+ * Activate license
254
+ *
255
+ * @since 5.0
256
+ * @static
257
+ * @param string $addon_name Addon name
258
+ * @param string $addon_code Addon code
259
+ * @param string $license License code
260
+ * @return bool $valid True if valid, False otherwise
261
+ */
262
+ public static function activate_license( $addon_name, $addon_code, $license ) {
263
+ $license_data = BD_EDD_API_Wrapper::activate_license( $addon_name, $license );
264
+ $valid = false;
265
+ $msg = array(
266
+ 'msg' => sprintf( __( 'There was some problem in contacting our store to activate the license key for "%s" addon', 'bulk-delete' ), $addon_name ),
267
+ 'type' => 'error',
268
+ );
269
+
270
+ if ( $license_data && is_array( $license_data ) && key_exists( 'validity', $license_data ) ) {
271
+ if ( 'valid' == $license_data['validity'] ) {
272
+ $key = Bulk_Delete::LICENSE_CACHE_KEY_PREFIX . $addon_code;
273
+ $license_data['addon-code'] = $addon_code;
274
+ update_option( $key, $license_data );
275
+
276
+ $msg['msg'] = sprintf( __( 'The license key for "%s" addon was successfully activated. The addon will get updates automatically till the license key is valid.', 'bulk-delete' ), $addon_name );
277
+ $msg['type'] = 'updated';
278
+ $valid = true;
279
+ } else {
280
+ if ( key_exists( 'error', $license_data ) ) {
281
+ switch ( $license_data['error'] ) {
282
+
283
+ case 'no_activations_left':
284
+ $msg['msg'] = sprintf( __( 'The license key for "%s" addon doesn\'t have any more activations left. Kindly buy a new license.', 'bulk-delete' ), $addon_name );
285
+ break;
286
+
287
+ case 'revoked':
288
+ $msg['msg'] = sprintf( __( 'The license key for "%s" addon is revoked. Kindly buy a new license.', 'bulk-delete' ), $addon_name );
289
+ break;
290
+
291
+ case 'expired':
292
+ $msg['msg'] = sprintf( __( 'The license key for "%s" addon has expired. Kindly buy a new license.', 'bulk-delete' ), $addon_name );
293
+ break;
294
+
295
+ default:
296
+ $msg['msg'] = sprintf( __( 'The license key for "%s" addon is invalid', 'bulk-delete' ), $addon_name );
297
+ break;
298
+ }
299
+ }
300
+ }
301
+ }
302
+
303
+ add_settings_error(
304
+ Bulk_Delete::ADDON_PAGE_SLUG,
305
+ 'license-activation',
306
+ $msg['msg'],
307
+ $msg['type']
308
+ );
309
+
310
+ if ( ! $valid && isset( $key ) ) {
311
+ delete_option( $key );
312
+ }
313
+ return $valid;
314
+ }
315
+
316
+ /**
317
+ * Validate the license for the given addon
318
+ *
319
+ * @since 5.0
320
+ * @static
321
+ * @param string $addon_code Addon code
322
+ * @param string $addon_name Addon name
323
+ */
324
+ public static function validate_license( $addon_code, $addon_name ) {
325
+ $key = Bulk_Delete::LICENSE_CACHE_KEY_PREFIX . $addon_code;
326
+
327
+ $licenses = get_option( Bulk_Delete::SETTING_OPTION_NAME );
328
+ if ( is_array( $licenses ) && key_exists( $addon_code, $licenses ) ) {
329
+ $license_data = BD_EDD_API_Wrapper::check_license( $addon_name, $licenses[ $addon_code ] );
330
+ if ( $license_data ) {
331
+ $license_data['addon-code'] = $addon_code;
332
+ $license_data['addon-name'] = $license_data['item_name'];
333
+ update_option( $key, $license_data );
334
+ } else {
335
+ delete_option( $key );
336
+ }
337
+ }
338
+
339
+ if ( $license_data && is_array( $license_data ) && key_exists( 'validity', $license_data ) ) {
340
+ if ( 'valid' == $license_data['validity'] ) {
341
+ if ( strtotime( 'now' ) > strtotime( $license_data['expires'] ) ) {
342
+ $license_data['validity'] = 'expired';
343
+ update_option( $key, $license_data );
344
+ }
345
+ }
346
+ }
347
+ }
348
+ }
349
+
350
+ // hooks
351
+ add_action( 'bd_license_form' , array( 'BD_License', 'display_activate_license_form' ), 100 );
352
+ add_action( 'bd_deactivate_license', array( 'BD_License', 'deactivate_license' ) );
353
+ add_action( 'bd_delete_license' , array( 'BD_License', 'delete_license' ) );
354
+ add_action( 'bd_validate_license' , array( 'BD_License', 'validate_license' ), 10, 2 );
355
+ ?>
include/license/class-license-list-table.php ADDED
@@ -0,0 +1,171 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Table to show the list of addon licenses
4
+ *
5
+ * @since 5.0
6
+ * @author Sudar
7
+ * @package BulkDelete\Addon
8
+ */
9
+
10
+ defined( 'ABSPATH' ) || exit; // Exit if accessed directly
11
+
12
+ class License_List_Table extends WP_List_Table {
13
+
14
+ /**
15
+ * Constructor, setup labels
16
+ *
17
+ * @since 5.0
18
+ */
19
+ public function __construct() {
20
+ parent::__construct( array(
21
+ 'singular' => 'license_list', // Singular label
22
+ 'plural' => 'license_lists', // plural label, also this well be one of the table css class
23
+ 'ajax' => false, // We won't support Ajax for this table
24
+ )
25
+ );
26
+ }
27
+
28
+ /**
29
+ * Add extra markup in the toolbars before or after the list
30
+ *
31
+ * @since 5.0
32
+ * @param string $which Whether the markup should be after (bottom) or before (top) the list
33
+ */
34
+ public function extra_tablenav( $which ) {
35
+ if ( 'top' == $which ) {
36
+ echo '<p>';
37
+ _e( 'This is the list of addon license that are currently registered with the plugin.', 'bulk-delete' );
38
+ echo '</p>';
39
+ }
40
+ }
41
+
42
+ /**
43
+ * Define the list of columns that will be used in the table.
44
+ *
45
+ * @since 5.0
46
+ * @return array The list of columns in the table
47
+ */
48
+ public function get_columns() {
49
+ return array(
50
+ 'col_addon_name' => __( 'Addon Name', 'bulk-delete' ),
51
+ 'col_license' => __( 'License Code', 'bulk-delete' ),
52
+ 'col_license_validity' => __( 'Validity', 'bulk-delete' ),
53
+ 'col_expires' => __( 'Expires', 'bulk-delete' )
54
+ );
55
+ }
56
+
57
+ /**
58
+ * Defines columns that can be sorted
59
+ *
60
+ * @since 5.0
61
+ * @return array List of columns that can be sorted
62
+ */
63
+ public function get_sortable_columns() {
64
+ return array(
65
+ 'col_addon_name' => array( 'addon_name', false )
66
+ );
67
+ }
68
+
69
+ /**
70
+ * Prepare the table
71
+ *
72
+ * @since 5.0
73
+ */
74
+ public function prepare_items() {
75
+ $columns = $this->get_columns();
76
+ $hidden = array();
77
+ $sortable = $this->get_sortable_columns();
78
+
79
+ $this->_column_headers = array( $columns, $hidden, $sortable );
80
+
81
+ $this->items = BD_License::get_licenses();
82
+ }
83
+
84
+ /**
85
+ * Display the col_addon_name column
86
+ *
87
+ * @since 5.0
88
+ * @param array $item Single row of data
89
+ * @return string
90
+ */
91
+ public function column_col_addon_name( $item ) {
92
+ $validity = $item['validity'];
93
+ $action_label = __( 'Delete', 'bulk-delete' );
94
+ $action_name = 'delete_license';
95
+
96
+ if ( 'valid' == $validity ) {
97
+ $action_label = __( 'Deactivate', 'bulk-delete' );
98
+ $action_name = 'deactivate_license';
99
+ }
100
+
101
+ // Build row actions
102
+ $actions = array(
103
+ 'deactivate' => sprintf( '<a href="?page=%s&bd_action=%s&addon-code=%s&%s=%s">%s</a>',
104
+ $_REQUEST['page'],
105
+ $action_name,
106
+ $item['addon-code'],
107
+ 'bd-deactivate-license-nonce',
108
+ wp_create_nonce( 'bd-deactivate-license' ),
109
+ $action_label
110
+ ),
111
+ );
112
+
113
+ // Return the title contents
114
+ return sprintf( '%1$s%2$s',
115
+ /*$1%s*/ $item['addon-name'],
116
+ /*$2%s*/ $this->row_actions( $actions )
117
+ );
118
+ }
119
+
120
+ /**
121
+ * Display the col_license column
122
+ *
123
+ * @since 5.0
124
+ * @param array $item Single row of data
125
+ * @return string
126
+ */
127
+ public function column_col_license( $item ) {
128
+ return $item['license'];
129
+ }
130
+
131
+ /**
132
+ * Display the col_license_validity column
133
+ *
134
+ * @since 5.0
135
+ * @param array $item Single row of data
136
+ * @return string
137
+ */
138
+ public function column_col_license_validity( $item ) {
139
+ $validity = $item['validity'];
140
+ if ( 'valid' == $validity ) {
141
+ return '<span style="color:green;">' . $validity . '</span>';
142
+ } else {
143
+ return '<span style="color:red;">' . $validity . '</span>';
144
+ }
145
+ }
146
+
147
+ /**
148
+ * Display the col_expires column
149
+ *
150
+ * @since 5.0
151
+ * @param array $item Single row of data
152
+ * @return string
153
+ */
154
+ public function column_col_expires( $item ) {
155
+ if ( key_exists( 'expires', $item ) ) {
156
+ return $item['expires'];
157
+ } else {
158
+ return __( 'N/A', 'bulk-delete' );
159
+ }
160
+ }
161
+
162
+ /**
163
+ * Define the message that will be shown when the table is empty
164
+ *
165
+ * @since 5.0
166
+ */
167
+ public function no_items() {
168
+ _e( "You don't have any valid addon license yet.", 'bulk-delete' );
169
+ }
170
+ }
171
+ ?>
include/meta/class-bulk-delete-comment-meta.php CHANGED
@@ -2,70 +2,73 @@
2
  /**
3
  * Utility class for deleting Comment Meta.
4
  *
5
- * @package Bulk_Delete
6
- * @subpackage meta
7
- * @author Sudar
8
  * @since 5.4
 
 
9
  */
 
 
10
  class Bulk_Delete_Comment_Meta {
11
 
12
- /**
13
- * Box slug.
14
- * @since 5.4
15
- */
16
- const BOX_COMMENT_META = 'bd-comment-meta';
17
-
18
- /**
19
- * Cron Hook.
20
- * @since 5.4
21
- */
22
- const CRON_HOOK = 'do-bulk-delete-comment-meta';
23
-
24
- /**
25
- * Register comment-meta meta box for delete meta page.
26
- *
27
- * @static
28
- * @since 5.4
29
- */
30
- public static function add_delete_comment_meta_box() {
31
- $bd = BULK_DELETE();
32
-
33
- add_meta_box(
34
- self::BOX_COMMENT_META,
35
- __( 'Bulk Delete Comment Meta', 'bulk-delete' ),
36
- array( __CLASS__, 'render_delete_comment_meta_box' ),
37
- $bd->meta_page,
38
- 'advanced'
39
- );
40
- }
41
-
42
- /**
43
- * Render delete comment-meta meta box for delete meta page.
44
- *
45
- * @static
46
- * @since 5.4
47
- */
48
- public static function render_delete_comment_meta_box() {
49
- if ( Bulk_Delete_Meta::is_meta_box_hidden( self::BOX_COMMENT_META ) ) {
50
- printf( __( 'This section just got enabled. Kindly <a href = "%1$s">refresh</a> the page to fully enable it.', 'bulk-delete' ), 'admin.php?page=' . Bulk_Delete_meta::META_PAGE_SLUG );
51
- return;
52
- }
 
 
53
  ?>
54
  <!-- Comment Meta box start-->
55
  <fieldset class="options">
56
  <?php
57
- $types = get_post_types( array(
58
- 'public' => true,
59
- '_builtin' => false,
60
- ), 'names'
61
- );
62
 
63
- array_unshift( $types, 'post' );
64
  ?>
65
  <h4><?php _e( 'Select the post type whose comment meta fields you want to delete', 'bulk-delete' ); ?></h4>
66
  <table class="optiontable">
67
  <?php
68
- foreach ( $types as $type ) {
69
  ?>
70
  <tr>
71
  <td>
@@ -74,7 +77,7 @@ class Bulk_Delete_Comment_Meta {
74
  </td>
75
  </tr>
76
  <?php
77
- }
78
  ?>
79
  </table>
80
 
@@ -105,13 +108,13 @@ class Bulk_Delete_Comment_Meta {
105
  </tr>
106
  </table>
107
  <?php
108
- /**
109
- * Add more fields to the delete comment meta field form.
110
- * This hook can be used to add more fields to the delete comment meta field form
111
- *
112
- * @since 5.4
113
- */
114
- do_action( 'bd_delete_comment_meta_form' );
115
  ?>
116
  <table class="optiontable">
117
  <tr>
@@ -128,7 +131,7 @@ class Bulk_Delete_Comment_Meta {
128
  <option value ="before"><?php _e( 'older than', 'bulk-delete' );?></option>
129
  <option value ="after"><?php _e( 'commented within last', 'bulk-delete' );?></option>
130
  </select>
131
- <input type ="textbox" name="smbd_cm_days" id="smbd_cm_days" disabled value ="0" maxlength="4" size="4"><?php _e( 'days', 'bulk-delete' );?>
132
  </td>
133
  </tr>
134
 
@@ -136,7 +139,7 @@ class Bulk_Delete_Comment_Meta {
136
  <td>
137
  <input name="smbd_cm_limit" id="smbd_cm_limit" value = "true" type = "checkbox">
138
  <?php _e( 'Only delete comment meta field from first ', 'bulk-delete' );?>
139
- <input type ="textbox" name="smbd_cm_limit_to" id="smbd_cm_limit_to" disabled value ="0" maxlength="4" size="4"><?php _e( 'comments.', 'bulk-delete' );?>
140
  <?php _e( 'Use this option if there are more than 1000 posts and the script timesout.', 'bulk-delete' ) ?>
141
  </td>
142
  </tr>
@@ -149,12 +152,12 @@ class Bulk_Delete_Comment_Meta {
149
  <select name="smbd_cm_cron_freq" id="smbd_cm_cron_freq" disabled>
150
  <option value = "-1"><?php _e( "Don't repeat", 'bulk-delete' ); ?></option>
151
  <?php
152
- $schedules = wp_get_schedules();
153
- foreach ( $schedules as $key => $value ) {
154
  ?>
155
  <option value = "<?php echo $key; ?>"><?php echo $value['display']; ?></option>
156
  <?php
157
- }
158
  ?>
159
  </select>
160
  <span class="bd-cm-pro" style="color:red">
@@ -177,128 +180,127 @@ class Bulk_Delete_Comment_Meta {
177
  </p>
178
  <!-- Comment Meta box end-->
179
  <?php
180
- }
181
-
182
- /**
183
- * Filter JS Array and add validation hooks.
184
- *
185
- * @since 5.4
186
- * @static
187
- * @param array $js_array JavaScript Array
188
- * @return array Modified JavaScript Array
189
- */
190
- public static function filter_js_array( $js_array ) {
191
- $js_array['dt_iterators'][] = '_cm';
192
- $js_array['validators']['delete_meta_comment'] = 'noValidation';
193
-
194
- $js_array['pre_action_msg']['delete_meta_comment'] = 'deleteCMWarning';
195
- $js_array['msg']['deleteCMWarning'] = __( 'Are you sure you want to delete all the comment meta fields that match the selected filters?', 'bulk-delete' );
196
-
197
- return $js_array;
198
- }
199
-
200
- /**
201
- * Controller for deleting comment meta fields.
202
- *
203
- * @static
204
- * @since 5.4
205
- */
206
- public static function do_delete_comment_meta() {
207
- $delete_options = array();
208
- $delete_options['post_type'] = esc_sql( array_get( $_POST, 'smbd_cm_post_type', 'post' ) );
209
-
210
- $delete_options['use_value'] = array_get_bool( $_POST, 'smbd_cm_use_value', FALSE );
211
- $delete_options['meta_key'] = esc_sql( array_get( $_POST, 'smbd_cm_key', '' ) );
212
-
213
- $delete_options['limit_to'] = absint( array_get( $_POST, 'smbd_cm_limit_to', 0 ) );
214
-
215
- $delete_options['restrict'] = array_get_bool( $_POST, 'smbd_cm_restrict', FALSE );
216
- $delete_options['op'] = esc_sql( array_get( $_POST, 'smbd_cm_op', 'before' ) );
217
- $delete_options['days'] = absint( array_get( $_POST, 'smbd_cm_days', 0 ) );
218
-
219
- /**
220
- * Delete comment-meta delete options filter.
221
- * This filter is for processing filtering options for deleting comment meta
222
- *
223
- * @since 5.4
224
- */
225
- $delete_options = apply_filters( 'bd_delete_comment_meta_options', $delete_options, $_POST );
226
-
227
- if ( array_get( $_POST, 'smbd_cm_cron', 'false' ) == 'true' ) {
228
- $freq = $_POST['smbd_cm_cron_freq'];
229
- $time = strtotime( $_POST['smbd_cm_cron_start'] ) - ( get_option( 'gmt_offset' ) * 60 * 60 );
230
-
231
- if ( $freq == -1 ) {
232
- wp_schedule_single_event( $time, self::CRON_HOOK, array( $delete_options ) );
233
- } else {
234
- wp_schedule_event( $time, $freq, self::CRON_HOOK, array( $delete_options ) );
235
- }
236
- $msg = __( 'Comment meta fields from the comments with the selected criteria are scheduled for deletion.', 'bulk-delete' ) . ' ' .
237
- sprintf( __( 'See the full list of <a href = "%s">scheduled tasks</a>' , 'bulk-delete' ), get_bloginfo( 'wpurl' ) . '/wp-admin/admin.php?page=' . Bulk_Delete::CRON_PAGE_SLUG );
238
- } else {
239
- $deleted_count = self::delete_comment_meta( $delete_options );
240
- $msg = sprintf( _n( 'Deleted comment meta field from %d comment', 'Deleted comment meta field from %d comments' , $deleted_count, 'bulk-delete' ), $deleted_count );
241
- }
242
-
243
- add_settings_error(
244
- Bulk_Delete_Meta::META_PAGE_SLUG,
245
- 'deleted-comments',
246
- $msg,
247
- 'updated'
248
- );
249
- }
250
-
251
- /**
252
- * Delete Comment Meta.
253
- *
254
- * @static
255
- * @since 5.4
256
- * @param array $delete_options Options for deleting
257
- * @return int Number of comments that were deleted
258
- */
259
- public static function delete_comment_meta( $delete_options ) {
260
- $count = 0;
261
- $post_type = $delete_options['post_type'];
262
- $limit_to = $delete_options['limit_to'];
263
- $meta_key = $delete_options['meta_key'];
264
- $use_value = $delete_options['use_value'];
265
- $restrict = $delete_options['restrict'];
266
- $days = $delete_options['days'];
267
- $op = $delete_options['op'];
268
-
269
- $options = array(
270
- 'post_type' => $post_type,
271
- );
272
-
273
- if ( $limit_to > 0 ) {
274
- $options['number'] = $limit_to;
275
- }
276
-
277
- if ( $restrict ) {
278
- $options['date_query'] = array(
279
- array(
280
- 'column' => 'comment_date',
281
- $op => "{$days} day ago",
282
- ),
283
- );
284
- }
285
-
286
- if ( $use_value ) {
287
- $meta_value = $delete_options['meta_value'];
288
- $options['meta_query'] = apply_filters( 'bd_delete_comment_meta_query', array(), $delete_options );
289
- } else {
290
- $options['meta_key'] = $meta_key;
291
- }
292
-
293
- $comments = get_comments( $options );
294
-
295
- foreach ( $comments as $comment ) {
296
- if ( delete_comment_meta( $comment->comment_ID, $meta_key ) ) {
297
- $count++;
298
- }
299
- }
300
- return $count;
301
- }
302
  }
303
 
304
  // hooks
2
  /**
3
  * Utility class for deleting Comment Meta.
4
  *
 
 
 
5
  * @since 5.4
6
+ * @author Sudar
7
+ * @package BulkDelete\Meta
8
  */
9
+
10
+
11
  class Bulk_Delete_Comment_Meta {
12
 
13
+ /**
14
+ * Box slug.
15
+ *
16
+ * @since 5.4
17
+ */
18
+ const BOX_COMMENT_META = 'bd-comment-meta';
19
+
20
+ /**
21
+ * Cron Hook.
22
+ *
23
+ * @since 5.4
24
+ */
25
+ const CRON_HOOK = 'do-bulk-delete-comment-meta';
26
+
27
+ /**
28
+ * Register comment-meta meta box for delete meta page.
29
+ *
30
+ * @static
31
+ * @since 5.4
32
+ */
33
+ public static function add_delete_comment_meta_box() {
34
+ $bd = BULK_DELETE();
35
+
36
+ add_meta_box(
37
+ self::BOX_COMMENT_META,
38
+ __( 'Bulk Delete Comment Meta', 'bulk-delete' ),
39
+ array( __CLASS__, 'render_delete_comment_meta_box' ),
40
+ $bd->meta_page,
41
+ 'advanced'
42
+ );
43
+ }
44
+
45
+ /**
46
+ * Render delete comment-meta meta box for delete meta page.
47
+ *
48
+ * @static
49
+ * @since 5.4
50
+ */
51
+ public static function render_delete_comment_meta_box() {
52
+ if ( Bulk_Delete_Meta::is_meta_box_hidden( self::BOX_COMMENT_META ) ) {
53
+ printf( __( 'This section just got enabled. Kindly <a href = "%1$s">refresh</a> the page to fully enable it.', 'bulk-delete' ), 'admin.php?page=' . Bulk_Delete_meta::META_PAGE_SLUG );
54
+ return;
55
+ }
56
  ?>
57
  <!-- Comment Meta box start-->
58
  <fieldset class="options">
59
  <?php
60
+ $types = get_post_types( array(
61
+ 'public' => true,
62
+ '_builtin' => false,
63
+ ), 'names'
64
+ );
65
 
66
+ array_unshift( $types, 'post' );
67
  ?>
68
  <h4><?php _e( 'Select the post type whose comment meta fields you want to delete', 'bulk-delete' ); ?></h4>
69
  <table class="optiontable">
70
  <?php
71
+ foreach ( $types as $type ) {
72
  ?>
73
  <tr>
74
  <td>
77
  </td>
78
  </tr>
79
  <?php
80
+ }
81
  ?>
82
  </table>
83
 
108
  </tr>
109
  </table>
110
  <?php
111
+ /**
112
+ * Add more fields to the delete comment meta field form.
113
+ * This hook can be used to add more fields to the delete comment meta field form
114
+ *
115
+ * @since 5.4
116
+ */
117
+ do_action( 'bd_delete_comment_meta_form' );
118
  ?>
119
  <table class="optiontable">
120
  <tr>
131
  <option value ="before"><?php _e( 'older than', 'bulk-delete' );?></option>
132
  <option value ="after"><?php _e( 'commented within last', 'bulk-delete' );?></option>
133
  </select>
134
+ <input type="number" name="smbd_cm_days" id="smbd_cm_days" disabled value ="0" maxlength="4" size="4"><?php _e( 'days', 'bulk-delete' );?>
135
  </td>
136
  </tr>
137
 
139
  <td>
140
  <input name="smbd_cm_limit" id="smbd_cm_limit" value = "true" type = "checkbox">
141
  <?php _e( 'Only delete comment meta field from first ', 'bulk-delete' );?>
142
+ <input type="number" name="smbd_cm_limit_to" id="smbd_cm_limit_to" disabled value ="0" maxlength="4" size="4"><?php _e( 'comments.', 'bulk-delete' );?>
143
  <?php _e( 'Use this option if there are more than 1000 posts and the script timesout.', 'bulk-delete' ) ?>
144
  </td>
145
  </tr>
152
  <select name="smbd_cm_cron_freq" id="smbd_cm_cron_freq" disabled>
153
  <option value = "-1"><?php _e( "Don't repeat", 'bulk-delete' ); ?></option>
154
  <?php
155
+ $schedules = wp_get_schedules();
156
+ foreach ( $schedules as $key => $value ) {
157
  ?>
158
  <option value = "<?php echo $key; ?>"><?php echo $value['display']; ?></option>
159
  <?php
160
+ }
161
  ?>
162
  </select>
163
  <span class="bd-cm-pro" style="color:red">
180
  </p>
181
  <!-- Comment Meta box end-->
182
  <?php
183
+ }
184
+
185
+ /**
186
+ * Filter JS Array and add validation hooks.
187
+ *
188
+ * @since 5.4
189
+ * @static
190
+ * @param array $js_array JavaScript Array
191
+ * @return array Modified JavaScript Array
192
+ */
193
+ public static function filter_js_array( $js_array ) {
194
+ $js_array['dt_iterators'][] = '_cm';
195
+ $js_array['validators']['delete_meta_comment'] = 'noValidation';
196
+
197
+ $js_array['pre_action_msg']['delete_meta_comment'] = 'deleteCMWarning';
198
+ $js_array['msg']['deleteCMWarning'] = __( 'Are you sure you want to delete all the comment meta fields that match the selected filters?', 'bulk-delete' );
199
+
200
+ return $js_array;
201
+ }
202
+
203
+ /**
204
+ * Controller for deleting comment meta fields.
205
+ *
206
+ * @static
207
+ * @since 5.4
208
+ */
209
+ public static function do_delete_comment_meta() {
210
+ $delete_options = array();
211
+ $delete_options['post_type'] = esc_sql( array_get( $_POST, 'smbd_cm_post_type', 'post' ) );
212
+
213
+ $delete_options['use_value'] = array_get_bool( $_POST, 'smbd_cm_use_value', false );
214
+ $delete_options['meta_key'] = esc_sql( array_get( $_POST, 'smbd_cm_key', '' ) );
215
+
216
+ $delete_options['limit_to'] = absint( array_get( $_POST, 'smbd_cm_limit_to', 0 ) );
217
+
218
+ $delete_options['restrict'] = array_get_bool( $_POST, 'smbd_cm_restrict', false );
219
+ $delete_options['op'] = esc_sql( array_get( $_POST, 'smbd_cm_op', 'before' ) );
220
+ $delete_options['days'] = absint( array_get( $_POST, 'smbd_cm_days', 0 ) );
221
+
222
+ /**
223
+ * Delete comment-meta delete options filter.
224
+ * This filter is for processing filtering options for deleting comment meta
225
+ *
226
+ * @since 5.4
227
+ */
228
+ $delete_options = apply_filters( 'bd_delete_comment_meta_options', $delete_options, $_POST );
229
+
230
+ if ( 'true' == array_get( $_POST, 'smbd_cm_cron', 'false' ) ) {
231
+ $freq = $_POST['smbd_cm_cron_freq'];
232
+ $time = strtotime( $_POST['smbd_cm_cron_start'] ) - ( get_option( 'gmt_offset' ) * 60 * 60 );
233
+
234
+ if ( $freq == -1 ) {
235
+ wp_schedule_single_event( $time, self::CRON_HOOK, array( $delete_options ) );
236
+ } else {
237
+ wp_schedule_event( $time, $freq, self::CRON_HOOK, array( $delete_options ) );
238
+ }
239
+ $msg = __( 'Comment meta fields from the comments with the selected criteria are scheduled for deletion.', 'bulk-delete' ) . ' ' .
240
+ sprintf( __( 'See the full list of <a href = "%s">scheduled tasks</a>' , 'bulk-delete' ), get_bloginfo( 'wpurl' ) . '/wp-admin/admin.php?page=' . Bulk_Delete::CRON_PAGE_SLUG );
241
+ } else {
242
+ $deleted_count = self::delete_comment_meta( $delete_options );
243
+ $msg = sprintf( _n( 'Deleted comment meta field from %d comment', 'Deleted comment meta field from %d comments' , $deleted_count, 'bulk-delete' ), $deleted_count );
244
+ }
245
+
246
+ add_settings_error(
247
+ Bulk_Delete_Meta::META_PAGE_SLUG,
248
+ 'deleted-comments',
249
+ $msg,
250
+ 'updated'
251
+ );
252
+ }
253
+
254
+ /**
255
+ * Delete Comment Meta.
256
+ *
257
+ * @static
258
+ * @since 5.4
259
+ * @param array $delete_options Options for deleting
260
+ * @return int Number of comments that were deleted
261
+ */
262
+ public static function delete_comment_meta( $delete_options ) {
263
+ $count = 0;
264
+ $post_type = $delete_options['post_type'];
265
+ $limit_to = $delete_options['limit_to'];
266
+ $meta_key = $delete_options['meta_key'];
267
+ $use_value = $delete_options['use_value'];
268
+ $restrict = $delete_options['restrict'];
269
+ $days = $delete_options['days'];
270
+ $op = $delete_options['op'];
271
+
272
+ $options = array(
273
+ 'post_type' => $post_type,
274
+ );
275
+
276
+ if ( $limit_to > 0 ) {
277
+ $options['number'] = $limit_to;
278
+ }
279
+
280
+ if ( $restrict ) {
281
+ $options['date_query'] = array(
282
+ array(
283
+ 'column' => 'comment_date',
284
+ $op => "{$days} day ago",
285
+ ),
286
+ );
287
+ }
288
+
289
+ if ( $use_value ) {
290
+ $options['meta_query'] = apply_filters( 'bd_delete_comment_meta_query', array(), $delete_options );
291
+ } else {
292
+ $options['meta_key'] = $meta_key;
293
+ }
294
+
295
+ $comments = get_comments( $options );
296
+
297
+ foreach ( $comments as $comment ) {
298
+ if ( delete_comment_meta( $comment->comment_ID, $meta_key ) ) {
299
+ $count++;
300
+ }
301
+ }
302
+ return $count;
303
+ }
 
304
  }
305
 
306
  // hooks
include/meta/class-bulk-delete-meta.php CHANGED
@@ -2,97 +2,102 @@
2
  /**
3
  * Utility class for deleting Meta Fields.
4
  *
5
- * @package Bulk_Delete
6
- * @subpackage Meta
7
- * @author Sudar
8
  * @since 5.4
 
 
9
  */
 
 
 
10
  class Bulk_Delete_Meta {
11
 
12
- /**
13
- * Slug for *meta* page.
14
- * @since 5.4
15
- */
16
- const META_PAGE_SLUG = 'bulk-delete-meta';
17
-
18
- /**
19
- * User meta that stores box preferences.
20
- * @since 5.4
21
- */
22
- const VISIBLE_META_BOXES = 'metaboxhidden_bulk-delete_page_bulk-delete-meta';
23
-
24
- /**
25
- * Add *meta* menu.
26
- *
27
- * @static
28
- * @since 5.4
29
- */
30
- public static function add_menu() {
31
- $bd = BULK_DELETE();
32
-
33
- $bd->meta_page = add_submenu_page(
34
- Bulk_Delete::POSTS_PAGE_SLUG,
35
- __( 'Bulk Delete Meta Fields', 'bulk-delete' ),
36
- __( 'Bulk Delete Meta Fields', 'bulk-delete' ),
37
- 'delete_posts',
38
- self::META_PAGE_SLUG,
39
- array( __CLASS__, 'display_meta_page' )
40
- );
41
-
42
- // enqueue JavaScript
43
- add_action( 'admin_print_scripts-' . $bd->meta_page, array( $bd, 'add_script') );
44
-
45
- // delete menus page
 
 
46
  add_action( "load-{$bd->meta_page}", array( __CLASS__, 'add_delete_meta_settings_panel' ) );
47
- add_action( "add_meta_boxes_{$bd->meta_page}", array( __CLASS__, 'add_delete_meta_meta_boxes' ) );
48
- }
49
-
50
- /**
51
- * Add settings Panel for delete meta page.
52
- *
53
- * @static
54
- * @since 5.4
55
- */
56
- public static function add_delete_meta_settings_panel() {
57
- $bd = BULK_DELETE();
58
-
59
- /**
60
- * Add contextual help for admin screens.
61
- *
62
- * @since 5.4
63
- */
64
- do_action( 'bd_add_contextual_help', $bd->meta_page );
65
-
66
- /* Trigger the add_meta_boxes hooks to allow meta boxes to be added */
67
- do_action( 'add_meta_boxes_' . $bd->meta_page, null );
68
-
69
- /* Enqueue WordPress' script for handling the meta boxes */
70
- wp_enqueue_script( 'postbox' );
71
- }
72
-
73
- /**
74
- * Register meta boxes for delete meta page.
75
- *
76
- * @static
77
- * @since 5.4
78
- */
79
- public static function add_delete_meta_meta_boxes() {
80
- /**
81
- * Add meta box in meta page.
82
- * This hook can be used for adding additional meta boxes in *meta* page
83
- *
84
- * @since 5.4
85
- */
86
- do_action( 'bd_add_meta_box_for_meta' );
87
- }
88
-
89
- /**
90
- * Show the delete meta page.
91
- *
92
- * @static
93
- * @since 5.4
94
- */
95
- public static function display_meta_page() {
 
96
  ?>
97
  <div class="wrap">
98
  <h2><?php _e( 'Bulk Delete Meta Fields', 'bulk-delete' );?></h2>
@@ -100,16 +105,16 @@ class Bulk_Delete_Meta {
100
 
101
  <form method = "post">
102
  <?php
103
- wp_nonce_field( 'sm-bulk-delete-meta', 'sm-bulk-delete-meta-nonce' );
104
 
105
- /* Used to save closed meta boxes and their order */
106
- wp_nonce_field( 'meta-box-order', 'meta-box-order-nonce', false );
107
- wp_nonce_field( 'closedpostboxes', 'closedpostboxesnonce', false );
108
  ?>
109
  <div id = "poststuff">
110
  <div id="post-body" class="metabox-holder columns-2">
111
 
112
- <div class="updated" >
113
  <p><strong><?php _e( 'WARNING: Items deleted once cannot be retrieved back. Use with caution.', 'bulk-delete' ); ?></strong></p>
114
  </div>
115
 
@@ -126,41 +131,41 @@ class Bulk_Delete_Meta {
126
  </form>
127
  </div><!-- .wrap -->
128
  <?php
129
- /**
130
- * Runs just before displaying the footer text in the "Bulk Delete Meta" admin page.
131
- * This action is primarily for adding extra content in the footer of "Bulk Delete Meta" admin page.
132
- *
133
- * @since 5.4
134
- */
135
- do_action( 'bd_admin_footer_meta_page' );
136
- }
137
-
138
- /**
139
- * Check whether the meta box in meta page is hidden or not.
140
- *
141
- * @static
142
- * @access private
143
- * @since 5.4
144
- * @param string $box The name of the box to check
145
- * @return bool True if the box is hidden, False otherwise
146
- */
147
- public static function is_meta_box_hidden( $box ) {
148
- $hidden_boxes = self::get_meta_hidden_boxes();
149
- return ( is_array( $hidden_boxes ) && in_array( $box, $hidden_boxes ) );
150
- }
151
-
152
- /**
153
- * Get the list of hidden boxes in meta page.
154
- *
155
- * @static
156
- * @access private
157
- * @since 5.4
158
- * @return array The array of hidden meta boxes
159
- */
160
- private static function get_meta_hidden_boxes() {
161
- $current_user = wp_get_current_user();
162
- return get_user_meta( $current_user->ID, self::VISIBLE_META_BOXES, TRUE );
163
- }
164
  }
165
 
166
  // Add menu
2
  /**
3
  * Utility class for deleting Meta Fields.
4
  *
 
 
 
5
  * @since 5.4
6
+ * @author Sudar
7
+ * @package BulkDelete\Meta
8
  */
9
+
10
+ defined( 'ABSPATH' ) || exit; // Exit if accessed directly
11
+
12
  class Bulk_Delete_Meta {
13
 
14
+ /**
15
+ * Slug for *meta* page.
16
+ *
17
+ * @since 5.4
18
+ */
19
+ const META_PAGE_SLUG = 'bulk-delete-meta';
20
+
21
+ /**
22
+ * User meta that stores box preferences.
23
+ *
24
+ * @since 5.4
25
+ */
26
+ const VISIBLE_META_BOXES = 'metaboxhidden_bulk-delete_page_bulk-delete-meta';
27
+
28
+ /**
29
+ * Add *meta* menu.
30
+ *
31
+ * @static
32
+ * @since 5.4
33
+ */
34
+ public static function add_menu() {
35
+ $bd = BULK_DELETE();
36
+
37
+ $bd->meta_page = add_submenu_page(
38
+ Bulk_Delete::POSTS_PAGE_SLUG,
39
+ __( 'Bulk Delete Meta Fields', 'bulk-delete' ),
40
+ __( 'Bulk Delete Meta Fields', 'bulk-delete' ),
41
+ 'delete_posts',
42
+ self::META_PAGE_SLUG,
43
+ array( __CLASS__, 'display_meta_page' )
44
+ );
45
+
46
+ // enqueue JavaScript
47
+ add_action( 'admin_print_scripts-' . $bd->meta_page, array( $bd, 'add_script' ) );
48
+
49
+ // delete menus page
50
  add_action( "load-{$bd->meta_page}", array( __CLASS__, 'add_delete_meta_settings_panel' ) );
51
+ add_action( "add_meta_boxes_{$bd->meta_page}", array( __CLASS__, 'add_delete_meta_meta_boxes' ) );
52
+ }
53
+
54
+ /**
55
+ * Add settings Panel for delete meta page.
56
+ *
57
+ * @static
58
+ * @since 5.4
59
+ */
60
+ public static function add_delete_meta_settings_panel() {
61
+ $bd = BULK_DELETE();
62
+
63
+ /**
64
+ * Add contextual help for admin screens.
65
+ *
66
+ * @since 5.4
67
+ */
68
+ do_action( 'bd_add_contextual_help', $bd->meta_page );
69
+
70
+ /* Trigger the add_meta_boxes hooks to allow meta boxes to be added */
71
+ do_action( 'add_meta_boxes_' . $bd->meta_page, null );
72
+
73
+ /* Enqueue WordPress' script for handling the meta boxes */
74
+ wp_enqueue_script( 'postbox' );
75
+ }
76
+
77
+ /**
78
+ * Register meta boxes for delete meta page.
79
+ *
80
+ * @static
81
+ * @since 5.4
82
+ */
83
+ public static function add_delete_meta_meta_boxes() {
84
+
85
+ /**
86
+ * Add meta box in meta page.
87
+ * This hook can be used for adding additional meta boxes in *meta* page
88
+ *
89
+ * @since 5.4
90
+ */
91
+ do_action( 'bd_add_meta_box_for_meta' );
92
+ }
93
+
94
+ /**
95
+ * Show the delete meta page.
96
+ *
97
+ * @static
98
+ * @since 5.4
99
+ */
100
+ public static function display_meta_page() {
101
  ?>
102
  <div class="wrap">
103
  <h2><?php _e( 'Bulk Delete Meta Fields', 'bulk-delete' );?></h2>
105
 
106
  <form method = "post">
107
  <?php
108
+ wp_nonce_field( 'sm-bulk-delete-meta', 'sm-bulk-delete-meta-nonce' );
109
 
110
+ /* Used to save closed meta boxes and their order */
111
+ wp_nonce_field( 'meta-box-order', 'meta-box-order-nonce', false );
112
+ wp_nonce_field( 'closedpostboxes', 'closedpostboxesnonce', false );
113
  ?>
114
  <div id = "poststuff">
115
  <div id="post-body" class="metabox-holder columns-2">
116
 
117
+ <div class="notice notice-warning">
118
  <p><strong><?php _e( 'WARNING: Items deleted once cannot be retrieved back. Use with caution.', 'bulk-delete' ); ?></strong></p>
119
  </div>
120
 
131
  </form>
132
  </div><!-- .wrap -->
133
  <?php
134
+ /**
135
+ * Runs just before displaying the footer text in the "Bulk Delete Meta" admin page.
136
+ * This action is primarily for adding extra content in the footer of "Bulk Delete Meta" admin page.
137
+ *
138
+ * @since 5.4
139
+ */
140
+ do_action( 'bd_admin_footer_meta_page' );
141
+ }
142
+
143
+ /**
144
+ * Check whether the meta box in meta page is hidden or not.
145
+ *
146
+ * @static
147
+ * @access private
148
+ * @since 5.4
149
+ * @param string $box The name of the box to check
150
+ * @return bool True if the box is hidden, False otherwise
151
+ */
152
+ public static function is_meta_box_hidden( $box ) {
153
+ $hidden_boxes = self::get_meta_hidden_boxes();
154
+ return is_array( $hidden_boxes ) && in_array( $box, $hidden_boxes );
155
+ }
156
+
157
+ /**
158
+ * Get the list of hidden boxes in meta page.
159
+ *
160
+ * @static
161
+ * @access private
162
+ * @since 5.4
163
+ * @return array The array of hidden meta boxes
164
+ */
165
+ private static function get_meta_hidden_boxes() {
166
+ $current_user = wp_get_current_user();
167
+ return get_user_meta( $current_user->ID, self::VISIBLE_META_BOXES, true );
168
+ }
169
  }
170
 
171
  // Add menu
include/meta/class-bulk-delete-post-meta.php CHANGED
@@ -2,70 +2,73 @@
2
  /**
3
  * Utility class for deleting Post Meta.
4
  *
5
- * @package Bulk_Delete
6
- * @subpackage meta
7
- * @author Sudar
8
  * @since 5.4
 
 
9
  */
 
 
10
  class Bulk_Delete_Post_Meta {
11
 
12
- /**
13
- * Box slug.
14
- * @since 5.4
15
- */
16
- const BOX_POST_META = 'bd-post-meta';
17
-
18
- /**
19
- * Cron Hook.
20
- * @since 5.4
21
- */
22
- const CRON_HOOK = 'do-bulk-delete-post-meta';
23
-
24
- /**
25
- * Register post-meta meta box for delete meta page.
26
- *
27
- * @static
28
- * @since 5.4
29
- */
30
- public static function add_delete_post_meta_box() {
31
- $bd = BULK_DELETE();
32
-
33
- add_meta_box(
34
- self::BOX_POST_META,
35
- __( 'Bulk Delete Post Meta', 'bulk-delete' ),
36
- array( __CLASS__, 'render_delete_post_meta_box' ),
37
- $bd->meta_page,
38
- 'advanced'
39
- );
40
- }
41
-
42
- /**
43
- * Render delete post-meta meta box for delete meta page.
44
- *
45
- * @static
46
- * @since 5.4
47
- */
48
- public static function render_delete_post_meta_box() {
49
- if ( Bulk_Delete_Meta::is_meta_box_hidden( self::BOX_POST_META ) ) {
50
- printf( __( 'This section just got enabled. Kindly <a href = "%1$s">refresh</a> the page to fully enable it.', 'bulk-delete' ), 'admin.php?page=' . Bulk_Delete_meta::META_PAGE_SLUG );
51
- return;
52
- }
 
 
53
  ?>
54
  <!-- Post Meta box start-->
55
  <fieldset class="options">
56
  <?php
57
- $types = get_post_types( array(
58
- 'public' => true,
59
- '_builtin' => false,
60
- ), 'names'
61
- );
62
 
63
- array_unshift( $types, 'post' );
64
  ?>
65
  <h4><?php _e( 'Select the post type whose post meta fields you want to delete', 'bulk-delete' ); ?></h4>
66
  <table class="optiontable">
67
  <?php
68
- foreach ( $types as $type ) {
69
  ?>
70
  <tr>
71
  <td>
@@ -74,7 +77,7 @@ class Bulk_Delete_Post_Meta {
74
  </td>
75
  </tr>
76
  <?php
77
- }
78
  ?>
79
  </table>
80
 
@@ -105,13 +108,13 @@ class Bulk_Delete_Post_Meta {
105
  </tr>
106
  </table>
107
  <?php
108
- /**
109
- * Add more fields to the delete post meta field form.
110
- * This hook can be used to add more fields to the delete post meta field form
111
- *
112
- * @since 5.4
113
- */
114
- do_action( 'bd_delete_post_meta_form' );
115
  ?>
116
  <table class="optiontable">
117
  <tr>
@@ -149,12 +152,12 @@ class Bulk_Delete_Post_Meta {
149
  <select name="smbd_pm_cron_freq" id = "smbd_pm_cron_freq" disabled>
150
  <option value = "-1"><?php _e( "Don't repeat", 'bulk-delete' ); ?></option>
151
  <?php
152
- $schedules = wp_get_schedules();
153
- foreach ( $schedules as $key => $value ) {
154
  ?>
155
  <option value = "<?php echo $key; ?>"><?php echo $value['display']; ?></option>
156
  <?php
157
- }
158
  ?>
159
  </select>
160
  <span class="bd-pm-pro" style="color:red">
@@ -177,132 +180,130 @@ class Bulk_Delete_Post_Meta {
177
  </p>
178
  <!-- Post Meta box end-->
179
  <?php
180
- }
181
-
182
- /**
183
- * Filter JS Array and add validation hooks.
184
- *
185
- * @since 5.4
186
- * @static
187
- * @param array $js_array JavaScript Array
188
- * @return array Modified JavaScript Array
189
- */
190
- public static function filter_js_array( $js_array ) {
191
- $js_array['dt_iterators'][] = '_pm';
192
- $js_array['validators']['delete_meta_post'] = 'noValidation';
193
-
194
- $js_array['pre_action_msg']['delete_meta_post'] = 'deletePMWarning';
195
- $js_array['msg']['deletePMWarning'] = __( 'Are you sure you want to delete all the post meta fields that match the selected filters?', 'bulk-delete' );
196
-
197
- return $js_array;
198
- }
199
-
200
- /**
201
- * Controller for deleting post meta fields.
202
- *
203
- * @static
204
- * @since 5.4
205
- */
206
- public static function do_delete_post_meta() {
207
- $delete_options = array();
208
- $delete_options['post_type'] = esc_sql( array_get( $_POST, 'smbd_pm_post_type', 'post' ) );
209
-
210
- $delete_options['use_value'] = array_get_bool( $_POST, 'smbd_pm_use_value', FALSE );
211
- $delete_options['meta_key'] = esc_sql( array_get( $_POST, 'smbd_pm_key', '' ) );
212
-
213
- $delete_options['limit_to'] = absint( array_get( $_POST, 'smbd_pm_limit_to', 0 ) );
214
-
215
- $delete_options['restrict'] = array_get_bool( $_POST, 'smbd_pm_restrict', FALSE );
216
- $delete_options['op'] = esc_sql( array_get( $_POST, 'smbd_pm_op', 'before' ) );
217
- $delete_options['days'] = absint( array_get( $_POST, 'smbd_pm_days', 0 ) );
218
-
219
- /**
220
- * Delete post-meta delete options filter.
221
- * This filter is for processing filtering options for deleting post meta
222
- *
223
- * @since 5.4
224
- */
225
- $delete_options = apply_filters( 'bd_delete_post_meta_options', $delete_options, $_POST );
226
-
227
- if ( array_get( $_POST, 'smbd_pm_cron', 'false' ) == 'true' ) {
228
- $freq = $_POST['smbd_pm_cron_freq'];
229
- $time = strtotime( $_POST['smbd_pm_cron_start'] ) - ( get_option( 'gmt_offset' ) * 60 * 60 );
230
-
231
- if ( $freq == -1 ) {
232
- wp_schedule_single_event( $time, self::CRON_HOOK, array( $delete_options ) );
233
- } else {
234
- wp_schedule_event( $time, $freq, self::CRON_HOOK, array( $delete_options ) );
235
- }
236
- $msg = __( 'Post meta fields from the posts with the selected criteria are scheduled for deletion.', 'bulk-delete' ) . ' ' .
237
- sprintf( __( 'See the full list of <a href = "%s">scheduled tasks</a>' , 'bulk-delete' ), get_bloginfo( 'wpurl' ) . '/wp-admin/admin.php?page=' . Bulk_Delete::CRON_PAGE_SLUG );
238
- } else {
239
- $deleted_count = self::delete_post_meta( $delete_options );
240
- $msg = sprintf( _n( 'Deleted post meta field from %d post', 'Deleted post meta field from %d posts' , $deleted_count, 'bulk-delete' ), $deleted_count );
241
- }
242
-
243
- add_settings_error(
244
- Bulk_Delete_Meta::META_PAGE_SLUG,
245
- 'deleted-posts',
246
- $msg,
247
- 'updated'
248
- );
249
- }
250
-
251
- /**
252
- * Delete Post Meta.
253
- *
254
- * @static
255
- * @since 5.4
256
- * @param array $delete_options Options for deleting
257
- * @return int Number of posts that were deleted
258
- */
259
- public static function delete_post_meta( $delete_options ) {
260
- $count = 0;
261
- $post_type = $delete_options['post_type'];
262
- $limit_to = $delete_options['limit_to'];
263
- $meta_key = $delete_options['meta_key'];
264
- $use_value = $delete_options['use_value'];
265
- $restrict = $delete_options['restrict'];
266
- $days = $delete_options['days'];
267
- $op = $delete_options['op'];
268
-
269
- $options = array(
270
- 'post_status' => 'publish',
271
- 'post_type' => $post_type,
272
- );
273
-
274
- if ( $limit_to > 0 ) {
275
- $options['showposts'] = $limit_to;
276
- } else {
277
- $options['nopaging'] = 'true';
278
- }
279
-
280
- if ( $restrict ) {
281
- $options['date_query'] = array(
282
- array(
283
- 'column' => 'post_date',
284
- $op => "{$days} day ago",
285
- ),
286
- );
287
- }
288
-
289
- if ( $use_value ) {
290
- $meta_value = $delete_options['meta_value'];
291
- $options['meta_query'] = apply_filters( 'bd_delete_post_meta_query', array(), $delete_options );
292
- } else {
293
- $options['meta_key'] = $meta_key;
294
- }
295
-
296
- $wp_query = new WP_Query();
297
- $posts = $wp_query->query( $options );
298
-
299
- foreach ( $posts as $post ) {
300
- if ( delete_post_meta( $post->ID, $meta_key ) ) {
301
- $count++;
302
- }
303
- }
304
- return $count;
305
- }
306
  }
307
 
308
  // hooks
2
  /**
3
  * Utility class for deleting Post Meta.
4
  *
 
 
 
5
  * @since 5.4
6
+ * @author Sudar
7
+ * @package BulkDelete\Meta
8
  */
9
+
10
+
11
  class Bulk_Delete_Post_Meta {
12
 
13
+ /**
14
+ * Box slug.
15
+ *
16
+ * @since 5.4
17
+ */
18
+ const BOX_POST_META = 'bd-post-meta';
19
+
20
+ /**
21
+ * Cron Hook.
22
+ *
23
+ * @since 5.4
24
+ */
25
+ const CRON_HOOK = 'do-bulk-delete-post-meta';
26
+
27
+ /**
28
+ * Register post-meta meta box for delete meta page.
29
+ *
30
+ * @static
31
+ * @since 5.4
32
+ */
33
+ public static function add_delete_post_meta_box() {
34
+ $bd = BULK_DELETE();
35
+
36
+ add_meta_box(
37
+ self::BOX_POST_META,
38
+ __( 'Bulk Delete Post Meta', 'bulk-delete' ),
39
+ array( __CLASS__, 'render_delete_post_meta_box' ),
40
+ $bd->meta_page,
41
+ 'advanced'
42
+ );
43
+ }
44
+
45
+ /**
46
+ * Render delete post-meta meta box for delete meta page.
47
+ *
48
+ * @static
49
+ * @since 5.4
50
+ */
51
+ public static function render_delete_post_meta_box() {
52
+ if ( Bulk_Delete_Meta::is_meta_box_hidden( self::BOX_POST_META ) ) {
53
+ printf( __( 'This section just got enabled. Kindly <a href = "%1$s">refresh</a> the page to fully enable it.', 'bulk-delete' ), 'admin.php?page=' . Bulk_Delete_meta::META_PAGE_SLUG );
54
+ return;
55
+ }
56
  ?>
57
  <!-- Post Meta box start-->
58
  <fieldset class="options">
59
  <?php
60
+ $types = get_post_types( array(
61
+ 'public' => true,
62
+ '_builtin' => false,
63
+ ), 'names'
64
+ );
65
 
66
+ array_unshift( $types, 'post' );
67
  ?>
68
  <h4><?php _e( 'Select the post type whose post meta fields you want to delete', 'bulk-delete' ); ?></h4>
69
  <table class="optiontable">
70
  <?php
71
+ foreach ( $types as $type ) {
72
  ?>
73
  <tr>
74
  <td>
77
  </td>
78
  </tr>
79
  <?php
80
+ }
81
  ?>
82
  </table>
83
 
108
  </tr>
109
  </table>
110
  <?php
111
+ /**
112
+ * Add more fields to the delete post meta field form.
113
+ * This hook can be used to add more fields to the delete post meta field form
114
+ *
115
+ * @since 5.4
116
+ */
117
+ do_action( 'bd_delete_post_meta_form' );
118
  ?>
119
  <table class="optiontable">
120
  <tr>
152
  <select name="smbd_pm_cron_freq" id = "smbd_pm_cron_freq" disabled>
153
  <option value = "-1"><?php _e( "Don't repeat", 'bulk-delete' ); ?></option>
154
  <?php
155
+ $schedules = wp_get_schedules();
156
+ foreach ( $schedules as $key => $value ) {
157
  ?>
158
  <option value = "<?php echo $key; ?>"><?php echo $value['display']; ?></option>
159
  <?php
160
+ }
161
  ?>
162
  </select>
163
  <span class="bd-pm-pro" style="color:red">
180
  </p>
181
  <!-- Post Meta box end-->
182
  <?php
183
+ }
184
+
185
+ /**
186
+ * Filter JS Array and add validation hooks.
187
+ *
188
+ * @since 5.4
189
+ * @static
190
+ * @param array $js_array JavaScript Array
191
+ * @return array Modified JavaScript Array
192
+ */
193
+ public static function filter_js_array( $js_array ) {
194
+ $js_array['dt_iterators'][] = '_pm';
195
+ $js_array['validators']['delete_meta_post'] = 'noValidation';
196
+
197
+ $js_array['pre_action_msg']['delete_meta_post'] = 'deletePMWarning';
198
+ $js_array['msg']['deletePMWarning'] = __( 'Are you sure you want to delete all the post meta fields that match the selected filters?', 'bulk-delete' );
199
+
200
+ return $js_array;
201
+ }
202
+
203
+ /**
204
+ * Controller for deleting post meta fields.
205
+ *
206
+ * @static
207
+ * @since 5.4
208
+ */
209
+ public static function do_delete_post_meta() {
210
+ $delete_options = array();
211
+ $delete_options['post_type'] = esc_sql( array_get( $_POST, 'smbd_pm_post_type', 'post' ) );
212
+
213
+ $delete_options['use_value'] = array_get_bool( $_POST, 'smbd_pm_use_value', false );
214
+ $delete_options['meta_key'] = esc_sql( array_get( $_POST, 'smbd_pm_key', '' ) );
215
+
216
+ $delete_options['limit_to'] = absint( array_get( $_POST, 'smbd_pm_limit_to', 0 ) );
217
+
218
+ $delete_options['restrict'] = array_get_bool( $_POST, 'smbd_pm_restrict', false );
219
+ $delete_options['op'] = esc_sql( array_get( $_POST, 'smbd_pm_op', 'before' ) );
220
+ $delete_options['days'] = absint( array_get( $_POST, 'smbd_pm_days', 0 ) );
221
+
222
+ /**
223
+ * Delete post-meta delete options filter.
224
+ * This filter is for processing filtering options for deleting post meta
225
+ *
226
+ * @since 5.4
227
+ */
228
+ $delete_options = apply_filters( 'bd_delete_post_meta_options', $delete_options, $_POST );
229
+
230
+ if ( 'true' == array_get( $_POST, 'smbd_pm_cron', 'false' ) ) {
231
+ $freq = $_POST['smbd_pm_cron_freq'];
232
+ $time = strtotime( $_POST['smbd_pm_cron_start'] ) - ( get_option( 'gmt_offset' ) * 60 * 60 );
233
+
234
+ if ( $freq == -1 ) {
235
+ wp_schedule_single_event( $time, self::CRON_HOOK, array( $delete_options ) );
236
+ } else {
237
+ wp_schedule_event( $time, $freq, self::CRON_HOOK, array( $delete_options ) );
238
+ }
239
+ $msg = __( 'Post meta fields from the posts with the selected criteria are scheduled for deletion.', 'bulk-delete' ) . ' ' .
240
+ sprintf( __( 'See the full list of <a href = "%s">scheduled tasks</a>' , 'bulk-delete' ), get_bloginfo( 'wpurl' ) . '/wp-admin/admin.php?page=' . Bulk_Delete::CRON_PAGE_SLUG );
241
+ } else {
242
+ $deleted_count = self::delete_post_meta( $delete_options );
243
+ $msg = sprintf( _n( 'Deleted post meta field from %d post', 'Deleted post meta field from %d posts' , $deleted_count, 'bulk-delete' ), $deleted_count );
244
+ }
245
+
246
+ add_settings_error(
247
+ Bulk_Delete_Meta::META_PAGE_SLUG,
248
+ 'deleted-posts',
249
+ $msg,
250
+ 'updated'
251
+ );
252
+ }
253
+
254
+ /**
255
+ * Delete Post Meta.
256
+ *
257
+ * @static
258
+ * @since 5.4
259
+ * @param array $delete_options Options for deleting
260
+ * @return int Number of posts that were deleted
261
+ */
262
+ public static function delete_post_meta( $delete_options ) {
263
+ $count = 0;
264
+ $post_type = $delete_options['post_type'];
265
+ $limit_to = $delete_options['limit_to'];
266
+ $meta_key = $delete_options['meta_key'];
267
+ $use_value = $delete_options['use_value'];
268
+ $restrict = $delete_options['restrict'];
269
+ $days = $delete_options['days'];
270
+ $op = $delete_options['op'];
271
+
272
+ $options = array(
273
+ 'post_status' => 'publish',
274
+ 'post_type' => $post_type,
275
+ );
276
+
277
+ if ( $limit_to > 0 ) {
278
+ $options['showposts'] = $limit_to;
279
+ } else {
280
+ $options['nopaging'] = 'true';
281
+ }
282
+
283
+ if ( $restrict ) {
284
+ $options['date_query'] = array(
285
+ array(
286
+ 'column' => 'post_date',
287
+ $op => "{$days} day ago",
288
+ ),
289
+ );
290
+ }
291
+
292
+ if ( $use_value ) {
293
+ $options['meta_query'] = apply_filters( 'bd_delete_post_meta_query', array(), $delete_options );
294
+ } else {
295
+ $options['meta_key'] = $meta_key;
296
+ }
297
+
298
+ $post_ids = bd_query( $options );
299
+ foreach ( $post_ids as $post_id ) {
300
+ if ( delete_post_meta( $post_id, $meta_key ) ) {
301
+ $count++;
302
+ }
303
+ }
304
+
305
+ return $count;
306
+ }
 
 
307
  }
308
 
309
  // hooks
include/meta/class-bulk-delete-user-meta.php CHANGED
@@ -2,62 +2,65 @@
2
  /**
3
  * Utility class for deleting User Meta.
4
  *
5
- * @package Bulk_Delete
6
- * @subpackage meta
7
- * @author Sudar
8
  * @since 5.4
 
 
9
  */
 
 
10
  class Bulk_Delete_User_Meta {
11
 
12
- /**
13
- * Box slug.
14
- * @since 5.4
15
- */
16
- const BOX_USER_META = 'bd-user-meta';
17
-
18
- /**
19
- * Cron Hook.
20
- * @since 5.4
21
- */
22
- const CRON_HOOK = 'do-bulk-delete-user-meta';
23
-
24
- /**
25
- * Register user-meta meta box for delete meta page.
26
- *
27
- * @static
28
- * @since 5.4
29
- */
30
- public static function add_delete_user_meta_box() {
31
- $bd = BULK_DELETE();
32
-
33
- add_meta_box(
34
- self::BOX_USER_META,
35
- __( 'Bulk Delete User Meta', 'bulk-delete' ),
36
- array( __CLASS__, 'render_delete_user_meta_box' ),
37
- $bd->meta_page,
38
- 'advanced'
39
- );
40
- }
41
-
42
- /**
43
- * Render delete user-meta meta box for delete meta page.
44
- *
45
- * @static
46
- * @since 5.4
47
- */
48
- public static function render_delete_user_meta_box() {
49
- if ( Bulk_Delete_Meta::is_meta_box_hidden( self::BOX_USER_META ) ) {
50
- printf( __( 'This section just got enabled. Kindly <a href = "%1$s">refresh</a> the page to fully enable it.', 'bulk-delete' ), 'admin.php?page=' . Bulk_Delete_meta::META_PAGE_SLUG );
51
- return;
52
- }
 
 
53
  ?>
54
  <!-- User Meta box start-->
55
  <fieldset class="options">
56
  <h4><?php _e( 'Select the user role whose user meta fields you want to delete', 'bulk-delete' ); ?></h4>
57
  <table class="optiontable">
58
  <?php
59
- $users_count = count_users();
60
- foreach ( $users_count['avail_roles'] as $role => $count ) {
61
  ?>
62
  <tr>
63
  <td>
@@ -66,7 +69,7 @@ class Bulk_Delete_User_Meta {
66
  </td>
67
  </tr>
68
  <?php
69
- }
70
  ?>
71
  </table>
72
 
@@ -97,13 +100,13 @@ class Bulk_Delete_User_Meta {
97
  </tr>
98
  </table>
99
  <?php
100
- /**
101
- * Add more fields to the delete user meta field form.
102
- * This hook can be used to add more fields to the delete user meta field form
103
- *
104
- * @since 5.4
105
- */
106
- do_action( 'bd_delete_user_meta_form' );
107
  ?>
108
  <table class="optiontable">
109
  <tr>
@@ -129,12 +132,12 @@ class Bulk_Delete_User_Meta {
129
  <select name="smbd_um_cron_freq" id = "smbd_um_cron_freq" disabled>
130
  <option value = "-1"><?php _e( "Don't repeat", 'bulk-delete' ); ?></option>
131
  <?php
132
- $schedules = wp_get_schedules();
133
- foreach ( $schedules as $key => $value ) {
134
  ?>
135
  <option value = "<?php echo $key; ?>"><?php echo $value['display']; ?></option>
136
  <?php
137
- }
138
  ?>
139
  </select>
140
  <span class="bd-um-pro" style="color:red">
@@ -157,112 +160,111 @@ class Bulk_Delete_User_Meta {
157
  </p>
158
  <!-- User Meta box end-->
159
  <?php
160
- }
161
-
162
- /**
163
- * Filter JS Array and add validation hooks.
164
- *
165
- * @since 5.4
166
- * @static
167
- * @param array $js_array JavaScript Array
168
- * @return array Modified JavaScript Array
169
- */
170
- public static function filter_js_array( $js_array ) {
171
- $js_array['dt_iterators'][] = '_um';
172
- $js_array['validators']['delete_meta_user'] = 'noValidation';
173
-
174
- $js_array['pre_action_msg']['delete_meta_user'] = 'deleteUMWarning';
175
- $js_array['msg']['deleteUMWarning'] = __( 'Are you sure you want to delete all the user meta fields that match the selected filters?', 'bulk-delete' );
176
-
177
- return $js_array;
178
- }
179
-
180
- /**
181
- * Controller for deleting user meta fields.
182
- *
183
- * @static
184
- * @since 5.4
185
- */
186
- public static function do_delete_user_meta() {
187
- $delete_options = array();
188
- $delete_options['user_role'] = array_get( $_POST, 'smbd_um_role', 'administrator' );
189
-
190
- $delete_options['use_value'] = array_get_bool( $_POST, 'smbd_um_use_value', FALSE );
191
- $delete_options['meta_key'] = esc_sql( array_get( $_POST, 'smbd_um_key', '' ) );
192
-
193
- $delete_options['limit_to'] = absint( array_get( $_POST, 'smbd_um_limit_to', 0 ) );
194
-
195
- /**
196
- * Delete user-meta delete options filter.
197
- * This filter is for processing filtering options for deleting user meta
198
- *
199
- * @since 5.4
200
- */
201
- $delete_options = apply_filters( 'bd_delete_user_meta_options', $delete_options, $_POST );
202
-
203
- if ( array_get( $_POST, 'smbd_um_cron', 'false' ) == 'true' ) {
204
- $freq = $_POST['smbd_um_cron_freq'];
205
- $time = strtotime( $_POST['smbd_um_cron_start'] ) - ( get_option( 'gmt_offset' ) * 60 * 60 );
206
-
207
- if ( $freq == -1 ) {
208
- wp_schedule_single_event( $time, self::CRON_HOOK, array( $delete_options ) );
209
- } else {
210
- wp_schedule_event( $time, $freq, self::CRON_HOOK, array( $delete_options ) );
211
- }
212
- $msg = __( 'User meta fields from the users with the selected criteria are scheduled for deletion.', 'bulk-delete' ) . ' ' .
213
- sprintf( __( 'See the full list of <a href = "%s">scheduled tasks</a>' , 'bulk-delete' ), get_bloginfo( 'wpurl' ) . '/wp-admin/admin.php?page=' . Bulk_Delete::CRON_PAGE_SLUG );
214
- } else {
215
- $deleted_count = self::delete_user_meta( $delete_options );
216
- $msg = sprintf( _n( 'Deleted user meta field from %d user', 'Deleted user meta field from %d users' , $deleted_count, 'bulk-delete' ), $deleted_count );
217
- }
218
-
219
- add_settings_error(
220
- Bulk_Delete_Meta::META_PAGE_SLUG,
221
- 'deleted-users',
222
- $msg,
223
- 'updated'
224
- );
225
- }
226
-
227
- /**
228
- * Delete User Meta.
229
- *
230
- * @static
231
- * @since 5.4
232
- * @param array $delete_options Options for deleting
233
- * @return int Number of users that were deleted
234
- */
235
- public static function delete_user_meta( $delete_options ) {
236
- $count = 0;
237
- $user_role = $delete_options['user_role'];
238
- $meta_key = $delete_options['meta_key'];
239
- $use_value = $delete_options['use_value'];
240
- $limit_to = $delete_options['limit_to'];
241
-
242
- $options = array(
243
- 'role' => $user_role,
244
- );
245
-
246
- if ( $limit_to > 0 ) {
247
- $options['number'] = $limit_to;
248
- }
249
-
250
- if ( $use_value ) {
251
- $meta_value = $delete_options['meta_value'];
252
- $options['meta_query'] = apply_filters( 'bd_delete_user_meta_query', array(), $delete_options );
253
- } else {
254
- $options['meta_key'] = $meta_key;
255
- }
256
-
257
- $users = get_users( $options );
258
-
259
- foreach ( $users as $user ) {
260
- if ( delete_user_meta( $user->ID, $meta_key ) ) {
261
- $count++;
262
- }
263
- }
264
- return $count;
265
- }
266
  }
267
 
268
  // hooks
2
  /**
3
  * Utility class for deleting User Meta.
4
  *
 
 
 
5
  * @since 5.4
6
+ * @author Sudar
7
+ * @package BulkDelete\Meta
8
  */
9
+
10
+
11
  class Bulk_Delete_User_Meta {
12
 
13
+ /**
14
+ * Box slug.
15
+ *
16
+ * @since 5.4
17
+ */
18
+ const BOX_USER_META = 'bd-user-meta';
19
+
20
+ /**
21
+ * Cron Hook.
22
+ *
23
+ * @since 5.4
24
+ */
25
+ const CRON_HOOK = 'do-bulk-delete-user-meta';
26
+
27
+ /**
28
+ * Register user-meta meta box for delete meta page.
29
+ *
30
+ * @static
31
+ * @since 5.4
32
+ */
33
+ public static function add_delete_user_meta_box() {
34
+ $bd = BULK_DELETE();
35
+
36
+ add_meta_box(
37
+ self::BOX_USER_META,
38
+ __( 'Bulk Delete User Meta', 'bulk-delete' ),
39
+ array( __CLASS__, 'render_delete_user_meta_box' ),
40
+ $bd->meta_page,
41
+ 'advanced'
42
+ );
43
+ }
44
+
45
+ /**
46
+ * Render delete user-meta meta box for delete meta page.
47
+ *
48
+ * @static
49
+ * @since 5.4
50
+ */
51
+ public static function render_delete_user_meta_box() {
52
+ if ( Bulk_Delete_Meta::is_meta_box_hidden( self::BOX_USER_META ) ) {
53
+ printf( __( 'This section just got enabled. Kindly <a href = "%1$s">refresh</a> the page to fully enable it.', 'bulk-delete' ), 'admin.php?page=' . Bulk_Delete_meta::META_PAGE_SLUG );
54
+ return;
55
+ }
56
  ?>
57
  <!-- User Meta box start-->
58
  <fieldset class="options">
59
  <h4><?php _e( 'Select the user role whose user meta fields you want to delete', 'bulk-delete' ); ?></h4>
60
  <table class="optiontable">
61
  <?php
62
+ $users_count = count_users();
63
+ foreach ( $users_count['avail_roles'] as $role => $count ) {
64
  ?>
65
  <tr>
66
  <td>
69
  </td>
70
  </tr>
71
  <?php
72
+ }
73
  ?>
74
  </table>
75
 
100
  </tr>
101
  </table>
102
  <?php
103
+ /**
104
+ * Add more fields to the delete user meta field form.
105
+ * This hook can be used to add more fields to the delete user meta field form
106
+ *
107
+ * @since 5.4
108
+ */
109
+ do_action( 'bd_delete_user_meta_form' );
110
  ?>
111
  <table class="optiontable">
112
  <tr>
132
  <select name="smbd_um_cron_freq" id = "smbd_um_cron_freq" disabled>
133
  <option value = "-1"><?php _e( "Don't repeat", 'bulk-delete' ); ?></option>
134
  <?php
135
+ $schedules = wp_get_schedules();
136
+ foreach ( $schedules as $key => $value ) {
137
  ?>
138
  <option value = "<?php echo $key; ?>"><?php echo $value['display']; ?></option>
139
  <?php
140
+ }
141
  ?>
142
  </select>
143
  <span class="bd-um-pro" style="color:red">
160
  </p>
161
  <!-- User Meta box end-->
162
  <?php
163
+ }
164
+
165
+ /**
166
+ * Filter JS Array and add validation hooks.
167
+ *
168
+ * @since 5.4
169
+ * @static
170
+ * @param array $js_array JavaScript Array
171
+ * @return array Modified JavaScript Array
172
+ */
173
+ public static function filter_js_array( $js_array ) {
174
+ $js_array['dt_iterators'][] = '_um';
175
+ $js_array['validators']['delete_meta_user'] = 'noValidation';
176
+
177
+ $js_array['pre_action_msg']['delete_meta_user'] = 'deleteUMWarning';
178
+ $js_array['msg']['deleteUMWarning'] = __( 'Are you sure you want to delete all the user meta fields that match the selected filters?', 'bulk-delete' );
179
+
180
+ return $js_array;
181
+ }
182
+
183
+ /**
184
+ * Controller for deleting user meta fields.
185
+ *
186
+ * @static
187
+ * @since 5.4
188
+ */
189
+ public static function do_delete_user_meta() {
190
+ $delete_options = array();
191
+ $delete_options['user_role'] = array_get( $_POST, 'smbd_um_role', 'administrator' );
192
+
193
+ $delete_options['use_value'] = array_get_bool( $_POST, 'smbd_um_use_value', false );
194
+ $delete_options['meta_key'] = esc_sql( array_get( $_POST, 'smbd_um_key', '' ) );
195
+
196
+ $delete_options['limit_to'] = absint( array_get( $_POST, 'smbd_um_limit_to', 0 ) );
197
+
198
+ /**
199
+ * Delete user-meta delete options filter.
200
+ * This filter is for processing filtering options for deleting user meta
201
+ *
202
+ * @since 5.4
203
+ */
204
+ $delete_options = apply_filters( 'bd_delete_user_meta_options', $delete_options, $_POST );
205
+
206
+ if ( 'true' == array_get( $_POST, 'smbd_um_cron', 'false' ) ) {
207
+ $freq = $_POST['smbd_um_cron_freq'];
208
+ $time = strtotime( $_POST['smbd_um_cron_start'] ) - ( get_option( 'gmt_offset' ) * 60 * 60 );
209
+
210
+ if ( $freq == -1 ) {
211
+ wp_schedule_single_event( $time, self::CRON_HOOK, array( $delete_options ) );
212
+ } else {
213
+ wp_schedule_event( $time, $freq, self::CRON_HOOK, array( $delete_options ) );
214
+ }
215
+ $msg = __( 'User meta fields from the users with the selected criteria are scheduled for deletion.', 'bulk-delete' ) . ' ' .
216
+ sprintf( __( 'See the full list of <a href = "%s">scheduled tasks</a>' , 'bulk-delete' ), get_bloginfo( 'wpurl' ) . '/wp-admin/admin.php?page=' . Bulk_Delete::CRON_PAGE_SLUG );
217
+ } else {
218
+ $deleted_count = self::delete_user_meta( $delete_options );
219
+ $msg = sprintf( _n( 'Deleted user meta field from %d user', 'Deleted user meta field from %d users' , $deleted_count, 'bulk-delete' ), $deleted_count );
220
+ }
221
+
222
+ add_settings_error(
223
+ Bulk_Delete_Meta::META_PAGE_SLUG,
224
+ 'deleted-users',
225
+ $msg,
226
+ 'updated'
227
+ );
228
+ }
229
+
230
+ /**
231
+ * Delete User Meta.
232
+ *
233
+ * @static
234
+ * @since 5.4
235
+ * @param array $delete_options Options for deleting
236
+ * @return int Number of users that were deleted
237
+ */
238
+ public static function delete_user_meta( $delete_options ) {
239
+ $count = 0;
240
+ $user_role = $delete_options['user_role'];
241
+ $meta_key = $delete_options['meta_key'];
242
+ $use_value = $delete_options['use_value'];
243
+ $limit_to = $delete_options['limit_to'];
244
+
245
+ $options = array(
246
+ 'role' => $user_role,
247
+ );
248
+
249
+ if ( $limit_to > 0 ) {
250
+ $options['number'] = $limit_to;
251
+ }
252
+
253
+ if ( $use_value ) {
254
+ $options['meta_query'] = apply_filters( 'bd_delete_user_meta_query', array(), $delete_options );
255
+ } else {
256
+ $options['meta_key'] = $meta_key;
257
+ }
258
+
259
+ $users = get_users( $options );
260
+
261
+ foreach ( $users as $user ) {
262
+ if ( delete_user_meta( $user->ID, $meta_key ) ) {
263
+ $count++;
264
+ }
265
+ }
266
+ return $count;
267
+ }
 
268
  }
269
 
270
  // hooks
include/misc/class-bulk-delete-jetpack-contact-form-messages.php CHANGED
@@ -2,50 +2,51 @@
2
  /**
3
  * Utility class for deleting Jetpack Contact Form Messages
4
  *
5
- * @package Bulk_Delete
6
- * @subpackage Misc
7
- * @author Sudar
8
  * @since 5.3
 
 
9
  */
 
 
10
  class Bulk_Delete_Jetpack_Contact_Form_Message {
11
 
12
- // box slugs
13
- const BOX_JETPACK_MESSAGES = 'bd-jetpack-feedback';
14
-
15
- const FEEDBACK_POST_TYPE = 'feedback';
16
- const CRON_HOOK = 'do-bulk-delete-feedback';
17
-
18
- /**
19
- * Register Jetpack Feedback meta box for delete misc page
20
- *
21
- * @static
22
- * @since 5.3
23
- */
24
- public static function add_delete_jetpack_messages_meta_box() {
25
- $bd = BULK_DELETE();
26
-
27
- add_meta_box(
28
- self::BOX_JETPACK_MESSAGES,
29
- __( 'Bulk Delete Jetpack Contact Form Messages', 'bulk-delete' ),
30
- array( __CLASS__, 'render_delete_jetpack_messages_box' ),
31
- $bd->misc_page,
32
- 'advanced'
33
- );
34
- }
35
-
36
- /**
37
- * Render Jetpack Feedback meta box for delete misc page
38
- *
39
- * @static
40
- * @since 5.3
41
- */
42
- public static function render_delete_jetpack_messages_box() {
43
- if ( Bulk_Delete_Misc::is_misc_box_hidden( self::BOX_JETPACK_MESSAGES ) ) {
44
- printf( __( 'This section just got enabled. Kindly <a href = "%1$s">refresh</a> the page to fully enable it.', 'bulk-delete' ), 'admin.php?page=' . Bulk_Delete_Misc::MISC_PAGE_SLUG );
45
- return;
46
- }
47
-
48
- if ( !self::is_jetpack_contact_active() ) {
49
  ?>
50
  <!-- Delete Jetpack Feedback box start-->
51
  <p>
@@ -55,8 +56,8 @@ class Bulk_Delete_Jetpack_Contact_Form_Message {
55
  </p>
56
  <!-- Delete Jetpack Feedback box end-->
57
  <?php
58
- } else {
59
- $feedback_count = wp_count_posts( self::FEEDBACK_POST_TYPE );
60
  ?>
61
  <!-- Delete Jetpack Feedback box start-->
62
  <fieldset class="options">
@@ -81,13 +82,13 @@ class Bulk_Delete_Jetpack_Contact_Form_Message {
81
  </tr>
82
  </table>
83
  <?php
84
- /**
85
- * Add more fields to the delete jetpack messages form
86
- * This hook can be used to add more fields to the delete jetpack messages form
87
- *
88
- * @since 5.3
89
- */
90
- do_action( 'bd_delete_jetpack_messages_form' );
91
  ?>
92
  <table class="optiontable">
93
  <tr>
@@ -142,12 +143,12 @@ class Bulk_Delete_Jetpack_Contact_Form_Message {
142
  <select name = "smbd_feedback_cron_freq" id = "smbd_feedback_cron_freq" disabled>
143
  <option value = "-1"><?php _e( "Don't repeat", 'bulk-delete' ); ?></option>
144
  <?php
145
- $schedules = wp_get_schedules();
146
- foreach($schedules as $key => $value) {
147
  ?>
148
  <option value = "<?php echo $key; ?>"><?php echo $value['display']; ?></option>
149
  <?php
150
- }
151
  ?>
152
  </select>
153
  <span class = "bd-feedback-pro" style = "color:red"><?php _e( 'Only available in Pro Addon', 'bulk-delete' ); ?> <a href = "http://bulkwp.com/addons/bulk-delete-jetpack-contact-form-messages/?utm_source=wpadmin&utm_campaign=BulkDelete&utm_medium=buynow&utm_content=bd-jcm" target="_blank">Buy now</a></span>
@@ -161,162 +162,161 @@ class Bulk_Delete_Jetpack_Contact_Form_Message {
161
  </p>
162
  <!-- Delete Jetpack Feedback box end-->
163
  <?php
164
- }
165
- }
166
-
167
- /**
168
- * Filter JS Array and add validation hooks
169
- *
170
- * @since 5.4
171
- * @static
172
- * @param array $js_array JavaScript Array
173
- * @return array Modified JavaScript Array
174
- */
175
- public static function filter_js_array( $js_array ) {
176
- $js_array['dt_iterators'][] = '_feedback';
177
- $js_array['validators']['delete_jetpack_messages'] = 'noValidation';
178
-
179
- $js_array['pre_action_msg']['delete_jetpack_messages'] = 'deleteJetpackWarning';
180
- $js_array['msg']['deleteJetpackWarning'] = __( 'Are you sure you want to delete all the Jetpack contact form messages based on the selected filters?', 'bulk-delete' );
181
- return $js_array;
182
- }
183
-
184
- /**
185
- * Controller for deleting Jetpack contact form messages
186
- *
187
- * @static
188
- * @since 5.3
189
- */
190
- public static function do_delete_jetpack_messages() {
191
- $delete_options = array();
192
-
193
- $delete_options['use_filter'] = array_get( $_POST, 'smbd_feedback_use_filter', 'false' );
194
-
195
- $delete_options['restrict'] = array_get( $_POST, 'smbd_feedback_restrict', FALSE );
196
- $delete_options['limit_to'] = absint( array_get( $_POST, 'smbd_feedback_limit_to', 0 ) );
197
- $delete_options['force_delete'] = array_get( $_POST, 'smbd_feedback_force_delete', 'false' );
198
-
199
- $delete_options['feedback_op'] = array_get( $_POST, 'smbd_feedback_op' );
200
- $delete_options['feedback_days'] = array_get( $_POST, 'smbd_feedback_days' );
201
-
202
- /**
203
- * Delete jetpack feedback delete options filter
204
- * This filter is for processing filtering options for deleting jetpack message
205
- *
206
- * @since 5.3
207
- */
208
- $delete_options = apply_filters( 'bd_delete_jetpack_messages_delete_options', $delete_options, $_POST );
209
-
210
- if ( array_get( $_POST, 'smbd_feedback_cron', 'false' ) == 'true' ) {
211
- $freq = $_POST['smbd_feedback_cron_freq'];
212
- $time = strtotime( $_POST['smbd_feedback_cron_start'] ) - ( get_option( 'gmt_offset' ) * 60 * 60 );
213
-
214
- if ( $freq == -1 ) {
215
- wp_schedule_single_event( $time, self::CRON_HOOK, array( $delete_options ) );
216
- } else {
217
- wp_schedule_event( $time, $freq, self::CRON_HOOK, array( $delete_options ) );
218
- }
219
- $msg = __( 'Jetpack contact form messages with the selected criteria are scheduled for deletion.', 'bulk-delete' ) . ' ' .
220
- sprintf( __( 'See the full list of <a href = "%s">scheduled tasks</a>' , 'bulk-delete' ), get_bloginfo( "wpurl" ) . '/wp-admin/admin.php?page=' . Bulk_Delete::CRON_PAGE_SLUG );
221
- } else {
222
- $deleted_count = self::delete_jetpack_messages( $delete_options );
223
- $msg = sprintf( _n( 'Deleted %d Jetpack contact form message', 'Deleted %d Jetpack contact form messages' , $deleted_count, 'bulk-delete' ), $deleted_count );
224
- }
225
-
226
- add_settings_error(
227
- Bulk_Delete_Misc::MISC_PAGE_SLUG,
228
- 'deleted-posts',
229
- $msg,
230
- 'updated'
231
- );
232
- }
233
-
234
- /**
235
- * Delete Jetpack contact form messages
236
- *
237
- * @static
238
- * @since 5.3
239
- * @param array $delete_options Options for deleting
240
- * @return int Number of posts that were deleted
241
- */
242
- public static function delete_jetpack_messages( $delete_options ) {
243
- $count = 0;
244
- $use_filter = $delete_options['use_filter'];
245
-
246
- $options = array(
247
- 'post_status' => 'publish',
248
- 'post_type' => self::FEEDBACK_POST_TYPE
249
- );
250
-
251
- $limit_to = $delete_options['limit_to'];
252
-
253
- if ( $limit_to > 0 ) {
254
- $options['showposts'] = $limit_to;
255
- } else {
256
- $options['nopaging'] = 'true';
257
- }
258
-
259
- $force_delete = $delete_options['force_delete'];
260
-
261
- if ( $force_delete == 'true' ) {
262
- $force_delete = true;
263
- } else {
264
- $force_delete = false;
265
- }
266
-
267
- if ($delete_options['restrict'] == "true") {
268
- $options['op'] = $delete_options['feedback_op'];
269
- $options['days'] = $delete_options['feedback_days'];
270
-
271
- if ( !class_exists( 'Bulk_Delete_By_Days' ) ) {
272
- require_once Bulk_Delete::$PLUGIN_DIR . '/include/class-bulk-delete-by-days.php';
273
- }
274
- $bulk_Delete_By_Days = new Bulk_Delete_By_Days;
275
- }
276
-
277
- $wp_query = new WP_Query();
278
- $posts = $wp_query->query( $options );
279
-
280
- foreach ( $posts as $post ) {
281
- if ( 'true' == $use_filter ) {
282
- /**
283
- * Process additional filters for deleting jetpack messages
284
- *
285
- * @since 5.3
286
- */
287
- $can_delete = apply_filters( 'bd_delete_jetpack_messages_can_delete', $delete_options, $post->ID );
288
- if ( ! $can_delete ) {
289
- continue;
290
- }
291
- }
292
-
293
- // $force delete parameter to custom post types doesn't work
294
- if ( $force_delete ) {
295
- wp_delete_post( $post->ID, TRUE );
296
- } else {
297
- wp_trash_post( $post->ID );
298
- }
299
- $count++;
300
- }
301
-
302
- return $count;
303
- }
304
-
305
- /**
306
- * Check whether Jetpack Contact Form is active
307
- *
308
- * @static
309
- * @since 5.3
310
- * @return bool True if active, False otherwise
311
- */
312
- public static function is_jetpack_contact_active() {
313
- $jetpack_active_modules = get_option( 'jetpack_active_modules' );
314
- if ( class_exists( 'Jetpack', FALSE ) && $jetpack_active_modules && in_array( 'contact-form', $jetpack_active_modules ) ) {
315
- return TRUE;
316
- }
317
-
318
- return FALSE;
319
- }
320
  }
321
 
322
  // hooks
2
  /**
3
  * Utility class for deleting Jetpack Contact Form Messages
4
  *
 
 
 
5
  * @since 5.3
6
+ * @author Sudar
7
+ * @package BulkDelete\Misc
8
  */
9
+
10
+
11
  class Bulk_Delete_Jetpack_Contact_Form_Message {
12
 
13
+ // box slugs
14
+ const BOX_JETPACK_MESSAGES = 'bd-jetpack-feedback';
15
+
16
+ const FEEDBACK_POST_TYPE = 'feedback';
17
+ const CRON_HOOK = 'do-bulk-delete-feedback';
18
+
19
+ /**
20
+ * Register Jetpack Feedback meta box for delete misc page
21
+ *
22
+ * @static
23
+ * @since 5.3
24
+ */
25
+ public static function add_delete_jetpack_messages_meta_box() {
26
+ $bd = BULK_DELETE();
27
+
28
+ add_meta_box(
29
+ self::BOX_JETPACK_MESSAGES,
30
+ __( 'Bulk Delete Jetpack Contact Form Messages', 'bulk-delete' ),
31
+ array( __CLASS__, 'render_delete_jetpack_messages_box' ),
32
+ $bd->misc_page,
33
+ 'advanced'
34
+ );
35
+ }
36
+
37
+ /**
38
+ * Render Jetpack Feedback meta box for delete misc page
39
+ *
40
+ * @static
41
+ * @since 5.3
42
+ */
43
+ public static function render_delete_jetpack_messages_box() {
44
+ if ( Bulk_Delete_Misc::is_misc_box_hidden( self::BOX_JETPACK_MESSAGES ) ) {
45
+ printf( __( 'This section just got enabled. Kindly <a href = "%1$s">refresh</a> the page to fully enable it.', 'bulk-delete' ), 'admin.php?page=' . Bulk_Delete_Misc::MISC_PAGE_SLUG );
46
+ return;
47
+ }
48
+
49
+ if ( ! self::is_jetpack_contact_active() ) {
50
  ?>
51
  <!-- Delete Jetpack Feedback box start-->
52
  <p>
56
  </p>
57
  <!-- Delete Jetpack Feedback box end-->
58
  <?php
59
+ } else {
60
+ $feedback_count = wp_count_posts( self::FEEDBACK_POST_TYPE );
61
  ?>
62
  <!-- Delete Jetpack Feedback box start-->
63
  <fieldset class="options">
82
  </tr>
83
  </table>
84
  <?php
85
+ /**
86
+ * Add more fields to the delete jetpack messages form
87
+ * This hook can be used to add more fields to the delete jetpack messages form
88
+ *
89
+ * @since 5.3
90
+ */
91
+ do_action( 'bd_delete_jetpack_messages_form' );
92
  ?>
93
  <table class="optiontable">
94
  <tr>
143
  <select name = "smbd_feedback_cron_freq" id = "smbd_feedback_cron_freq" disabled>
144
  <option value = "-1"><?php _e( "Don't repeat", 'bulk-delete' ); ?></option>
145
  <?php
146
+ $schedules = wp_get_schedules();
147
+ foreach ( $schedules as $key => $value ) {
148
  ?>
149
  <option value = "<?php echo $key; ?>"><?php echo $value['display']; ?></option>
150
  <?php
151
+ }
152
  ?>
153
  </select>
154
  <span class = "bd-feedback-pro" style = "color:red"><?php _e( 'Only available in Pro Addon', 'bulk-delete' ); ?> <a href = "http://bulkwp.com/addons/bulk-delete-jetpack-contact-form-messages/?utm_source=wpadmin&utm_campaign=BulkDelete&utm_medium=buynow&utm_content=bd-jcm" target="_blank">Buy now</a></span>
162
  </p>
163
  <!-- Delete Jetpack Feedback box end-->
164
  <?php
165
+ }
166
+ }
167
+
168
+ /**
169
+ * Filter JS Array and add validation hooks
170
+ *
171
+ * @since 5.4
172
+ * @static
173
+ * @param array $js_array JavaScript Array
174
+ * @return array Modified JavaScript Array
175
+ */
176
+ public static function filter_js_array( $js_array ) {
177
+ $js_array['dt_iterators'][] = '_feedback';
178
+ $js_array['validators']['delete_jetpack_messages'] = 'noValidation';
179
+
180
+ $js_array['pre_action_msg']['delete_jetpack_messages'] = 'deleteJetpackWarning';
181
+ $js_array['msg']['deleteJetpackWarning'] = __( 'Are you sure you want to delete all the Jetpack contact form messages based on the selected filters?', 'bulk-delete' );
182
+ return $js_array;
183
+ }
184
+
185
+ /**
186
+ * Controller for deleting Jetpack contact form messages
187
+ *
188
+ * @static
189
+ * @since 5.3
190
+ */
191
+ public static function do_delete_jetpack_messages() {
192
+ $delete_options = array();
193
+
194
+ $delete_options['use_filter'] = array_get( $_POST, 'smbd_feedback_use_filter', 'false' );
195
+
196
+ $delete_options['restrict'] = array_get( $_POST, 'smbd_feedback_restrict', false );
197
+ $delete_options['limit_to'] = absint( array_get( $_POST, 'smbd_feedback_limit_to', 0 ) );
198
+ $delete_options['force_delete'] = array_get( $_POST, 'smbd_feedback_force_delete', 'false' );
199
+
200
+ $delete_options['feedback_op'] = array_get( $_POST, 'smbd_feedback_op' );
201
+ $delete_options['feedback_days'] = array_get( $_POST, 'smbd_feedback_days' );
202
+
203
+ /**
204
+ * Delete jetpack feedback delete options filter
205
+ * This filter is for processing filtering options for deleting jetpack message
206
+ *
207
+ * @since 5.3
208
+ */
209
+ $delete_options = apply_filters( 'bd_delete_jetpack_messages_delete_options', $delete_options, $_POST );
210
+
211
+ if ( 'true' == array_get( $_POST, 'smbd_feedback_cron', 'false' ) ) {
212
+ $freq = $_POST['smbd_feedback_cron_freq'];
213
+ $time = strtotime( $_POST['smbd_feedback_cron_start'] ) - ( get_option( 'gmt_offset' ) * 60 * 60 );
214
+
215
+ if ( $freq == -1 ) {
216
+ wp_schedule_single_event( $time, self::CRON_HOOK, array( $delete_options ) );
217
+ } else {
218
+ wp_schedule_event( $time, $freq, self::CRON_HOOK, array( $delete_options ) );
219
+ }
220
+ $msg = __( 'Jetpack contact form messages with the selected criteria are scheduled for deletion.', 'bulk-delete' ) . ' ' .
221
+ sprintf( __( 'See the full list of <a href = "%s">scheduled tasks</a>' , 'bulk-delete' ), get_bloginfo( 'wpurl' ) . '/wp-admin/admin.php?page=' . Bulk_Delete::CRON_PAGE_SLUG );
222
+ } else {
223
+ $deleted_count = self::delete_jetpack_messages( $delete_options );
224
+ $msg = sprintf( _n( 'Deleted %d Jetpack contact form message', 'Deleted %d Jetpack contact form messages' , $deleted_count, 'bulk-delete' ), $deleted_count );
225
+ }
226
+
227
+ add_settings_error(
228
+ Bulk_Delete_Misc::MISC_PAGE_SLUG,
229
+ 'deleted-posts',
230
+ $msg,
231
+ 'updated'
232
+ );
233
+ }
234
+
235
+ /**
236
+ * Delete Jetpack contact form messages
237
+ *
238
+ * @static
239
+ * @since 5.3
240
+ * @param array $delete_options Options for deleting
241
+ * @return int Number of posts that were deleted
242
+ */
243
+ public static function delete_jetpack_messages( $delete_options ) {
244
+ $count = 0;
245
+ $use_filter = $delete_options['use_filter'];
246
+
247
+ $options = array(
248
+ 'post_status' => 'publish',
249
+ 'post_type' => self::FEEDBACK_POST_TYPE,
250
+ );
251
+
252
+ $limit_to = $delete_options['limit_to'];
253
+
254
+ if ( $limit_to > 0 ) {
255
+ $options['showposts'] = $limit_to;
256
+ } else {
257
+ $options['nopaging'] = 'true';
258
+ }
259
+
260
+ $force_delete = $delete_options['force_delete'];
261
+
262
+ if ( 'true' == $force_delete ) {
263
+ $force_delete = true;
264
+ } else {
265
+ $force_delete = false;
266
+ }
267
+
268
+ if ( 'true' == $delete_options['restrict'] ) {
269
+ $options['op'] = $delete_options['feedback_op'];
270
+ $options['days'] = $delete_options['feedback_days'];
271
+
272
+ if ( ! class_exists( 'Bulk_Delete_By_Days' ) ) {
273
+ require_once Bulk_Delete::$PLUGIN_DIR . '/include/util/class-bulk-delete-by-days.php';
274
+ }
275
+ new Bulk_Delete_By_Days;
276
+ }
277
+
278
+ $post_ids = bd_query( $options );
279
+ foreach ( $post_ids as $post_id ) {
280
+ if ( 'true' == $use_filter ) {
281
+
282
+ /**
283
+ * Process additional filters for deleting jetpack messages
284
+ *
285
+ * @since 5.3
286
+ */
287
+ $can_delete = apply_filters( 'bd_delete_jetpack_messages_can_delete', $delete_options, $post_id );
288
+ if ( ! $can_delete ) {
289
+ continue;
290
+ }
291
+ }
292
+
293
+ // $force delete parameter to custom post types doesn't work
294
+ if ( $force_delete ) {
295
+ wp_delete_post( $post_id, true );
296
+ } else {
297
+ wp_trash_post( $post_id );
298
+ }
299
+ $count++;
300
+ }
301
+
302
+ return $count;
303
+ }
304
+
305
+ /**
306
+ * Check whether Jetpack Contact Form is active
307
+ *
308
+ * @static
309
+ * @since 5.3
310
+ * @return bool True if active, False otherwise
311
+ */
312
+ public static function is_jetpack_contact_active() {
313
+ $jetpack_active_modules = get_option( 'jetpack_active_modules' );
314
+ if ( class_exists( 'Jetpack', false ) && $jetpack_active_modules && in_array( 'contact-form', $jetpack_active_modules ) ) {
315
+ return true;
316
+ }
317
+
318
+ return false;
319
+ }
 
320
  }
321
 
322
  // hooks
include/misc/class-bulk-delete-misc.php CHANGED
@@ -2,94 +2,97 @@
2
  /**
3
  * Utility class for deleting Misc stuff
4
  *
5
- * @package Bulk_Delete
6
- * @subpackage Misc
7
- * @author Sudar
8
  * @since 5.3
 
 
9
  */
 
 
 
10
  class Bulk_Delete_Misc {
11
 
12
- /**
13
- * Slug for *misc* page
14
- *
15
- * @since 5.3
16
- */
17
- const MISC_PAGE_SLUG = 'bulk-delete-misc';
18
-
19
- const VISIBLE_MISC_BOXES = 'metaboxhidden_bulk-delete_page_bulk-delete-misc';
20
-
21
- /**
22
- * Add *misc* menu
23
- *
24
- * @static
25
- * @since 5.3
26
- */
27
- public static function add_menu() {
28
- $bd = BULK_DELETE();
29
-
30
- $bd->misc_page = add_submenu_page(
31
- Bulk_Delete::POSTS_PAGE_SLUG,
32
- __( 'Bulk Delete Miscellaneous Items', 'bulk-delete' ),
33
- __( 'Bulk Delete Misc', 'bulk-delete' ),
34
- 'delete_posts',
35
- self::MISC_PAGE_SLUG,
36
- array( __CLASS__, 'display_misc_page' )
37
- );
38
-
39
- // enqueue JavaScript
40
- add_action( 'admin_print_scripts-' . $bd->misc_page, array( $bd, 'add_script') );
41
-
42
- // delete menus page
43
  add_action( "load-{$bd->misc_page}", array( __CLASS__, 'add_delete_misc_settings_panel' ) );
44
- add_action( "add_meta_boxes_{$bd->misc_page}", array( __CLASS__, 'add_delete_misc_meta_boxes' ) );
45
- }
46
-
47
- /**
48
- * Add settings Panel for delete misc page
49
- *
50
- * @static
51
- * @since 5.3
52
- */
53
- public static function add_delete_misc_settings_panel() {
54
- $bd = BULK_DELETE();
55
-
56
- /**
57
- * Add contextual help for admin screens
58
- *
59
- * @since 5.3
60
- */
61
- do_action( 'bd_add_contextual_help', $bd->misc_page );
62
-
63
- /* Trigger the add_meta_boxes hooks to allow meta boxes to be added */
64
- do_action( 'add_meta_boxes_' . $bd->misc_page, null );
65
-
66
- /* Enqueue WordPress' script for handling the meta boxes */
67
- wp_enqueue_script( 'postbox' );
68
- }
69
-
70
- /**
71
- * Register meta boxes for delete misc page
72
- *
73
- * @static
74
- * @since 5.3
75
- */
76
- public static function add_delete_misc_meta_boxes() {
77
- /**
78
- * Add meta box in misc page
79
- * This hook can be used for adding additional meta boxes in *misc* page
80
- *
81
- * @since 5.3
82
- */
83
- do_action( 'bd_add_meta_box_for_misc' );
84
- }
85
-
86
- /**
87
- * Show the delete misc page
88
- *
89
- * @static
90
- * @since 5.3
91
- */
92
- public static function display_misc_page() {
 
93
  ?>
94
  <div class="wrap">
95
  <h2><?php _e( 'Bulk Delete Miscellaneous Items', 'bulk-delete' );?></h2>
@@ -97,17 +100,17 @@ class Bulk_Delete_Misc {
97
 
98
  <form method = "post">
99
  <?php
100
- // nonce for bulk delete
101
- wp_nonce_field( 'sm-bulk-delete-misc', 'sm-bulk-delete-misc-nonce' );
102
 
103
- /* Used to save closed meta boxes and their order */
104
- wp_nonce_field( 'meta-box-order', 'meta-box-order-nonce', false );
105
- wp_nonce_field( 'closedpostboxes', 'closedpostboxesnonce', false );
106
  ?>
107
  <div id = "poststuff">
108
  <div id="post-body" class="metabox-holder columns-2">
109
 
110
- <div class="updated" >
111
  <p><strong><?php _e( 'WARNING: Posts deleted once cannot be retrieved back. Use with caution.', 'bulk-delete' ); ?></strong></p>
112
  </div>
113
 
@@ -125,46 +128,46 @@ class Bulk_Delete_Misc {
125
  </div><!-- .wrap -->
126
 
127
  <?php
128
- /**
129
- * Runs just before displaying the footer text in the "Bulk Delete Misc" admin page.
130
- *
131
- * This action is primarily for adding extra content in the footer of "Bulk Delete Misc" admin page.
132
- *
133
- * @since 5.3
134
- */
135
- do_action( 'bd_admin_footer_misc_page' );
136
- }
137
-
138
- /**
139
- * Check whether the meta box in misc page is hidden or not
140
- *
141
- * @static
142
- * @access private
143
- * @since 5.3
144
- * @param string $box The name of the box to check
145
- * @return bool True if the box is hidden, False otherwise
146
- */
147
- public static function is_misc_box_hidden( $box ) {
148
- $hidden_boxes = self::get_misc_hidden_boxes();
149
- return ( is_array( $hidden_boxes ) && in_array( $box, $hidden_boxes ) );
150
- }
151
-
152
- /**
153
- * Get the list of hidden boxes in misc page
154
- *
155
- * @static
156
- * @access private
157
- * @since 5.3
158
- * @return array The array of hidden meta boxes
159
- */
160
- private static function get_misc_hidden_boxes() {
161
- $current_user = wp_get_current_user();
162
- return get_user_meta( $current_user->ID, self::VISIBLE_MISC_BOXES, TRUE );
163
- }
164
  }
165
 
166
  // Add menu
167
- add_action( 'bd_after_primary_menus', array( 'Bulk_Delete_Misc' , 'add_menu' ) );
168
 
169
  // Modify admin footer
170
  add_action( 'bd_admin_footer_misc_page', 'bd_modify_admin_footer' );
2
  /**
3
  * Utility class for deleting Misc stuff
4
  *
 
 
 
5
  * @since 5.3
6
+ * @author Sudar
7
+ * @package BulkDelete\Misc
8
  */
9
+
10
+ defined( 'ABSPATH' ) || exit; // Exit if accessed directly
11
+
12
  class Bulk_Delete_Misc {
13
 
14
+ /**
15
+ * Slug for *misc* page
16
+ *
17
+ * @since 5.3
18
+ */
19
+ const MISC_PAGE_SLUG = 'bulk-delete-misc';
20
+
21
+ const VISIBLE_MISC_BOXES = 'metaboxhidden_bulk-delete_page_bulk-delete-misc';
22
+
23
+ /**
24
+ * Add *misc* menu
25
+ *
26
+ * @static
27
+ * @since 5.3
28
+ */
29
+ public static function add_menu() {
30
+ $bd = BULK_DELETE();
31
+
32
+ $bd->misc_page = add_submenu_page(
33
+ Bulk_Delete::POSTS_PAGE_SLUG,
34
+ __( 'Bulk Delete Miscellaneous Items', 'bulk-delete' ),
35
+ __( 'Bulk Delete Misc', 'bulk-delete' ),
36
+ 'delete_posts',
37
+ self::MISC_PAGE_SLUG,
38
+ array( __CLASS__, 'display_misc_page' )
39
+ );
40
+
41
+ // enqueue JavaScript
42
+ add_action( 'admin_print_scripts-' . $bd->misc_page, array( $bd, 'add_script' ) );
43
+
44
+ // delete menus page
45
  add_action( "load-{$bd->misc_page}", array( __CLASS__, 'add_delete_misc_settings_panel' ) );
46
+ add_action( "add_meta_boxes_{$bd->misc_page}", array( __CLASS__, 'add_delete_misc_meta_boxes' ) );
47
+ }
48
+
49
+ /**
50
+ * Add settings Panel for delete misc page
51
+ *
52
+ * @static
53
+ * @since 5.3
54
+ */
55
+ public static function add_delete_misc_settings_panel() {
56
+ $bd = BULK_DELETE();
57
+
58
+ /**
59
+ * Add contextual help for admin screens
60
+ *
61
+ * @since 5.3
62
+ */
63
+ do_action( 'bd_add_contextual_help', $bd->misc_page );
64
+
65
+ /* Trigger the add_meta_boxes hooks to allow meta boxes to be added */
66
+ do_action( 'add_meta_boxes_' . $bd->misc_page, null );
67
+
68
+ /* Enqueue WordPress' script for handling the meta boxes */
69
+ wp_enqueue_script( 'postbox' );
70
+ }
71
+
72
+ /**
73
+ * Register meta boxes for delete misc page
74
+ *
75
+ * @static
76
+ * @since 5.3
77
+ */
78
+ public static function add_delete_misc_meta_boxes() {
79
+
80
+ /**
81
+ * Add meta box in misc page
82
+ * This hook can be used for adding additional meta boxes in *misc* page
83
+ *
84
+ * @since 5.3
85
+ */
86
+ do_action( 'bd_add_meta_box_for_misc' );
87
+ }
88
+
89
+ /**
90
+ * Show the delete misc page
91
+ *
92
+ * @static
93
+ * @since 5.3
94
+ */
95
+ public static function display_misc_page() {
96
  ?>
97
  <div class="wrap">
98
  <h2><?php _e( 'Bulk Delete Miscellaneous Items', 'bulk-delete' );?></h2>
100
 
101
  <form method = "post">
102
  <?php
103
+ // nonce for bulk delete
104
+ wp_nonce_field( 'sm-bulk-delete-misc', 'sm-bulk-delete-misc-nonce' );
105
 
106
+ /* Used to save closed meta boxes and their order */
107
+ wp_nonce_field( 'meta-box-order', 'meta-box-order-nonce', false );
108
+ wp_nonce_field( 'closedpostboxes', 'closedpostboxesnonce', false );
109
  ?>
110
  <div id = "poststuff">
111
  <div id="post-body" class="metabox-holder columns-2">
112
 
113
+ <div class="notice notice-warning">
114
  <p><strong><?php _e( 'WARNING: Posts deleted once cannot be retrieved back. Use with caution.', 'bulk-delete' ); ?></strong></p>
115
  </div>
116
 
128
  </div><!-- .wrap -->
129
 
130
  <?php
131
+ /**
132
+ * Runs just before displaying the footer text in the "Bulk Delete Misc" admin page.
133
+ *
134
+ * This action is primarily for adding extra content in the footer of "Bulk Delete Misc" admin page.
135
+ *
136
+ * @since 5.3
137
+ */
138
+ do_action( 'bd_admin_footer_misc_page' );
139
+ }
140
+
141
+ /**
142
+ * Check whether the meta box in misc page is hidden or not
143
+ *
144
+ * @static
145
+ * @access private
146
+ * @since 5.3
147
+ * @param string $box The name of the box to check
148
+ * @return bool True if the box is hidden, False otherwise
149
+ */
150
+ public static function is_misc_box_hidden( $box ) {
151
+ $hidden_boxes = self::get_misc_hidden_boxes();
152
+ return is_array( $hidden_boxes ) && in_array( $box, $hidden_boxes );
153
+ }
154
+
155
+ /**
156
+ * Get the list of hidden boxes in misc page
157
+ *
158
+ * @static
159
+ * @access private
160
+ * @since 5.3
161
+ * @return array The array of hidden meta boxes
162
+ */
163
+ private static function get_misc_hidden_boxes() {
164
+ $current_user = wp_get_current_user();
165
+ return get_user_meta( $current_user->ID, self::VISIBLE_MISC_BOXES, true );
166
+ }
167
  }
168
 
169
  // Add menu
170
+ add_action( 'bd_after_primary_menus', array( 'Bulk_Delete_Misc', 'add_menu' ) );
171
 
172
  // Modify admin footer
173
  add_action( 'bd_admin_footer_misc_page', 'bd_modify_admin_footer' );
include/pages/class-bulk-delete-pages.php ADDED
@@ -0,0 +1,207 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Utility class for deleting pages
4
+ *
5
+ * @since 5.0
6
+ * @author Sudar
7
+ * @package BulkDelete
8
+ */
9
+
10
+ defined( 'ABSPATH' ) || exit; // Exit if accessed directly
11
+
12
+ class Bulk_Delete_Pages {
13
+
14
+ /**
15
+ * Render delete pages by page status box
16
+ *
17
+ * @access public
18
+ * @static
19
+ * @since 5.0
20
+ */
21
+ public static function render_delete_pages_by_status_box() {
22
+ if ( BD_Util::is_pages_box_hidden( Bulk_Delete::BOX_PAGE_STATUS ) ) {
23
+ printf( __( 'This section just got enabled. Kindly <a href = "%1$s">refresh</a> the page to fully enable it.', 'bulk-delete' ), 'admin.php?page=' . Bulk_Delete::PAGES_PAGE_SLUG );
24
+ return;
25
+ }
26
+
27
+ $pages_count = wp_count_posts( 'page' );
28
+ $pages = $pages_count->publish;
29
+ $page_drafts = $pages_count->draft;
30
+ $page_future = $pages_count->future;
31
+ $page_pending = $pages_count->pending;
32
+ $page_private = $pages_count->private;
33
+ ?>
34
+ <!-- Pages start-->
35
+ <h4><?php _e( 'Select the pages which you want to delete', 'bulk-delete' ); ?></h4>
36
+
37
+ <fieldset class="options">
38
+ <table class="optiontable">
39
+ <tr>
40
+ <td>
41
+ <input name="smbd_published_pages" value="published_pages" type="checkbox">
42
+ <label for="smbd_published_pages"><?php _e( 'All Published Pages', 'bulk-delete' ); ?> (<?php echo $pages . ' '; _e( 'Pages', 'bulk-delete' ); ?>)</label>
43
+ </td>
44
+ </tr>
45
+
46
+ <tr>
47
+ <td>
48
+ <input name="smbd_draft_pages" value="draft_pages" type="checkbox">
49
+ <label for="smbd_draft_pages"><?php _e( 'All Draft Pages', 'bulk-delete' ); ?> (<?php echo $page_drafts . ' '; _e( 'Pages', 'bulk-delete' ); ?>)</label>
50
+ </td>
51
+ </tr>
52
+
53
+ <tr>
54
+ <td>
55
+ <input name="smbd_future_pages" value="scheduled_pages" type="checkbox">
56
+ <label for="smbd_future_pages"><?php _e( 'All Scheduled Pages', 'bulk-delete' ); ?> (<?php echo $page_future . ' '; _e( 'Pages', 'bulk-delete' ); ?>)</label>
57
+ </td>
58
+ </tr>
59
+
60
+ <tr>
61
+ <td>
62
+ <input name="smbd_pending_pages" value="pending_pages" type="checkbox">
63
+ <label for="smbd_pending_pages"><?php _e( 'All Pending Pages', 'bulk-delete' ); ?> (<?php echo $page_pending . ' '; _e( 'Pages', 'bulk-delete' ); ?>)</label>
64
+ </td>
65
+ </tr>
66
+
67
+ <tr>
68
+ <td>
69
+ <input name="smbd_private_pages" value="private_pages" type="checkbox">
70
+ <label for="smbd_private_pages"><?php _e( 'All Private Pages', 'bulk-delete' ); ?> (<?php echo $page_private . ' '; _e( 'Pages', 'bulk-delete' ); ?>)</label>
71
+ </td>
72
+ </tr>
73
+ </table>
74
+
75
+ <table class="optiontable">
76
+ <?php
77
+ bd_render_filtering_table_header();
78
+ bd_render_restrict_settings( 'pages', 'pages' );
79
+ bd_render_delete_settings( 'pages' );
80
+ bd_render_limit_settings( 'pages' );
81
+ bd_render_cron_settings( 'pages','http://bulkwp.com/addons/scheduler-for-deleting-pages-by-status/?utm_source=wpadmin&utm_campaign=BulkDelete&utm_medium=buynow&utm_content=bd-sp' );
82
+ ?>
83
+ </table>
84
+ </fieldset>
85
+ <?php
86
+ bd_render_submit_button( 'delete_pages_by_status' );
87
+ }
88
+
89
+ /**
90
+ * Request handler for deleting pages by status
91
+ *
92
+ * @since 5.0
93
+ */
94
+ public static function do_delete_pages_by_status() {
95
+ $delete_options = array();
96
+ $delete_options['restrict'] = array_get_bool( $_POST, 'smbd_pages_restrict', false );
97
+ $delete_options['limit_to'] = absint( array_get( $_POST, 'smbd_pages_limit_to', 0 ) );
98
+ $delete_options['force_delete'] = array_get_bool( $_POST, 'smbd_pages_force_delete', false );
99
+
100
+ $delete_options['date_op'] = array_get( $_POST, 'smbd_pages_op' );
101
+ $delete_options['days'] = absint( array_get( $_POST, 'smbd_pages_days' ) );
102
+
103
+ $delete_options['publish'] = array_get( $_POST, 'smbd_published_pages' );
104
+ $delete_options['drafts'] = array_get( $_POST, 'smbd_draft_pages' );
105
+ $delete_options['pending'] = array_get( $_POST, 'smbd_pending_pages' );
106
+ $delete_options['future'] = array_get( $_POST, 'smbd_future_pages' );
107
+ $delete_options['private'] = array_get( $_POST, 'smbd_private_pages' );
108
+
109
+ if ( 'true' == array_get( $_POST, 'smbd_pages_cron', 'false' ) ) {
110
+ $freq = $_POST['smbd_pages_cron_freq'];
111
+ $time = strtotime( $_POST['smbd_pages_cron_start'] ) - ( get_option( 'gmt_offset' ) * 60 * 60 );
112
+
113
+ if ( $freq == -1 ) {
114
+ wp_schedule_single_event( $time, Bulk_Delete::CRON_HOOK_PAGES_STATUS, array( $delete_options ) );
115
+ } else {
116
+ wp_schedule_event( $time, $freq , Bulk_Delete::CRON_HOOK_PAGES_STATUS, array( $delete_options ) );
117
+ }
118
+ $msg = __( 'The selected pages are scheduled for deletion.', 'bulk-delete' ) . ' ' .
119
+ sprintf( __( 'See the full list of <a href = "%s">scheduled tasks</a>' , 'bulk-delete' ), get_bloginfo( 'wpurl' ) . '/wp-admin/admin.php?page=' . Bulk_Delete::CRON_PAGE_SLUG );
120
+ } else {
121
+ $deleted_count = self::delete_pages_by_status( $delete_options );
122
+ $msg = sprintf( _n( 'Deleted %d page', 'Deleted %d pages' , $deleted_count, 'bulk-delete' ), $deleted_count );
123
+ }
124
+
125
+ add_settings_error(
126
+ Bulk_Delete::PAGES_PAGE_SLUG,
127
+ 'deleted-cron',
128
+ $msg,
129
+ 'updated'
130
+ );
131
+ }
132
+
133
+ /**
134
+ * Bulk Delete pages
135
+ *
136
+ * @since 5.0
137
+ * @param array $delete_options
138
+ * @return integer
139
+ */
140
+ public static function delete_pages_by_status( $delete_options ) {
141
+ global $wp_query;
142
+
143
+ // Backward compatibility code. Will be removed in Bulk Delete v6.0
144
+ if ( array_key_exists( 'page_op', $delete_options ) ) {
145
+ $delete_options['date_op'] = $delete_options['page_op'];
146
+ $delete_options['days'] = $delete_options['page_days'];
147
+ }
148
+ $delete_options = apply_filters( 'bd_delete_options', $delete_options );
149
+
150
+ $post_status = array();
151
+
152
+ // published pages
153
+ if ( 'published_pages' == $delete_options['publish'] ) {
154
+ $post_status[] = 'publish';
155
+ }
156
+
157
+ // Drafts
158
+ if ( 'draft_pages' == $delete_options['drafts'] ) {
159
+ $post_status[] = 'draft';
160
+ }
161
+
162
+ // Pending pages
163
+ if ( 'pending_pages' == $delete_options['pending'] ) {
164
+ $post_status[] = 'pending';
165
+ }
166
+
167
+ // Future pages
168
+ if ( 'future_pages' == $delete_options['future'] ) {
169
+ $post_status[] = 'future';
170
+ }
171
+
172
+ // Private pages
173
+ if ( 'private_pages' == $delete_options['private'] ) {
174
+ $post_status[] = 'private';
175
+ }
176
+
177
+ $options = array(
178
+ 'post_type' => 'page',
179
+ 'post_status' => $post_status,
180
+ );
181
+
182
+ $options = bd_build_query_options( $delete_options, $options );
183
+ $pages = $wp_query->query( $options );
184
+ foreach ( $pages as $page ) {
185
+ wp_delete_post( $page->ID, $delete_options['force_delete'] );
186
+ }
187
+
188
+ return count( $pages );
189
+ }
190
+
191
+ /**
192
+ * Filter JS Array and add validation hooks
193
+ *
194
+ * @since 5.4
195
+ * @static
196
+ * @param array $js_array JavaScript Array
197
+ * @return array Modified JavaScript Array
198
+ */
199
+ public static function filter_js_array( $js_array ) {
200
+ $js_array['dt_iterators'][] = '_pages';
201
+ return $js_array;
202
+ }
203
+ }
204
+
205
+ add_action( 'bd_delete_pages_by_status', array( 'Bulk_Delete_Pages', 'do_delete_pages_by_status' ) );
206
+ add_filter( 'bd_javascript_array', array( 'Bulk_Delete_Pages', 'filter_js_array' ) );
207
+ ?>
include/posts/class-bulk-delete-posts.php ADDED
@@ -0,0 +1,1043 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Utility class for deleting posts
4
+ *
5
+ * @author Sudar
6
+ * @package BulkDelete
7
+ */
8
+
9
+ defined( 'ABSPATH' ) || exit; // Exit if accessed directly
10
+
11
+ class Bulk_Delete_Posts {
12
+ /**
13
+ * Render post status box
14
+ */
15
+ public static function render_delete_posts_by_status_box() {
16
+
17
+ if ( BD_Util::is_posts_box_hidden( Bulk_Delete::BOX_POST_STATUS ) ) {
18
+ printf( __( 'This section just got enabled. Kindly <a href = "%1$s">refresh</a> the page to fully enable it.', 'bulk-delete' ), 'admin.php?page=' . Bulk_Delete::POSTS_PAGE_SLUG );
19
+ return;
20
+ }
21
+
22
+ $posts_count = wp_count_posts();
23
+ $publish = $posts_count->publish;
24
+ $drafts = $posts_count->draft;
25
+ $future = $posts_count->future;
26
+ $pending = $posts_count->pending;
27
+ $private = $posts_count->private;
28
+
29
+ $sticky = count( get_option( 'sticky_posts' ) );
30
+ ?>
31
+ <h4><?php _e( 'Select the posts which you want to delete', 'bulk-delete' ); ?></h4>
32
+
33
+ <fieldset class="options">
34
+ <table class="optiontable">
35
+ <tr>
36
+ <td>
37
+ <input name="smbd_publish" id="smbd_publish" value="publish" type="checkbox">
38
+ <label for="smbd_publish"><?php _e( 'All publish posts', 'bulk-delete' ); ?> (<?php echo $publish . ' '; _e( 'Posts', 'bulk-delete' ); ?>)</label>
39
+ </td>
40
+ </tr>
41
+
42
+ <tr>
43
+ <td scope="row">
44
+ <input name="smbd_drafts" id="smbd_drafts" value="drafts" type="checkbox">
45
+ <label for="smbd_drafts"><?php _e( 'All Draft Posts', 'bulk-delete' ); ?> (<?php echo $drafts . ' '; _e( 'Drafts', 'bulk-delete' ); ?>)</label>
46
+ </td>
47
+ </tr>
48
+
49
+ <tr>
50
+ <td>
51
+ <input name="smbd_pending" id="smbd_pending" value="pending" type="checkbox">
52
+ <label for="smbd_pending"><?php _e( 'All Pending posts', 'bulk-delete' ); ?> (<?php echo $pending . ' '; _e( 'Posts', 'bulk-delete' ); ?>)</label>
53
+ </td>
54
+ </tr>
55
+
56
+ <tr>
57
+ <td>
58
+ <input name="smbd_future" id="smbd_future" value="future" type="checkbox">
59
+ <label for="smbd_future"><?php _e( 'All scheduled posts', 'bulk-delete' ); ?> (<?php echo $future . ' '; _e( 'Posts', 'bulk-delete' ); ?>)</label>
60
+ </td>
61
+ </tr>
62
+
63
+ <tr>
64
+ <td>
65
+ <input name="smbd_private" id="smbd_private" value="private" type="checkbox">
66
+ <label for="smbd_private"><?php _e( 'All private posts', 'bulk-delete' ); ?> (<?php echo $private . ' '; _e( 'Posts', 'bulk-delete' ); ?>)</label>
67
+ </td>
68
+ </tr>
69
+
70
+ <tr>
71
+ <td>
72
+ <input name="smbd_sticky" id="smbd_sticky" value="sticky" type="checkbox">
73
+ <label for="smbd_sticky"><?php _e( 'All Sticky posts', 'bulk-delete' ); ?> (<?php echo $sticky . ' '; _e( 'Posts', 'bulk-delete' ); ?>)</label>
74
+ </td>
75
+ </tr>
76
+ </table>
77
+
78
+ <table class="optiontable">
79
+ <?php bd_render_filtering_table_header(); ?>
80
+ <tr>
81
+ <td colspan="2">
82
+ <p><?php _e( 'Note: The date filter will not work for sticky posts', 'bulk-delete' ); ?></p>
83
+ </td>
84
+ </tr>
85
+ <?php bd_render_restrict_settings( 'post_status' ); ?>
86
+ <?php bd_render_delete_settings( 'post_status' ); ?>
87
+ <?php bd_render_limit_settings( 'post_status' ); ?>
88
+ <?php bd_render_cron_settings( 'post_status', 'http://bulkwp.com/addons/scheduler-for-deleting-posts-by-status/?utm_source=wpadmin&utm_campaign=BulkDelete&utm_medium=buynow&utm_content=bd-sps' ); ?>
89
+ </table>
90
+
91
+ </fieldset>
92
+ <?php
93
+ bd_render_submit_button( 'delete_posts_by_status' );
94
+ }
95
+
96
+ /**
97
+ * Delete posts by post status
98
+ *
99
+ * @since 5.0
100
+ * @static
101
+ */
102
+ public static function do_delete_posts_by_status() {
103
+ $delete_options = array();
104
+ $delete_options['restrict'] = array_get_bool( $_POST, 'smbd_post_status_restrict', false );
105
+ $delete_options['limit_to'] = absint( array_get( $_POST, 'smbd_post_status_limit_to', 0 ) );
106
+ $delete_options['force_delete'] = array_get_bool( $_POST, 'smbd_post_status_force_delete', false );
107
+
108
+ $delete_options['date_op'] = array_get( $_POST, 'smbd_post_status_op' );
109
+ $delete_options['days'] = absint( array_get( $_POST, 'smbd_post_status_days' ) );
110
+
111
+ $delete_options['publish'] = array_get( $_POST, 'smbd_publish' );
112
+ $delete_options['drafts'] = array_get( $_POST, 'smbd_drafts' );
113
+ $delete_options['pending'] = array_get( $_POST, 'smbd_pending' );
114
+ $delete_options['future'] = array_get( $_POST, 'smbd_future' );
115
+ $delete_options['private'] = array_get( $_POST, 'smbd_private' );
116
+ $delete_options['sticky'] = array_get( $_POST, 'smbd_sticky' );
117
+
118
+ if ( array_get( $_POST, 'smbd_post_status_cron', 'false' ) == 'true' ) {
119
+ $freq = $_POST['smbd_post_status_cron_freq'];
120
+ $time = strtotime( $_POST['smbd_post_status_cron_start'] ) - ( get_option( 'gmt_offset' ) * 60 * 60 );
121
+
122
+ if ( $freq == -1 ) {
123
+ wp_schedule_single_event( $time, Bulk_Delete::CRON_HOOK_POST_STATUS, array( $delete_options ) );
124
+ } else {
125
+ wp_schedule_event( $time, $freq, Bulk_Delete::CRON_HOOK_POST_STATUS, array( $delete_options ) );
126
+ }
127
+ $msg = __( 'Posts with the selected status are scheduled for deletion.', 'bulk-delete' ) . ' ' .
128
+ sprintf( __( 'See the full list of <a href = "%s">scheduled tasks</a>' , 'bulk-delete' ), get_bloginfo( 'wpurl' ) . '/wp-admin/admin.php?page=' . Bulk_Delete::CRON_PAGE_SLUG );
129
+ } else {
130
+ $deleted_count = self::delete_posts_by_status( $delete_options );
131
+ $msg = sprintf( _n( 'Deleted %d post with the selected post status', 'Deleted %d posts with the selected post status' , $deleted_count, 'bulk-delete' ), $deleted_count );
132
+ }
133
+
134
+ add_settings_error(
135
+ Bulk_Delete::POSTS_PAGE_SLUG,
136
+ 'deleted-posts',
137
+ $msg,
138
+ 'updated'
139
+ );
140
+ }
141
+
142
+ /**
143
+ * Delete posts by post status - drafts, pending posts, scheduled posts etc.
144
+ *
145
+ * @since 5.0
146
+ * @static
147
+ *
148
+ * @param array $delete_options Options for deleting posts
149
+ * @return int $posts_deleted Number of posts that were deleted
150
+ */
151
+ public static function delete_posts_by_status( $delete_options ) {
152
+ global $wpdb;
153
+
154
+ // Backward compatibility code. Will be removed in Bulk Delete v6.0
155
+ if ( array_key_exists( 'post_status_op', $delete_options ) ) {
156
+ $delete_options['date_op'] = $delete_options['post_status_op'];
157
+ $delete_options['days'] = $delete_options['post_status_days'];
158
+ }
159
+
160
+ $delete_options = apply_filters( 'bd_delete_options', $delete_options );
161
+
162
+ $posts_deleted = 0;
163
+
164
+ // Delete sticky posts
165
+ if ( 'sticky' == $delete_options['sticky'] ) {
166
+ $sticky_post_ids = get_option( 'sticky_posts' );
167
+
168
+ foreach ( $sticky_post_ids as $sticky_post_id ) {
169
+ wp_delete_post( $sticky_post_id, $delete_options['force_delete'] );
170
+ }
171
+
172
+ $posts_deleted += count( $sticky_post_ids );
173
+ }
174
+
175
+ $options = array();
176
+ $post_status = array();
177
+
178
+ // Published posts
179
+ if ( 'publish' == $delete_options['publish'] ) {
180
+ $post_status[] = 'publish';
181
+ }
182
+
183
+ // Drafts
184
+ if ( 'drafts' == $delete_options['drafts'] ) {
185
+ $post_status[] = 'draft';
186
+
187
+ // ignore sticky posts.
188
+ // For some reason, sticky posts also gets deleted when deleting drafts through a schedule
189
+ $options['post__not_in'] = get_option( 'sticky_posts' );
190
+ }
191
+
192
+ // Pending Posts
193
+ if ( 'pending' == $delete_options['pending'] ) {
194
+ $post_status[] = 'pending';
195
+ }
196
+
197
+ // Future Posts
198
+ if ( 'future' == $delete_options['future'] ) {
199
+ $post_status[] = 'future';
200
+ }
201
+
202
+ // Private Posts
203
+ if ( 'private' == $delete_options['private'] ) {
204
+ $post_status[] = 'private';
205
+ }
206
+
207
+ $options['post_status'] = $post_status;
208
+ $options = bd_build_query_options( $delete_options, $options );
209
+ $post_ids = bd_query( $options );
210
+ foreach ( $post_ids as $post_id ) {
211
+ wp_delete_post( $post_id, $delete_options['force_delete'] );
212
+ }
213
+
214
+ $posts_deleted += count( $post_ids );
215
+ return $posts_deleted;
216
+ }
217
+
218
+ /**
219
+ * Render Delete posts by category box
220
+ */
221
+ public static function render_delete_posts_by_category_box() {
222
+ if ( BD_Util::is_posts_box_hidden( Bulk_Delete::BOX_CATEGORY ) ) {
223
+ printf( __( 'This section just got enabled. Kindly <a href = "%1$s">refresh</a> the page to fully enable it.', 'bulk-delete' ), 'admin.php?page=' . Bulk_Delete::POSTS_PAGE_SLUG );
224
+ return;
225
+ }
226
+ ?>
227
+ <!-- Category Start-->
228
+ <h4><?php _e( 'Select the post type whose category posts you want to delete', 'bulk-delete' ); ?></h4>
229
+ <fieldset class="options">
230
+ <table class="optiontable">
231
+ <?php bd_render_post_type_dropdown( 'cats' ); ?>
232
+ </table>
233
+
234
+ <h4><?php _e( 'Select the categories whose post you want to delete', 'bulk-delete' ); ?></h4>
235
+ <p><?php _e( 'Note: The post count below for each category is the total number of posts in that category, irrespective of post type', 'bulk-delete' ); ?></p>
236
+ <?php
237
+ $categories = get_categories( array(
238
+ 'hide_empty' => false,
239
+ )
240
+ );
241
+ ?>
242
+ <table class="form-table">
243
+ <tr>
244
+ <td scope="row">
245
+ <select class="select2" name="smbd_cats[]" multiple data-placeholder="<?php _e( 'Select Categories', 'bulk-delete' ); ?>">
246
+ <option value="all"><?php _e( 'All Categories', 'bulk-delete' ); ?></option>
247
+ <?php foreach ( $categories as $category ) { ?>
248
+ <option value="<?php echo $category->cat_ID; ?>"><?php echo $category->cat_name, ' (', $category->count, ' ', __( 'Posts', 'bulk-delete' ), ')'; ?></option>
249
+ <?php } ?>
250
+ </select>
251
+ </td>
252
+ </tr>
253
+ </table>
254
+
255
+ <table class="optiontable">
256
+ <?php bd_render_filtering_table_header(); ?>
257
+ <?php bd_render_restrict_settings( 'cats' ); ?>
258
+ <?php bd_render_delete_settings( 'cats' ); ?>
259
+ <?php bd_render_private_post_settings( 'cats' ); ?>
260
+ <?php bd_render_limit_settings( 'cats' ); ?>
261
+ <?php bd_render_cron_settings( 'cats', 'http://bulkwp.com/addons/scheduler-for-deleting-posts-by-category/?utm_source=wpadmin&utm_campaign=BulkDelete&utm_medium=buynow&utm_content=bd-sc' ); ?>
262
+ </table>
263
+
264
+ </fieldset>
265
+ <?php
266
+ bd_render_submit_button( 'delete_posts_by_category' );
267
+ }
268
+
269
+ /**
270
+ * Process delete posts by category
271
+ *
272
+ * @since 5.0
273
+ * @static
274
+ */
275
+ public static function do_delete_posts_by_category() {
276
+ $delete_options = array();
277
+
278
+ $delete_options['post_type'] = array_get( $_POST, 'smbd_cat_post_type', 'post' );
279
+ $delete_options['selected_cats'] = array_get( $_POST, 'smbd_cats' );
280
+ $delete_options['restrict'] = array_get_bool( $_POST, 'smbd_cats_restrict', false );
281
+ $delete_options['private'] = array_get_bool( $_POST, 'smbd_cats_private', false );
282
+ $delete_options['limit_to'] = absint( array_get( $_POST, 'smbd_cats_limit_to', 0 ) );
283
+ $delete_options['force_delete'] = array_get_bool( $_POST, 'smbd_cats_force_delete', false );
284
+
285
+ $delete_options['date_op'] = array_get( $_POST, 'smbd_cats_op' );
286
+ $delete_options['days'] = absint( array_get( $_POST, 'smbd_cats_days' ) );
287
+
288
+ if ( array_get_bool( $_POST, 'smbd_cats_cron', false ) ) {
289
+ $freq = $_POST['smbd_cats_cron_freq'];
290
+ $time = strtotime( $_POST['smbd_cats_cron_start'] ) - ( get_option( 'gmt_offset' ) * 60 * 60 );
291
+
292
+ if ( $freq == -1 ) {
293
+ wp_schedule_single_event( $time, Bulk_Delete::CRON_HOOK_CATEGORY, array( $delete_options ) );
294
+ } else {
295
+ wp_schedule_event( $time, $freq , Bulk_Delete::CRON_HOOK_CATEGORY, array( $delete_options ) );
296
+ }
297
+
298
+ $msg = __( 'Posts from the selected categories are scheduled for deletion.', 'bulk-delete' ) . ' ' .
299
+ sprintf( __( 'See the full list of <a href = "%s">scheduled tasks</a>' , 'bulk-delete' ), get_bloginfo( 'wpurl' ) . '/wp-admin/admin.php?page=' . Bulk_Delete::CRON_PAGE_SLUG );
300
+ } else {
301
+ $deleted_count = self::delete_posts_by_category( $delete_options );
302
+ $msg = sprintf( _n( 'Deleted %d post from the selected categories', 'Deleted %d posts from the selected categories' , $deleted_count, 'bulk-delete' ), $deleted_count );
303
+ }
304
+
305
+ add_settings_error(
306
+ Bulk_Delete::POSTS_PAGE_SLUG,
307
+ 'deleted-posts',
308
+ $msg,
309
+ 'updated'
310
+ );
311
+ }
312
+
313
+ /**
314
+ * Delete posts by category
315
+ *
316
+ * @since 5.0
317
+ * @static
318
+ * @param array $delete_options Options for deleting posts
319
+ * @return int $posts_deleted Number of posts that were deleted
320
+ */
321
+ public static function delete_posts_by_category( $delete_options ) {
322
+ // Backward compatibility code. Will be removed in Bulk Delete v6.0
323
+ $delete_options['post_type'] = array_get( $delete_options, 'post_type', 'post' );
324
+
325
+ if ( array_key_exists( 'cats_op', $delete_options ) ) {
326
+ $delete_options['date_op'] = $delete_options['cats_op'];
327
+ $delete_options['days'] = $delete_options['cats_days'];
328
+ }
329
+
330
+ $delete_options = apply_filters( 'bd_delete_options', $delete_options );
331
+
332
+ $options = array();
333
+ $selected_cats = $delete_options['selected_cats'];
334
+ if ( in_array( 'all', $selected_cats ) ) {
335
+ $options['category__not__in'] = array(0);
336
+ } else {
337
+ $options['category__in'] = $selected_cats;
338
+ }
339
+
340
+ $options = bd_build_query_options( $delete_options, $options );
341
+ $post_ids = bd_query( $options );
342
+
343
+ foreach ( $post_ids as $post_id ) {
344
+ // $force delete parameter to custom post types doesn't work
345
+ if ( $delete_options['force_delete'] ) {
346
+ wp_delete_post( $post_id, true );
347
+ } else {
348
+ wp_trash_post( $post_id );
349
+ }
350
+ }
351
+
352
+ return count( $post_ids );
353
+ }
354
+
355
+ /**
356
+ * Render delete posts by tag box
357
+ */
358
+ public static function render_delete_posts_by_tag_box() {
359
+ if ( BD_Util::is_posts_box_hidden( Bulk_Delete::BOX_TAG ) ) {
360
+ printf( __( 'This section just got enabled. Kindly <a href = "%1$s">refresh</a> the page to fully enable it.', 'bulk-delete' ), 'admin.php?page=' . Bulk_Delete::POSTS_PAGE_SLUG );
361
+ return;
362
+ }
363
+
364
+ $tags = get_tags();
365
+ if ( count( $tags ) > 0 ) {
366
+ ?>
367
+ <h4><?php _e( 'Select the tags whose post you want to delete', 'bulk-delete' ) ?></h4>
368
+
369
+ <!-- Tags start-->
370
+ <fieldset class="options">
371
+ <table class="form-table">
372
+ <tr>
373
+ <td scope="row" colspan="2">
374
+ <select class="select2" name="smbd_tags[]" multiple data-placeholder="<?php _e( 'Select Tags', 'bulk-delete' ); ?>">
375
+ <option value="all"><?php _e( 'All Tags', 'bulk-delete' ); ?></option>
376
+ <?php foreach ( $tags as $tag ) { ?>
377
+ <option value="<?php echo absint( $tag->term_id ); ?>"><?php echo $tag->name, ' (', $tag->count, ' ', __( 'Posts', 'bulk-delete' ), ')'; ?></option>
378
+ <?php } ?>
379
+ </select>
380
+ </td>
381
+ </tr>
382
+ </table>
383
+
384
+ <table class="optiontable">
385
+ <?php bd_render_filtering_table_header(); ?>
386
+ <?php bd_render_restrict_settings( 'tags' ); ?>
387
+ <?php bd_render_delete_settings( 'tags' ); ?>
388
+ <?php bd_render_private_post_settings( 'tags' ); ?>
389
+ <?php bd_render_limit_settings( 'tags' ); ?>
390
+ <?php bd_render_cron_settings( 'tags', 'http://bulkwp.com/addons/scheduler-for-deleting-posts-by-tag/?utm_source=wpadmin&utm_campaign=BulkDelete&utm_medium=buynow&utm_content=bd-st' ); ?>
391
+ </table>
392
+ </fieldset>
393
+ <?php
394
+ bd_render_submit_button( 'delete_posts_by_tag' );
395
+ } else {
396
+ ?>
397
+ <h4><?php _e( "You don't have any posts assigned to tags in this blog.", 'bulk-delete' ) ?></h4>
398
+ <?php
399
+ }
400
+ }
401
+
402
+ /**
403
+ * Process Delete Posts by tag request
404
+ *
405
+ * @static
406
+ * @since 5.0
407
+ */
408
+ public static function do_delete_posts_by_tag() {
409
+ $delete_options = array();
410
+ $delete_options['selected_tags'] = array_get( $_POST, 'smbd_tags' );
411
+ $delete_options['restrict'] = array_get_bool( $_POST, 'smbd_tags_restrict', false );
412
+ $delete_options['private'] = array_get( $_POST, 'smbd_tags_private' );
413
+ $delete_options['limit_to'] = absint( array_get( $_POST, 'smbd_tags_limit_to', 0 ) );
414
+ $delete_options['force_delete'] = array_get_bool( $_POST, 'smbd_tags_force_delete', false );
415
+
416
+ $delete_options['date_op'] = array_get( $_POST, 'smbd_tags_op' );
417
+ $delete_options['days'] = absint( array_get( $_POST, 'smbd_tags_days' ) );
418
+
419
+ if ( array_get( $_POST, 'smbd_tags_cron', 'false' ) == 'true' ) {
420
+ $freq = $_POST['smbd_tags_cron_freq'];
421
+ $time = strtotime( $_POST['smbd_tags_cron_start'] ) - ( get_option( 'gmt_offset' ) * 60 * 60 );
422
+
423
+ if ( $freq == -1 ) {
424
+ wp_schedule_single_event( $time, Bulk_Delete::CRON_HOOK_TAG, array( $delete_options ) );
425
+ } else {
426
+ wp_schedule_event( $time, $freq, Bulk_Delete::CRON_HOOK_TAG, array( $delete_options ) );
427
+ }
428
+ $msg = __( 'Posts from the selected tags are scheduled for deletion.', 'bulk-delete' ) . ' ' .
429
+ sprintf( __( 'See the full list of <a href = "%s">scheduled tasks</a>' , 'bulk-delete' ), get_bloginfo( 'wpurl' ) . '/wp-admin/admin.php?page=' . Bulk_Delete::CRON_PAGE_SLUG );
430
+ } else {
431
+ $deleted_count = self::delete_posts_by_tag( $delete_options );
432
+ $msg = sprintf( _n( 'Deleted %d post from the selected tags', 'Deleted %d posts from the selected tags' , $deleted_count, 'bulk-delete' ), $deleted_count );
433
+ }
434
+
435
+ add_settings_error(
436
+ Bulk_Delete::POSTS_PAGE_SLUG,
437
+ 'deleted-posts',
438
+ $msg,
439
+ 'updated'
440
+ );
441
+ }
442
+
443
+ /**
444
+ * Delete posts by tag
445
+ *
446
+ * @since 5.0
447
+ * @static
448
+ * @param array $delete_options Options for deleting posts
449
+ * @return int $posts_deleted Number of posts that were deleted
450
+ */
451
+ public static function delete_posts_by_tag( $delete_options ) {
452
+ // Backward compatibility code. Will be removed in Bulk Delete v6.0
453
+ if ( array_key_exists( 'tags_op', $delete_options ) ) {
454
+ $delete_options['date_op'] = $delete_options['tags_op'];
455
+ $delete_options['days'] = $delete_options['tags_days'];
456
+ }
457
+
458
+ $delete_options = apply_filters( 'bd_delete_options', $delete_options );
459
+
460
+ $options = array();
461
+ $selected_tags = $delete_options['selected_tags'];
462
+ if ( in_array( 'all', $selected_tags ) ) {
463
+ $options['tag__not__in'] = array(0);
464
+ } else {
465
+ $options['tag__in'] = $selected_tags;
466
+ }
467
+
468
+ $options = bd_build_query_options( $delete_options, $options );
469
+ $post_ids = bd_query( $options );
470
+ foreach ( $post_ids as $post_id ) {
471
+ wp_delete_post( $post_id, $delete_options['force_delete'] );
472
+ }
473
+
474
+ return count( $post_ids );
475
+ }
476
+
477
+ /**
478
+ * Render delete by custom taxonomy box.
479
+ */
480
+ public static function render_delete_posts_by_taxonomy_box() {
481
+ if ( BD_Util::is_posts_box_hidden( Bulk_Delete::BOX_TAX ) ) {
482
+ printf( __( 'This section just got enabled. Kindly <a href = "%1$s">refresh</a> the page to fully enable it.', 'bulk-delete' ), 'admin.php?page=' . Bulk_Delete::POSTS_PAGE_SLUG );
483
+ return;
484
+ }
485
+
486
+ $taxs = get_taxonomies( array(
487
+ 'public' => true,
488
+ '_builtin' => false
489
+ ), 'objects'
490
+ );
491
+
492
+ $terms_array = array();
493
+ if ( count( $taxs ) > 0 ) {
494
+ foreach ( $taxs as $tax ) {
495
+ $terms = get_terms( $tax->name );
496
+ if ( count( $terms ) > 0 ) {
497
+ $terms_array[$tax->name] = $terms;
498
+ }
499
+ }
500
+ }
501
+
502
+ if ( count( $terms_array ) > 0 ) {
503
+ ?>
504
+ <!-- Custom tax Start-->
505
+ <h4><?php _e( 'Select the post type whose taxonomy posts you want to delete', 'bulk-delete' ); ?></h4>
506
+
507
+ <fieldset class="options">
508
+ <table class="optiontable">
509
+ <?php bd_render_post_type_dropdown( 'tax' ); ?>
510
+ </table>
511
+
512
+ <h4><?php _e( 'Select the taxonomies whose post you want to delete', 'bulk-delete' ) ?></h4>
513
+
514
+ <table class="optiontable">
515
+ <?php
516
+ foreach ( $terms_array as $tax => $terms ) {
517
+ ?>
518
+ <tr>
519
+ <td scope="row" >
520
+ <input name="smbd_taxs" value="<?php echo $tax; ?>" type="radio" class="custom-tax">
521
+ </td>
522
+ <td>
523
+ <label for="smbd_taxs"><?php echo $taxs[$tax]->labels->name; ?> </label>
524
+ </td>
525
+ </tr>
526
+ <?php
527
+ }
528
+ ?>
529
+ </table>
530
+
531
+ <h4><?php _e( 'The selected taxonomy has the following terms. Select the terms whose post you want to delete', 'bulk-delete' ) ?></h4>
532
+ <p><?php _e( 'Note: The post count below for each term is the total number of posts in that term, irrespective of post type', 'bulk-delete' ); ?></p>
533
+ <?php
534
+ foreach ( $terms_array as $tax => $terms ) {
535
+ ?>
536
+ <table class="optiontable terms_<?php echo $tax;?> terms">
537
+ <?php
538
+ foreach ( $terms as $term ) {
539
+ ?>
540
+ <tr>
541
+ <td scope="row" >
542
+ <input name="smbd_tax_terms[]" value="<?php echo $term->slug; ?>" type="checkbox" class="terms">
543
+ </td>
544
+ <td>
545
+ <label for="smbd_tax_terms"><?php echo $term->name; ?> (<?php echo $term->count . ' '; _e( 'Posts', 'bulk-delete' ); ?>)</label>
546
+ </td>
547
+ </tr>
548
+ <?php
549
+ }
550
+ ?>
551
+ </table>
552
+ <?php
553
+ }
554
+ ?>
555
+ <table class="optiontable">
556
+ <?php bd_render_filtering_table_header(); ?>
557
+ <?php bd_render_restrict_settings( 'taxs' ); ?>
558
+ <?php bd_render_delete_settings( 'taxs' ); ?>
559
+ <?php bd_render_private_post_settings( 'taxs' ); ?>
560
+ <?php bd_render_limit_settings( 'taxs' ); ?>
561
+ <?php bd_render_cron_settings( 'taxs', 'http://bulkwp.com/addons/scheduler-for-deleting-posts-by-taxonomy/?utm_source=wpadmin&utm_campaign=BulkDelete&utm_medium=buynow&utm_content=bd-stx' ); ?>
562
+ </table>
563
+
564
+ </fieldset>
565
+ <?php
566
+ bd_render_submit_button( 'delete_posts_by_taxonomy' );
567
+ } else {
568
+ ?>
569
+ <h4><?php _e( "You don't have any posts assigned to custom taxonomies in this blog.", 'bulk-delete' ) ?></h4>
570
+ <?php
571
+ }
572
+ }
573
+
574
+ /**
575
+ * Process Delete posts by Taxonomy Request.
576
+ *
577
+ * @static
578
+ * @since 5.0
579
+ */
580
+ public static function do_delete_posts_by_taxonomy() {
581
+ $delete_options = array();
582
+ $delete_options['post_type'] = array_get( $_POST, 'smbd_tax_post_type', 'post' );
583
+ $delete_options['selected_taxs'] = array_get( $_POST, 'smbd_taxs' );
584
+ $delete_options['selected_tax_terms'] = array_get( $_POST, 'smbd_tax_terms' );
585
+ $delete_options['restrict'] = array_get_bool( $_POST, 'smbd_taxs_restrict', false );
586
+ $delete_options['private'] = array_get_bool( $_POST, 'smbd_taxs_private' );
587
+ $delete_options['limit_to'] = absint( array_get( $_POST, 'smbd_taxs_limit_to', 0 ) );
588
+ $delete_options['force_delete'] = array_get_bool( $_POST, 'smbd_taxs_force_delete', false );
589
+
590
+ $delete_options['date_op'] = array_get( $_POST, 'smbd_taxs_op' );
591
+ $delete_options['days'] = absint( array_get( $_POST, 'smbd_taxs_days' ) );
592
+
593
+ if ( array_get( $_POST, 'smbd_taxs_cron', 'false' ) == 'true' ) {
594
+ $freq = $_POST['smbd_taxs_cron_freq'];
595
+ $time = strtotime( $_POST['smbd_taxs_cron_start'] ) - ( get_option( 'gmt_offset' ) * 60 * 60 );
596
+
597
+ if ( $freq == -1 ) {
598
+ wp_schedule_single_event( $time, Bulk_Delete::CRON_HOOK_TAXONOMY, array( $delete_options ) );
599
+ } else {
600
+ wp_schedule_event( $time, $freq, Bulk_Delete::CRON_HOOK_TAXONOMY, array( $delete_options ) );
601
+ }
602
+ $msg = __( 'Posts from the selected custom taxonomies are scheduled for deletion.', 'bulk-delete' ) . ' ' .
603
+ sprintf( __( 'See the full list of <a href = "%s">scheduled tasks</a>' , 'bulk-delete' ), get_bloginfo( 'wpurl' ) . '/wp-admin/admin.php?page=' . Bulk_Delete::CRON_PAGE_SLUG );
604
+ } else {
605
+ $deleted_count = self::delete_posts_by_taxonomy( $delete_options );
606
+ $msg = sprintf( _n( 'Deleted %d post from the selected custom taxonomies', 'Deleted %d posts from the selected custom taxonomies' , $deleted_count, 'bulk-delete' ), $deleted_count );
607
+ }
608
+
609
+ add_settings_error(
610
+ Bulk_Delete::POSTS_PAGE_SLUG,
611
+ 'deleted-posts',
612
+ $msg,
613
+ 'updated'
614
+ );
615
+ }
616
+
617
+ /**
618
+ * Delete posts by custom taxonomy.
619
+ *
620
+ * @since 5.0
621
+ * @static
622
+ * @param array $delete_options Options for deleting posts
623
+ * @return int $posts_deleted Number of posts that were deleted
624
+ */
625
+ public static function delete_posts_by_taxonomy( $delete_options ) {
626
+ // For compatibility reasons set default post type to 'post'
627
+ $post_type = array_get( $delete_options, 'post_type', 'post' );
628
+
629
+ if ( array_key_exists( 'taxs_op', $delete_options ) ) {
630
+ $delete_options['date_op'] = $delete_options['taxs_op'];
631
+ $delete_options['days'] = $delete_options['taxs_days'];
632
+ }
633
+
634
+ $delete_options = apply_filters( 'bd_delete_options', $delete_options );
635
+
636
+ $selected_taxs = $delete_options['selected_taxs'];
637
+ $selected_tax_terms = $delete_options['selected_tax_terms'];
638
+
639
+ $options = array(
640
+ 'post_status' => 'publish',
641
+ 'post_type' => $post_type,
642
+ 'tax_query' => array(
643
+ array(
644
+ 'taxonomy' => $selected_taxs,
645
+ 'terms' => $selected_tax_terms,
646
+ 'field' => 'slug',
647
+ ),
648
+ )
649
+ );
650
+
651
+ $options = bd_build_query_options( $delete_options, $options );
652
+ $post_ids = bd_query( $options );
653
+ foreach ( $post_ids as $post_id ) {
654
+ // $force delete parameter to custom post types doesn't work
655
+ if ( $delete_options['force_delete'] ) {
656
+ wp_delete_post( $post_id, true );
657
+ } else {
658
+ wp_trash_post( $post_id );
659
+ }
660
+ }
661
+
662
+ return count( $post_ids );
663
+ }
664
+
665
+ /**
666
+ * Render delete by custom post type box.
667
+ *
668
+ * @static
669
+ */
670
+ public static function render_delete_posts_by_post_type_box() {
671
+ if ( BD_Util::is_posts_box_hidden( Bulk_Delete::BOX_POST_TYPE ) ) {
672
+ printf( __( 'This section just got enabled. Kindly <a href = "%1$s">refresh</a> the page to fully enable it.', 'bulk-delete' ), 'admin.php?page=' . Bulk_Delete::POSTS_PAGE_SLUG );
673
+ return;
674
+ }
675
+
676
+ $types_array = array();
677
+
678
+ $types = get_post_types( array(
679
+ '_builtin' => false
680
+ ), 'names'
681
+ );
682
+
683
+ if ( count( $types ) > 0 ) {
684
+ foreach ( $types as $type ) {
685
+ $post_count = wp_count_posts( $type );
686
+ if ( $post_count->publish > 0 ) {
687
+ $types_array["$type-publish"] = $post_count->publish;
688
+ }
689
+ if ( $post_count->future > 0 ) {
690
+ $types_array["$type-future"] = $post_count->future;
691
+ }
692
+ if ( $post_count->pending > 0 ) {
693
+ $types_array["$type-pending"] = $post_count->pending;
694
+ }
695
+ if ( $post_count->draft > 0 ) {
696
+ $types_array["$type-draft"] = $post_count->draft;
697
+ }
698
+ if ( $post_count->private > 0 ) {
699
+ $types_array["$type-private"] = $post_count->private;
700
+ }
701
+ }
702
+ }
703
+
704
+ if ( count( $types_array ) > 0 ) {
705
+ ?>
706
+ <!-- Custom post type Start-->
707
+ <h4><?php _e( 'Select the custom post type whose post you want to delete', 'bulk-delete' ) ?></h4>
708
+
709
+ <fieldset class="options">
710
+ <table class="optiontable">
711
+ <?php
712
+ foreach ( $types_array as $type => $count ) {
713
+ ?>
714
+ <tr>
715
+ <td scope="row" >
716
+ <input name="smbd_types[]" value="<?php echo $type; ?>" type="checkbox">
717
+ </td>
718
+ <td>
719
+ <label for="smbd_types"><?php echo BD_Util::display_post_type_status( $type ), ' (', $count, ')'; ?></label>
720
+ </td>
721
+ </tr>
722
+ <?php
723
+ }
724
+
725
+ bd_render_filtering_table_header();
726
+ bd_render_restrict_settings( 'types' );
727
+ bd_render_delete_settings( 'types' );
728
+ bd_render_limit_settings( 'types' );
729
+ bd_render_cron_settings( 'types', 'http://bulkwp.com/addons/scheduler-for-deleting-posts-by-post-type/?utm_source=wpadmin&utm_campaign=BulkDelete&utm_medium=buynow&utm_content=bd-spt' );
730
+ ?>
731
+ </table>
732
+ </fieldset>
733
+ <?php
734
+ bd_render_submit_button( 'delete_posts_by_post_type' );
735
+ } else {
736
+ printf( '<h4>%s</h4>', __( "You don't have any posts assigned to custom post types in this blog.", 'bulk-delete' ) );
737
+ }
738
+ }
739
+
740
+ /**
741
+ * Process request to delete posts by post type.
742
+ *
743
+ * @static
744
+ * @since 5.0
745
+ */
746
+ public static function do_delete_posts_by_post_type() {
747
+ $delete_options = array();
748
+
749
+ $delete_options['selected_types'] = array_get( $_POST, 'smbd_types' );
750
+ $delete_options['restrict'] = array_get_bool( $_POST, 'smbd_types_restrict', false );
751
+ $delete_options['limit_to'] = absint( array_get( $_POST, 'smbd_types_limit_to', 0 ) );
752
+ $delete_options['force_delete'] = array_get_bool( $_POST, 'smbd_types_force_delete', false );
753
+
754
+ $delete_options['date_op'] = array_get( $_POST, 'smbd_types_op' );
755
+ $delete_options['days'] = absint( array_get( $_POST, 'smbd_types_days' ) );
756
+
757
+ if ( array_get( $_POST, 'smbd_types_cron', 'false' ) == 'true' ) {
758
+ $freq = $_POST['smbd_types_cron_freq'];
759
+ $time = strtotime( $_POST['smbd_types_cron_start'] ) - ( get_option( 'gmt_offset' ) * 60 * 60 );
760
+
761
+ if ( $freq == -1 ) {
762
+ wp_schedule_single_event( $time, Bulk_Delete::CRON_HOOK_POST_TYPE, array( $delete_options ) );
763
+ } else {
764
+ wp_schedule_event( $time, $freq, Bulk_Delete::CRON_HOOK_POST_TYPE, array( $delete_options ) );
765
+ }
766
+
767
+ $msg = __( 'Posts from the selected custom post type are scheduled for deletion.', 'bulk-delete' ) . ' ' .
768
+ sprintf( __( 'See the full list of <a href = "%s">scheduled tasks</a>' , 'bulk-delete' ), get_bloginfo( 'wpurl' ) . '/wp-admin/admin.php?page=' . Bulk_Delete::CRON_PAGE_SLUG );
769
+ } else {
770
+ $deleted_count = self::delete_posts_by_post_type( $delete_options );
771
+ $msg = sprintf( _n( 'Deleted %d post from the selected custom post type', 'Deleted %d posts from the selected custom post type' , $deleted_count, 'bulk-delete' ), $deleted_count );
772
+ }
773
+
774
+ add_settings_error(
775
+ Bulk_Delete::POSTS_PAGE_SLUG,
776
+ 'deleted-posts',
777
+ $msg,
778
+ 'updated'
779
+ );
780
+ }
781
+
782
+ /**
783
+ * Delete posts by custom post type.
784
+ *
785
+ * @static
786
+ * @since 5.0
787
+ * @param array $delete_options Options for deleting posts
788
+ * @return int $posts_deleted Number of posts that were deleted
789
+ */
790
+ public static function delete_posts_by_post_type( $delete_options ) {
791
+ // Backward compatibility code. Will be removed in Bulk Delete v6.0
792
+ if ( array_key_exists( 'types_op', $delete_options ) ) {
793
+ $delete_options['date_op'] = $delete_options['types_op'];
794
+ $delete_options['days'] = $delete_options['types_days'];
795
+ }
796
+
797
+ $delete_options = apply_filters( 'bd_delete_options', $delete_options );
798
+
799
+ $count = 0;
800
+ $selected_types = $delete_options['selected_types'];
801
+
802
+ foreach ( $selected_types as $selected_type ) {
803
+
804
+ $type_status = BD_Util::split_post_type_status( $selected_type );
805
+
806
+ $type = $type_status['type'];
807
+ $status = $type_status['status'];
808
+
809
+ $options = array(
810
+ 'post_status' => $status,
811
+ 'post_type' => $type,
812
+ );
813
+
814
+ $options = bd_build_query_options( $delete_options, $options );
815
+ $post_ids = bd_query( $options );
816
+ foreach ( $post_ids as $post_id ) {
817
+ // $force delete parameter to custom post types doesn't work
818
+ if ( $delete_options['force_delete'] ) {
819
+ wp_delete_post( $post_id, true );
820
+ } else {
821
+ wp_trash_post( $post_id );
822
+ }
823
+ }
824
+
825
+ $count += count( $post_ids );
826
+ }
827
+
828
+ return $count;
829
+ }
830
+
831
+ /**
832
+ * Render delete by url box.
833
+ *
834
+ * @static
835
+ */
836
+ public static function render_delete_posts_by_url_box() {
837
+ if ( BD_Util::is_posts_box_hidden( Bulk_Delete::BOX_URL ) ) {
838
+ printf( __( 'This section just got enabled. Kindly <a href = "%1$s">refresh</a> the page to fully enable it.', 'bulk-delete' ), 'admin.php?page=' . Bulk_Delete::POSTS_PAGE_SLUG );
839
+ return;
840
+ }
841
+ ?>
842
+ <!-- URLs start-->
843
+ <h4><?php _e( 'Delete posts and pages that have the following Permalink', 'bulk-delete' ); ?></h4>
844
+
845
+ <fieldset class="options">
846
+ <table class="optiontable">
847
+ <tr>
848
+ <td scope="row" colspan="2">
849
+ <label for="smdb_specific_pages"><?php _e( 'Enter one post url (not post ids) per line', 'bulk-delete' ); ?></label>
850
+ <br>
851
+ <textarea style="width: 450px; height: 80px;" id="smdb_specific_pages_urls" name="smdb_specific_pages_urls" rows="5" columns="80"></textarea>
852
+ </td>
853
+ </tr>
854
+
855
+ <?php bd_render_filtering_table_header(); ?>
856
+ <?php bd_render_delete_settings( 'specific' ); ?>
857
+
858
+ </table>
859
+ </fieldset>
860
+ <?php
861
+ bd_render_submit_button( 'delete_posts_by_url' );
862
+ }
863
+
864
+ /**
865
+ * Delete posts by url
866
+ *
867
+ * @static
868
+ * @since 5.0
869
+ */
870
+ public static function do_delete_posts_by_url() {
871
+ $force_delete = array_get_bool( $_POST, 'smbd_specific_force_delete', false );
872
+
873
+ $urls = preg_split( '/\r\n|\r|\n/', array_get( $_POST, 'smdb_specific_pages_urls' ) );
874
+ foreach ( $urls as $url ) {
875
+ $checkedurl = $url;
876
+ if ( substr( $checkedurl , 0, 1 ) == '/' ) {
877
+ $checkedurl = get_site_url() . $checkedurl ;
878
+ }
879
+ $postid = url_to_postid( $checkedurl );
880
+ wp_delete_post( $postid, $force_delete );
881
+ }
882
+
883
+ $deleted_count = count( $urls );
884
+ $msg = sprintf( _n( 'Deleted %d post with the specified urls', 'Deleted %d posts with the specified urls' , $deleted_count, 'bulk-delete' ), $deleted_count );
885
+
886
+ add_settings_error(
887
+ Bulk_Delete::POSTS_PAGE_SLUG,
888
+ 'deleted-posts',
889
+ $msg,
890
+ 'updated'
891
+ );
892
+ }
893
+
894
+ /**
895
+ * Render delete by post revisions box
896
+ *
897
+ * @static
898
+ */
899
+ public static function render_posts_by_revision_box() {
900
+ global $wpdb;
901
+
902
+ if ( BD_Util::is_posts_box_hidden( Bulk_Delete::BOX_POST_REVISION ) ) {
903
+ printf( __( 'This section just got enabled. Kindly <a href = "%1$s">refresh</a> the page to fully enable it.', 'bulk-delete' ), 'admin.php?page=' . Bulk_Delete::POSTS_PAGE_SLUG );
904
+ return;
905
+ }
906
+
907
+ $revisions = $wpdb->get_var( "select count(*) from $wpdb->posts where post_type = 'revision'" );
908
+ ?>
909
+ <!-- Post Revisions start-->
910
+ <h4><?php _e( 'Select the posts which you want to delete', 'bulk-delete' ); ?></h4>
911
+
912
+ <fieldset class="options">
913
+ <table class="optiontable">
914
+ <tr>
915
+ <td>
916
+ <input name="smbd_revisions" id ="smbd_revisions" value="revisions" type="checkbox">
917
+ <label for="smbd_revisions"><?php _e( 'All Revisions', 'bulk-delete' ); ?> (<?php echo $revisions . ' '; _e( 'Revisions', 'bulk-delete' ); ?>)</label>
918
+ </td>
919
+ </tr>
920
+
921
+ </table>
922
+ </fieldset>
923
+ <?php
924
+ bd_render_submit_button( 'delete_posts_by_revision' );
925
+ }
926
+
927
+ /**
928
+ * Process delete revisions request
929
+ *
930
+ * @static
931
+ * @since 5.0
932
+ */
933
+ public static function do_delete_posts_by_revision() {
934
+ $delete_options = array( 'revisions' => array_get( $_POST, 'smbd_revisions' ) );
935
+
936
+ $deleted_count = self::delete_posts_by_revision( $delete_options );
937
+
938
+ $msg = sprintf( _n( 'Deleted %d post revision', 'Deleted %d post revisions' , $deleted_count, 'bulk-delete' ), $deleted_count );
939
+
940
+ add_settings_error(
941
+ Bulk_Delete::POSTS_PAGE_SLUG,
942
+ 'deleted-posts',
943
+ $msg,
944
+ 'updated'
945
+ );
946
+ }
947
+
948
+ /**
949
+ * Delete all post revisions
950
+ *
951
+ * @since 5.0
952
+ * @static
953
+ * @param array $delete_options
954
+ * @return int The number of posts that were deleted
955
+ */
956
+ public static function delete_posts_by_revision( $delete_options ) {
957
+ global $wpdb;
958
+
959
+ // Revisions
960
+ if ( 'revisions' == $delete_options['revisions'] ) {
961
+ $revisions = $wpdb->get_results( "select ID from $wpdb->posts where post_type = 'revision'" );
962
+
963
+ foreach ( $revisions as $revision ) {
964
+ wp_delete_post( $revision->ID );
965
+ }
966
+
967
+ return count( $revisions );
968
+ }
969
+
970
+ return 0;
971
+ }
972
+
973
+ /**
974
+ * Filter JS Array and add validation hooks
975
+ *
976
+ * @since 5.4
977
+ * @static
978
+ * @param array $js_array JavaScript Array
979
+ * @return array Modified JavaScript Array
980
+ */
981
+ public static function filter_js_array( $js_array ) {
982
+ $js_array['msg']['deletePostsWarning'] = __( 'Are you sure you want to delete all the posts based on the selected option?', 'bulk-delete' );
983
+ $js_array['msg']['selectPostOption'] = __( 'Please select posts from at least one option', 'bulk-delete' );
984
+
985
+ $js_array['validators']['delete_posts_by_category'] = 'validateSelect2';
986
+ $js_array['error_msg']['delete_posts_by_category'] = 'selectCategory';
987
+ $js_array['msg']['selectCategory'] = __( 'Please select at least one category', 'bulk-delete' );
988
+
989
+ $js_array['validators']['delete_posts_by_tag'] = 'validateSelect2';
990
+ $js_array['error_msg']['delete_posts_by_category'] = 'selectTag';
991
+ $js_array['msg']['selectTag'] = __( 'Please select at least one tag', 'bulk-delete' );
992
+
993
+ $js_array['validators']['delete_posts_by_url'] = 'validateUrl';
994
+ $js_array['error_msg']['delete_posts_by_url'] = 'enterUrl';
995
+ $js_array['msg']['enterUrl'] = __( 'Please enter at least one post url', 'bulk-delete' );
996
+
997
+ $js_array['dt_iterators'][] = '_cats';
998
+ $js_array['dt_iterators'][] = '_tags';
999
+ $js_array['dt_iterators'][] = '_taxs';
1000
+ $js_array['dt_iterators'][] = '_types';
1001
+ $js_array['dt_iterators'][] = '_post_status';
1002
+
1003
+ return $js_array;
1004
+ }
1005
+
1006
+ /**
1007
+ * Process delete cron job request.
1008
+ * This should ideally go in a separate class. But I was
1009
+ * lazy to create a separate class for a single function
1010
+ *
1011
+ * @since 5.0
1012
+ * @static
1013
+ */
1014
+ public static function do_delete_cron() {
1015
+ if ( check_admin_referer( 'sm-bulk-delete-cron', 'sm-bulk-delete-cron-nonce' ) ) {
1016
+ $cron_id = absint( $_GET['cron_id'] );
1017
+ $cron_items = BD_Util::get_cron_schedules();
1018
+ wp_unschedule_event( $cron_items[$cron_id]['timestamp'], $cron_items[$cron_id]['type'], $cron_items[$cron_id]['args'] );
1019
+
1020
+ $msg = __( 'The selected scheduled job was successfully deleted ', 'bulk-delete' );
1021
+
1022
+ add_settings_error(
1023
+ Bulk_Delete::CRON_PAGE_SLUG,
1024
+ 'deleted-cron',
1025
+ $msg,
1026
+ 'updated'
1027
+ );
1028
+ }
1029
+ }
1030
+ }
1031
+
1032
+ // hooks
1033
+ add_action( 'bd_delete_posts_by_status' , array( 'Bulk_Delete_Posts', 'do_delete_posts_by_status' ) );
1034
+ add_action( 'bd_delete_posts_by_category' , array( 'Bulk_Delete_Posts', 'do_delete_posts_by_category' ) );
1035
+ add_action( 'bd_delete_posts_by_tag' , array( 'Bulk_Delete_Posts', 'do_delete_posts_by_tag' ) );
1036
+ add_action( 'bd_delete_posts_by_taxonomy' , array( 'Bulk_Delete_Posts', 'do_delete_posts_by_taxonomy' ) );
1037
+ add_action( 'bd_delete_posts_by_post_type' , array( 'Bulk_Delete_Posts', 'do_delete_posts_by_post_type' ) );
1038
+ add_action( 'bd_delete_posts_by_url' , array( 'Bulk_Delete_Posts', 'do_delete_posts_by_url' ) );
1039
+ add_action( 'bd_delete_posts_by_revision' , array( 'Bulk_Delete_Posts', 'do_delete_posts_by_revision' ) );
1040
+
1041
+ add_action( 'bd_delete_cron' , array( 'Bulk_Delete_Posts', 'do_delete_cron' ) );
1042
+ add_filter( 'bd_javascript_array' , array( 'Bulk_Delete_Posts', 'filter_js_array' ) );
1043
+ ?>
include/settings/class-bd-settings-page.php CHANGED
@@ -2,88 +2,93 @@
2
  /**
3
  * Utility class for Settings page
4
  *
5
- * @package Bulk_Delete
6
- * @subpackage Settings
7
- * @author Sudar
8
  * @since 5.3
 
 
9
  */
 
 
 
10
  class BD_Settings_Page {
11
 
12
- /**
13
- * Slug for settings page
14
- *
15
- * @since 5.3
16
- */
17
- const SETTINGS_PAGE_SLUG = 'bd-settings';
18
-
19
- /**
20
- * Slugs for addon settings
21
- *
22
- * @since 5.3
23
- */
24
- const ADDON_SETTING_OPTION_GROUP = 'bd_addon_settings';
25
- const ADDON_SETTING_OPTION_NAME = 'bd_addon_settings';
26
-
27
- /**
28
- * Add settings menu if needed
29
- *
30
- * @static
31
- * @since 5.3
32
- */
33
- public static function add_menu() {
34
- $settings_page_needed = apply_filters( 'bd_settings_page_needed', FALSE );
35
- if ( ! $settings_page_needed ) {
36
- return;
37
- }
38
-
39
- $bd = BULK_DELETE();
40
-
41
- // add page
42
- $bd->settings_page = add_submenu_page(
43
- Bulk_Delete::POSTS_PAGE_SLUG,
44
- __( 'Bulk Delete Settings', 'bulk-delete' ),
45
- __( 'Settings', 'bulk-delete' ),
46
- 'delete_posts',
47
- self::SETTINGS_PAGE_SLUG,
48
- array( __CLASS__, 'display_settings_page' )
49
- );
50
-
51
- // register settings
52
- register_setting(
53
- self::ADDON_SETTING_OPTION_GROUP, // Option group
54
- self::ADDON_SETTING_OPTION_NAME, // Option name
55
- array( __CLASS__, 'sanitize_settings' ) // Sanitize callback
56
- );
57
- }
58
-
59
- /**
60
- * Sanitize Settings
61
- *
62
- * @static
63
- * @since 5.3
64
- */
65
- public static function sanitize_settings( $input = array() ) {
66
- return apply_filters( 'bd_sanitize_settings_page_fields', $input );
67
- }
68
-
69
- /**
70
- * Return Addon settings
71
- *
72
- * @since 5.3
73
- * @static
74
- */
75
- public static function get_addon_settings() {
76
- $options = get_option( self::ADDON_SETTING_OPTION_NAME, array() );
77
- return apply_filters( 'bd_addon_settings', $options );
78
- }
79
-
80
- /**
81
- * Show the settings page
82
- *
83
- * @static
84
- * @since 5.3
85
- */
86
- public static function display_settings_page() {
 
 
 
87
  ?>
88
  <div class="wrap">
89
  <h2><?php _e( 'Bulk Delete Settings', 'bulk-delete' );?></h2>
@@ -100,8 +105,8 @@ class BD_Settings_Page {
100
  <form method = "post" action="options.php">
101
  <table class="form-table">
102
  <?php
103
- settings_fields( self::ADDON_SETTING_OPTION_GROUP );
104
- do_settings_sections( self::SETTINGS_PAGE_SLUG );
105
  ?>
106
  </table>
107
  <?php submit_button(); ?>
@@ -112,19 +117,19 @@ class BD_Settings_Page {
112
  </div><!-- #poststuff -->
113
  </div><!-- .wrap -->
114
  <?php
115
- /**
116
- * Runs just before displaying the footer text in the "Bulk Delete Settings" admin page.
117
- *
118
- * This action is primarily for adding extra content in the footer of "Bulk Delete Settings" admin page.
119
- *
120
- * @since 5.3
121
- */
122
- do_action( 'bd_admin_footer_settings_page' );
123
- }
124
  }
125
 
126
  // Add menu
127
- add_action( 'bd_before_secondary_menus', array( 'BD_Settings_Page' , 'add_menu' ) );
128
 
129
  // Modify admin footer
130
  add_action( 'bd_admin_footer_settings_page', 'bd_modify_admin_footer' );
2
  /**
3
  * Utility class for Settings page
4
  *
 
 
 
5
  * @since 5.3
6
+ * @author Sudar
7
+ * @package BulkDelete\Admin\Settings
8
  */
9
+
10
+ defined( 'ABSPATH' ) || exit; // Exit if accessed directly
11
+
12
  class BD_Settings_Page {
13
 
14
+ /**
15
+ * Slug for settings page
16
+ *
17
+ * @since 5.3
18
+ */
19
+ const SETTINGS_PAGE_SLUG = 'bd-settings';
20
+
21
+ /**
22
+ * Slugs for addon settings
23
+ *
24
+ * @since 5.3
25
+ */
26
+ const ADDON_SETTING_OPTION_GROUP = 'bd_addon_settings';
27
+ const ADDON_SETTING_OPTION_NAME = 'bd_addon_settings';
28
+
29
+ /**
30
+ * Add settings menu if needed
31
+ *
32
+ * @static
33
+ * @since 5.3
34
+ */
35
+ public static function add_menu() {
36
+ $settings_page_needed = apply_filters( 'bd_settings_page_needed', false );
37
+ if ( ! $settings_page_needed ) {
38
+ return;
39
+ }
40
+
41
+ $bd = BULK_DELETE();
42
+
43
+ // add page
44
+ $bd->settings_page = add_submenu_page(
45
+ Bulk_Delete::POSTS_PAGE_SLUG,
46
+ __( 'Bulk Delete Settings', 'bulk-delete' ),
47
+ __( 'Settings', 'bulk-delete' ),
48
+ 'delete_posts',
49
+ self::SETTINGS_PAGE_SLUG,
50
+ array( __CLASS__, 'display_settings_page' )
51
+ );
52
+
53
+ // register settings
54
+ register_setting(
55
+ self::ADDON_SETTING_OPTION_GROUP, // Option group
56
+ self::ADDON_SETTING_OPTION_NAME, // Option name
57
+ array( __CLASS__, 'sanitize_settings' ) // Sanitize callback
58
+ );
59
+ }
60
+
61
+ /**
62
+ * Sanitize Settings
63
+ *
64
+ * @static
65
+ * @since 5.3
66
+ * @param array $input (optional) Input array
67
+ * @return array Sanitized input
68
+ */
69
+ public static function sanitize_settings( $input = array() ) {
70
+ return apply_filters( 'bd_sanitize_settings_page_fields', $input );
71
+ }
72
+
73
+ /**
74
+ * Return Addon settings
75
+ *
76
+ * @since 5.3
77
+ * @static
78
+ * @return array Addon settings
79
+ */
80
+ public static function get_addon_settings() {
81
+ $options = get_option( self::ADDON_SETTING_OPTION_NAME, array() );
82
+ return apply_filters( 'bd_addon_settings', $options );
83
+ }
84
+
85
+ /**
86
+ * Show the settings page
87
+ *
88
+ * @static
89
+ * @since 5.3
90
+ */
91
+ public static function display_settings_page() {
92
  ?>
93
  <div class="wrap">
94
  <h2><?php _e( 'Bulk Delete Settings', 'bulk-delete' );?></h2>
105
  <form method = "post" action="options.php">
106
  <table class="form-table">
107
  <?php
108
+ settings_fields( self::ADDON_SETTING_OPTION_GROUP );
109
+ do_settings_sections( self::SETTINGS_PAGE_SLUG );
110
  ?>
111
  </table>
112
  <?php submit_button(); ?>
117
  </div><!-- #poststuff -->
118
  </div><!-- .wrap -->
119
  <?php
120
+ /**
121
+ * Runs just before displaying the footer text in the "Bulk Delete Settings" admin page.
122
+ *
123
+ * This action is primarily for adding extra content in the footer of "Bulk Delete Settings" admin page.
124
+ *
125
+ * @since 5.3
126
+ */
127
+ do_action( 'bd_admin_footer_settings_page' );
128
+ }
129
  }
130
 
131
  // Add menu
132
+ add_action( 'bd_before_secondary_menus', array( 'BD_Settings_Page', 'add_menu' ) );
133
 
134
  // Modify admin footer
135
  add_action( 'bd_admin_footer_settings_page', 'bd_modify_admin_footer' );
include/settings/class-bd-settings.php ADDED
@@ -0,0 +1,64 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Encapsulates the settings API for Bulk Delete Plugin
4
+ *
5
+ * @since 5.0
6
+ * @author Sudar
7
+ * @package BulkDelete\Settings
8
+ */
9
+
10
+ defined( 'ABSPATH' ) || exit; // Exit if accessed directly
11
+
12
+ class BD_Settings {
13
+
14
+ /**
15
+ * Register settings used by the plugin
16
+ *
17
+ * @since 5.0
18
+ * @static
19
+ */
20
+ public static function create_settings() {
21
+ register_setting(
22
+ Bulk_Delete::SETTING_OPTION_GROUP, // Option group
23
+ Bulk_Delete::SETTING_OPTION_NAME, // Option name
24
+ array( 'BD_Settings', 'check_license' ) // Sanitize
25
+ );
26
+
27
+ add_settings_section(
28
+ Bulk_Delete::SETTING_SECTION_ID, // ID
29
+ __( 'Add Addon License', 'bulk-delete' ), // Title
30
+ '__return_null', // Callback
31
+ Bulk_Delete::ADDON_PAGE_SLUG // Page
32
+ );
33
+
34
+ /**
35
+ * Runs just after registering license form fields
36
+ *
37
+ * This action is primarily for adding more fields to the license form
38
+ *
39
+ * @since 5.0
40
+ */
41
+ do_action( 'bd_license_field' );
42
+ }
43
+
44
+ /**
45
+ * Callback for sanitizing settings
46
+ *
47
+ * @since 5.0
48
+ * @static
49
+ * @param array $input
50
+ * @return array
51
+ */
52
+ public static function check_license( $input ) {
53
+ /**
54
+ * Filter license form inputs
55
+ *
56
+ * @since 5.0
57
+ */
58
+ return apply_filters( 'bd_license_input', $input );
59
+ }
60
+ }
61
+
62
+ // hooks
63
+ add_action( 'admin_init', array( 'BD_Settings', 'create_settings' ), 100 );
64
+ ?>
include/settings/setting-helpers.php CHANGED
@@ -3,18 +3,19 @@
3
  * Helper functions for settings API.
4
  * Most of these functions are copied from Easy Digital Downloads
5
  *
6
- * @package Bulk_Delete
7
- * @subpackage Settings
8
- * @author Sudar
9
  * @since 5.3
 
 
10
  */
 
 
11
  /**
12
  * Header Callback
13
  *
14
  * Renders the header.
15
  *
16
  * @since 5.3
17
- * @param array $args Arguments passed by the setting
18
  * @return void
19
  */
20
  function bd_header_callback( $args ) {
@@ -27,17 +28,18 @@ function bd_header_callback( $args ) {
27
  * Renders text fields.
28
  *
29
  * @since 5.3
30
- * @param array $args Arguments passed by the setting
31
  * @return void
32
  */
33
  function bd_text_callback( $args ) {
34
- $option_name = $args['option'];
35
- $bd_options = get_option( $option_name );
36
 
37
- if ( isset( $bd_options[ $args['id'] ] ) )
38
  $value = $bd_options[ $args['id'] ];
39
- else
40
  $value = isset( $args['std'] ) ? $args['std'] : '';
 
41
 
42
  $size = ( isset( $args['size'] ) && ! is_null( $args['size'] ) ) ? $args['size'] : 'regular';
43
  $html = '<input type="text" class="' . $size . '-text" id="' . $option_name . '[' . $args['id'] . ']" name="' . $option_name . '[' . $args['id'] . ']" value="' . esc_attr( stripslashes( $value ) ) . '">';
@@ -52,20 +54,21 @@ function bd_text_callback( $args ) {
52
  * Renders rich editor fields.
53
  *
54
  * @since 5.3
55
- * @param array $args Arguments passed by the setting
56
  */
57
  function bd_rich_editor_callback( $args ) {
58
- $option_name = $args['option'];
59
- $bd_options = get_option( $option_name );
60
 
61
- if ( isset( $bd_options[ $args['id'] ] ) )
62
  $value = $bd_options[ $args['id'] ];
63
- else
64
  $value = isset( $args['std'] ) ? $args['std'] : '';
 
65
 
66
- ob_start();
67
- wp_editor( stripslashes( $value ), $option_name . '_' . $args['id'], array( 'textarea_name' => $option_name . '[' . $args['id'] . ']', 'media_buttons' => FALSE ) );
68
- $html = ob_get_clean();
69
 
70
  $html .= '<br/><label for="' . $option_name . '[' . $args['id'] . ']"> ' . $args['desc'] . '</label>';
71
 
3
  * Helper functions for settings API.
4
  * Most of these functions are copied from Easy Digital Downloads
5
  *
 
 
 
6
  * @since 5.3
7
+ * @author Sudar
8
+ * @package BulkDelete\Settings
9
  */
10
+
11
+
12
  /**
13
  * Header Callback
14
  *
15
  * Renders the header.
16
  *
17
  * @since 5.3
18
+ * @param array $args Arguments passed by the setting
19
  * @return void
20
  */
21
  function bd_header_callback( $args ) {
28
  * Renders text fields.
29
  *
30
  * @since 5.3
31
+ * @param array $args Arguments passed by the setting
32
  * @return void
33
  */
34
  function bd_text_callback( $args ) {
35
+ $option_name = $args['option'];
36
+ $bd_options = get_option( $option_name );
37
 
38
+ if ( isset( $bd_options[ $args['id'] ] ) ) {
39
  $value = $bd_options[ $args['id'] ];
40
+ } else {
41
  $value = isset( $args['std'] ) ? $args['std'] : '';
42
+ }
43
 
44
  $size = ( isset( $args['size'] ) && ! is_null( $args['size'] ) ) ? $args['size'] : 'regular';
45
  $html = '<input type="text" class="' . $size . '-text" id="' . $option_name . '[' . $args['id'] . ']" name="' . $option_name . '[' . $args['id'] . ']" value="' . esc_attr( stripslashes( $value ) ) . '">';
54
  * Renders rich editor fields.
55
  *
56
  * @since 5.3
57
+ * @param array $args Arguments passed by the setting
58
  */
59
  function bd_rich_editor_callback( $args ) {
60
+ $option_name = $args['option'];
61
+ $bd_options = get_option( $option_name );
62
 
63
+ if ( isset( $bd_options[ $args['id'] ] ) ) {
64
  $value = $bd_options[ $args['id'] ];
65
+ } else {
66
  $value = isset( $args['std'] ) ? $args['std'] : '';
67
+ }
68
 
69
+ ob_start();
70
+ wp_editor( stripslashes( $value ), $option_name . '_' . $args['id'], array( 'textarea_name' => $option_name . '[' . $args['id'] . ']', 'media_buttons' => false ) );
71
+ $html = ob_get_clean();
72
 
73
  $html .= '<br/><label for="' . $option_name . '[' . $args['id'] . ']"> ' . $args['desc'] . '</label>';
74
 
include/{class-bulk-delete-system-info.php → system-info/class-bulk-delete-system-info.php} RENAMED
@@ -4,17 +4,13 @@
4
  *
5
  * These are functions are used for exporting data from Bulk Delete.
6
  *
7
- * @package Bulk Delete
8
- * @subpackage Admin/System
9
- * @author Sudar
10
  * @since 5.0
11
  * @note Based on the code from Easy Digital Downloads plugin
12
- */
13
-
14
- // Exit if accessed directly
15
- if ( ! defined( 'ABSPATH' ) ) exit;
16
 
17
- if ( ! class_exists( 'Bulk_Delete_System_Info' ) ) :
18
 
19
  /**
20
  * Encapsulates System info
@@ -22,52 +18,45 @@ if ( ! class_exists( 'Bulk_Delete_System_Info' ) ) :
22
  * @since 5.0
23
  */
24
  class Bulk_Delete_System_Info {
25
- /**
26
- * Shows the system info panel which contains version data and debug info.
27
- * The data for the system info is generated by the Browser class.
28
- *
29
- * @since 5.0
30
- * @static
31
- * @global $wpdb - global object $wpdb Used to query the database using the WordPress Database API
32
- * @return void
33
- */
34
- public static function display_system_info() {
35
- global $wpdb;
36
-
37
- if ( ! class_exists( 'Browser' ) ) {
38
- require_once Bulk_Delete::$PLUGIN_DIR . 'include/libraries/browser.php';
39
- }
40
-
41
- $browser = new Browser();
42
- if ( get_bloginfo( 'version' ) < '3.4' ) {
43
- $theme_data = get_theme_data( get_stylesheet_directory() . '/style.css' );
44
- $theme = $theme_data['Name'] . ' ' . $theme_data['Version'];
45
- } else {
46
- $theme_data = wp_get_theme();
47
- $theme = $theme_data->Name . ' ' . $theme_data->Version;
48
- }
49
-
50
- // Try to identity the hosting provider
51
- $host = false;
52
- if( defined( 'WPE_APIKEY' ) ) {
53
- $host = 'WP Engine';
54
- } elseif( defined( 'PAGELYBIN' ) ) {
55
- $host = 'Pagely';
56
- }
57
  ?>
58
  <div class="wrap">
59
  <h2><?php _e( 'System Information', 'bulk-delete' ); ?></h2>
60
  <?php settings_errors(); ?>
61
 
62
- <form action="<?php echo esc_url( admin_url( 'admin.php?page=' . Bulk_Delete::INFO_PAGE_SLUG ) ); ?>" method="post" dir="ltr">
63
  <div id = "poststuff">
64
  <div id="post-body" class="metabox-holder columns-2">
65
 
66
- <div id="post-body-content">
67
- <div class="updated" >
68
- <p><strong><?php _e( 'Please include this information when posting support requests.', 'bulk-delete' ); ?></strong></p>
69
- </div>
70
- </div><!-- #post-body-content -->
71
 
72
  <div id="postbox-container-1" class="postbox-container">
73
  <iframe frameBorder="0" height = "1500" src = "http://sudarmuthu.com/projects/wordpress/bulk-delete/sidebar.php?color=<?php echo get_user_option( 'admin_color' ); ?>&version=<?php echo Bulk_Delete::VERSION; ?>"></iframe>
@@ -75,50 +64,70 @@ class Bulk_Delete_System_Info {
75
 
76
  <div id="postbox-container-2" class="postbox-container">
77
 
78
- <textarea style="width:800px;height:500px;font-family:Menlo,Monaco,monospace;white-space:pre;" readonly="readonly" onclick="this.focus();this.select()" id="system-info-textarea" name="bulk-delete-sysinfo" title="<?php _e( 'To copy the system info, click below then press Ctrl + C (PC) or Cmd + C (Mac).', 'bulk-delete' ); ?>">
79
  ### Begin System Info ###
80
  <?php
81
- do_action( 'bd_system_info_before' );
82
  ?>
83
 
84
  Multisite: <?php echo is_multisite() ? 'Yes' . "\n" : 'No' . "\n" ?>
85
 
86
  SITE_URL: <?php echo site_url() . "\n"; ?>
87
  HOME_URL: <?php echo home_url() . "\n"; ?>
 
88
 
89
- Bulk Delete Version: <?php echo Bulk_Delete::VERSION . "\n"; ?>
90
- WordPress Version: <?php echo get_bloginfo( 'version' ) . "\n"; ?>
91
  Permalink Structure: <?php echo get_option( 'permalink_structure' ) . "\n"; ?>
92
  Active Theme: <?php echo $theme . "\n"; ?>
93
- <?php if( $host ) : ?>
94
- Host: <?php echo $host . "\n"; ?>
95
- <?php endif; ?>
96
-
97
- Registered Post types <?php echo implode( ', ', get_post_types() ) . "\n\n"; ?>
 
98
 
99
- <?php echo $browser ; ?>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
100
 
 
 
101
  PHP Version: <?php echo PHP_VERSION . "\n"; ?>
102
- MySQL Version: <?php echo mysql_get_server_info() . "\n"; ?>
103
  Web Server Info: <?php echo $_SERVER['SERVER_SOFTWARE'] . "\n"; ?>
104
 
105
  WordPress Memory Limit: <?php echo WP_MEMORY_LIMIT; ?><?php echo "\n"; ?>
 
106
  PHP Memory Limit: <?php echo ini_get( 'memory_limit' ) . "\n"; ?>
107
 
108
- PHP Safe Mode: <?php echo ini_get( 'safe_mode' ) ? "Yes" : "No\n"; ?>
 
 
 
 
 
 
109
  PHP Upload Max Size: <?php echo ini_get( 'upload_max_filesize' ) . "\n"; ?>
110
  PHP Post Max Size: <?php echo ini_get( 'post_max_size' ) . "\n"; ?>
111
  PHP Upload Max Filesize: <?php echo ini_get( 'upload_max_filesize' ) . "\n"; ?>
112
  PHP Time Limit: <?php echo ini_get( 'max_execution_time' ) . "\n"; ?>
113
  PHP Max Input Vars: <?php echo ini_get( 'max_input_vars' ) . "\n"; ?>
114
  PHP Arg Separator: <?php echo ini_get( 'arg_separator.output' ) . "\n"; ?>
115
- PHP Allow URL File Open: <?php echo ini_get( 'allow_url_fopen' ) ? "Yes" : "No\n"; ?>
116
-
117
- WP_DEBUG: <?php echo defined( 'WP_DEBUG' ) ? WP_DEBUG ? 'Enabled' . "\n" : 'Disabled' . "\n" : 'Not set' . "\n" ?>
118
- DISABLE_WP_CRON: <?php echo defined( 'DISABLE_WP_CRON' ) ? DISABLE_WP_CRON ? 'Yes' . "\n" : 'No' . "\n" : 'Not set' . "\n" ?>
119
- EMPTY_TRASH_DAYS: <?php echo defined( 'EMPTY_TRASH_DAYS' ) ? EMPTY_TRASH_DAYS : 'Not set' . "\n" ?>
120
 
121
- WP Table Prefix: <?php echo "Length: ". strlen( $wpdb->prefix ); echo " Status:"; if ( strlen( $wpdb->prefix )>16 ) {echo " ERROR: Too Long";} else {echo " Acceptable";} echo "\n"; ?>
122
 
123
  Session: <?php echo isset( $_SESSION ) ? 'Enabled' : 'Disabled'; ?><?php echo "\n"; ?>
124
  Session Name: <?php echo esc_html( ini_get( 'session.name' ) ); ?><?php echo "\n"; ?>
@@ -136,39 +145,41 @@ SUHOSIN: <?php echo ( extension_loaded( 'suhosin' ) ) ? 'Your s
136
  ACTIVE PLUGINS:
137
 
138
  <?php
139
- $plugins = get_plugins();
140
- $active_plugins = get_option( 'active_plugins', array() );
141
 
142
- foreach ( $plugins as $plugin_path => $plugin ) {
143
- // If the plugin isn't active, don't show it.
144
- if ( ! in_array( $plugin_path, $active_plugins ) )
145
- continue;
 
146
 
147
- echo $plugin['Name'] . ': ' . $plugin['Version'] ."\n";
148
- }
149
 
150
- if ( is_multisite() ) {
151
  ?>
152
 
153
  NETWORK ACTIVE PLUGINS:
154
 
155
  <?php
156
- $plugins = wp_get_active_network_plugins();
157
- $active_plugins = get_site_option( 'active_sitewide_plugins', array() );
158
 
159
- foreach ( $plugins as $plugin_path ) {
160
- $plugin_base = plugin_basename( $plugin_path );
161
 
162
- // If the plugin isn't active, don't show it.
163
- if ( ! array_key_exists( $plugin_base, $active_plugins ) )
164
- continue;
 
165
 
166
- $plugin = get_plugin_data( $plugin_path );
167
 
168
- echo $plugin['Name'] . ' :' . $plugin['Version'] ."\n";
169
- }
170
- }
171
- do_action( 'bd_system_info_after' );
172
  ?>
173
  ### End System Info ###</textarea>
174
  <p class="submit">
@@ -181,33 +192,32 @@ NETWORK ACTIVE PLUGINS:
181
  </form>
182
  </div><!-- .wrap -->
183
  <?php
184
- /**
185
- * Runs just before displaying the footer text in the "System Info" admin page.
186
- *
187
- * This action is primarily for adding extra content in the footer of "System Info" admin page.
188
- *
189
- * @since 5.0
190
- */
191
- do_action( 'bd_admin_footer_info_page' );
192
- }
193
-
194
- /**
195
- * Generates the System Info Download File
196
- *
197
- * @since 5.0
198
- * @return void
199
- */
200
- public static function generate_sysinfo_download() {
201
- nocache_headers();
202
-
203
- header( "Content-type: text/plain" );
204
- header( 'Content-Disposition: attachment; filename="bulk-delete-system-info.txt"' );
205
-
206
- echo wp_strip_all_tags( $_POST['bulk-delete-sysinfo'] );
207
- die();
208
- }
209
  }
210
- endif;
211
 
212
  add_action( 'bd_download_sysinfo', array( 'Bulk_Delete_System_Info', 'generate_sysinfo_download' ) );
213
  ?>
4
  *
5
  * These are functions are used for exporting data from Bulk Delete.
6
  *
 
 
 
7
  * @since 5.0
8
  * @note Based on the code from Easy Digital Downloads plugin
9
+ * @author Sudar
10
+ * @package BulkDelete\Admin
11
+ */
 
12
 
13
+ defined( 'ABSPATH' ) || exit; // Exit if accessed directly
14
 
15
  /**
16
  * Encapsulates System info
18
  * @since 5.0
19
  */
20
  class Bulk_Delete_System_Info {
21
+ /**
22
+ * Shows the system info panel which contains version data and debug info.
23
+ * The data for the system info is generated by the Browser class.
24
+ *
25
+ * @since 5.0
26
+ * @static
27
+ * @global $wpdb - global object $wpdb Used to query the database using the WordPress Database API
28
+ * @return void
29
+ */
30
+ public static function display_system_info() {
31
+ global $wpdb;
32
+
33
+ if ( get_bloginfo( 'version' ) < '3.4' ) {
34
+ $theme_data = get_theme_data( get_stylesheet_directory() . '/style.css' );
35
+ $theme = $theme_data['Name'] . ' ' . $theme_data['Version'];
36
+ } else {
37
+ $theme_data = wp_get_theme();
38
+ $theme = $theme_data->Name . ' ' . $theme_data->Version;
39
+ }
40
+
41
+ // Try to identity the hosting provider
42
+ $host = false;
43
+ if ( defined( 'WPE_APIKEY' ) ) {
44
+ $host = 'WP Engine';
45
+ } elseif ( defined( 'PAGELYBIN' ) ) {
46
+ $host = 'Pagely';
47
+ }
 
 
 
 
 
48
  ?>
49
  <div class="wrap">
50
  <h2><?php _e( 'System Information', 'bulk-delete' ); ?></h2>
51
  <?php settings_errors(); ?>
52
 
53
+ <form action="<?php echo esc_url( admin_url( 'admin.php?page=' . Bulk_Delete::INFO_PAGE_SLUG ) ); ?>" method="post">
54
  <div id = "poststuff">
55
  <div id="post-body" class="metabox-holder columns-2">
56
 
57
+ <div class="updated" >
58
+ <p><strong><?php _e( 'Please include this information when posting support requests.', 'bulk-delete' ); ?></strong></p>
59
+ </div>
 
 
60
 
61
  <div id="postbox-container-1" class="postbox-container">
62
  <iframe frameBorder="0" height = "1500" src = "http://sudarmuthu.com/projects/wordpress/bulk-delete/sidebar.php?color=<?php echo get_user_option( 'admin_color' ); ?>&version=<?php echo Bulk_Delete::VERSION; ?>"></iframe>
64
 
65
  <div id="postbox-container-2" class="postbox-container">
66
 
67
+ <textarea wrap="off" style="width:100%;height:500px;font-family:Menlo,Monaco,monospace;white-space:pre;" readonly="readonly" onclick="this.focus();this.select()" id="system-info-textarea" name="bulk-delete-sysinfo" title="<?php _e( 'To copy the system info, click below then press Ctrl + C (PC) or Cmd + C (Mac).', 'bulk-delete' ); ?>">
68
  ### Begin System Info ###
69
  <?php
70
+ do_action( 'bd_system_info_before' );
71
  ?>
72
 
73
  Multisite: <?php echo is_multisite() ? 'Yes' . "\n" : 'No' . "\n" ?>
74
 
75
  SITE_URL: <?php echo site_url() . "\n"; ?>
76
  HOME_URL: <?php echo home_url() . "\n"; ?>
77
+ Browser: <?php echo esc_html( $_SERVER['HTTP_USER_AGENT'] ), "\n"; ?>
78
 
 
 
79
  Permalink Structure: <?php echo get_option( 'permalink_structure' ) . "\n"; ?>
80
  Active Theme: <?php echo $theme . "\n"; ?>
81
+ GMT Offset: <?php echo esc_html( get_option( 'gmt_offset' ) ), "\n\n"; ?>
82
+ <?php
83
+ if ( false !== $host ) { ?>
84
+ Host: <?php echo $host . "\n\n"; ?>
85
+ <?php
86
+ }
87
 
88
+ $post_types = get_post_types();
89
+ ?>
90
+ Registered Post types: <?php echo implode( ', ', $post_types ) . "\n"; ?>
91
+ <?php
92
+ foreach ( $post_types as $post_type ) {
93
+ echo $post_type;
94
+ if ( strlen( $post_type ) < 26 ) {
95
+ echo str_repeat( ' ', 26 - strlen( $post_type ) );
96
+ }
97
+ $post_count = wp_count_posts( $post_type );
98
+ foreach ( $post_count as $key => $value ) {
99
+ echo $key, '=', $value, ', ';
100
+ }
101
+ echo "\n";
102
+ }
103
+ ?>
104
 
105
+ Bulk Delete Version: <?php echo Bulk_Delete::VERSION . "\n"; ?>
106
+ WordPress Version: <?php echo get_bloginfo( 'version' ) . "\n"; ?>
107
  PHP Version: <?php echo PHP_VERSION . "\n"; ?>
108
+ MySQL Version: <?php echo $wpdb->db_version() . "\n"; ?>
109
  Web Server Info: <?php echo $_SERVER['SERVER_SOFTWARE'] . "\n"; ?>
110
 
111
  WordPress Memory Limit: <?php echo WP_MEMORY_LIMIT; ?><?php echo "\n"; ?>
112
+ WordPress Max Limit: <?php echo WP_MAX_MEMORY_LIMIT; ?><?php echo "\n"; ?>
113
  PHP Memory Limit: <?php echo ini_get( 'memory_limit' ) . "\n"; ?>
114
 
115
+ SAVEQUERIES: <?php echo defined( 'SAVEQUERIES' ) ? SAVEQUERIES ? 'Enabled' . "\n" : 'Disabled' . "\n" : 'Not set' . "\n" ?>
116
+ WP_DEBUG: <?php echo defined( 'WP_DEBUG' ) ? WP_DEBUG ? 'Enabled' . "\n" : 'Disabled' . "\n" : 'Not set' . "\n" ?>
117
+ WP_SCRIPT_DEBUG: <?php echo defined( 'WP_SCRIPT_DEBUG' ) ? WP_SCRIPT_DEBUG ? 'Enabled' . "\n" : 'Disabled' . "\n" : 'Not set' . "\n" ?>
118
+ DISABLE_WP_CRON: <?php echo defined( 'DISABLE_WP_CRON' ) ? DISABLE_WP_CRON ? 'Yes' . "\n" : 'No' . "\n" : 'Not set' . "\n" ?>
119
+ EMPTY_TRASH_DAYS: <?php echo defined( 'EMPTY_TRASH_DAYS' ) ? EMPTY_TRASH_DAYS : 'Not set', "\n" ?>
120
+
121
+ PHP Safe Mode: <?php echo ini_get( 'safe_mode' ) ? 'Yes' : 'No', "\n"; ?>
122
  PHP Upload Max Size: <?php echo ini_get( 'upload_max_filesize' ) . "\n"; ?>
123
  PHP Post Max Size: <?php echo ini_get( 'post_max_size' ) . "\n"; ?>
124
  PHP Upload Max Filesize: <?php echo ini_get( 'upload_max_filesize' ) . "\n"; ?>
125
  PHP Time Limit: <?php echo ini_get( 'max_execution_time' ) . "\n"; ?>
126
  PHP Max Input Vars: <?php echo ini_get( 'max_input_vars' ) . "\n"; ?>
127
  PHP Arg Separator: <?php echo ini_get( 'arg_separator.output' ) . "\n"; ?>
128
+ PHP Allow URL File Open: <?php echo ini_get( 'allow_url_fopen' ) ? 'Yes' : 'No', "\n"; ?>
 
 
 
 
129
 
130
+ WP Table Prefix: <?php echo 'Length: '. strlen( $wpdb->prefix ), "\n";?>
131
 
132
  Session: <?php echo isset( $_SESSION ) ? 'Enabled' : 'Disabled'; ?><?php echo "\n"; ?>
133
  Session Name: <?php echo esc_html( ini_get( 'session.name' ) ); ?><?php echo "\n"; ?>
145
  ACTIVE PLUGINS:
146
 
147
  <?php
148
+ $plugins = get_plugins();
149
+ $active_plugins = get_option( 'active_plugins', array() );
150
 
151
+ foreach ( $plugins as $plugin_path => $plugin ) {
152
+ // If the plugin isn't active, don't show it.
153
+ if ( ! in_array( $plugin_path, $active_plugins ) ) {
154
+ continue;
155
+ }
156
 
157
+ echo $plugin['Name'] . ': ' . $plugin['Version'] ."\n";
158
+ }
159
 
160
+ if ( is_multisite() ) {
161
  ?>
162
 
163
  NETWORK ACTIVE PLUGINS:
164
 
165
  <?php
166
+ $plugins = wp_get_active_network_plugins();
167
+ $active_plugins = get_site_option( 'active_sitewide_plugins', array() );
168
 
169
+ foreach ( $plugins as $plugin_path ) {
170
+ $plugin_base = plugin_basename( $plugin_path );
171
 
172
+ // If the plugin isn't active, don't show it.
173
+ if ( ! array_key_exists( $plugin_base, $active_plugins ) ) {
174
+ continue;
175
+ }
176
 
177
+ $plugin = get_plugin_data( $plugin_path );
178
 
179
+ echo $plugin['Name'] . ' :' . $plugin['Version'] ."\n";
180
+ }
181
+ }
182
+ do_action( 'bd_system_info_after' );
183
  ?>
184
  ### End System Info ###</textarea>
185
  <p class="submit">
192
  </form>
193
  </div><!-- .wrap -->
194
  <?php
195
+ /**
196
+ * Runs just before displaying the footer text in the "System Info" admin page.
197
+ *
198
+ * This action is primarily for adding extra content in the footer of "System Info" admin page.
199
+ *
200
+ * @since 5.0
201
+ */
202
+ do_action( 'bd_admin_footer_info_page' );
203
+ }
204
+
205
+ /**
206
+ * Generates the System Info Download File
207
+ *
208
+ * @since 5.0
209
+ * @return void
210
+ */
211
+ public static function generate_sysinfo_download() {
212
+ nocache_headers();
213
+
214
+ header( 'Content-type: text/plain' );
215
+ header( 'Content-Disposition: attachment; filename="bulk-delete-system-info.txt"' );
216
+
217
+ echo wp_strip_all_tags( $_POST['bulk-delete-sysinfo'] );
218
+ die();
219
+ }
220
  }
 
221
 
222
  add_action( 'bd_download_sysinfo', array( 'Bulk_Delete_System_Info', 'generate_sysinfo_download' ) );
223
  ?>
include/ui/admin-ui.php ADDED
@@ -0,0 +1,87 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Customize admin UI for Bulk Delete plugin
4
+ *
5
+ * @since 5.0
6
+ * @author Sudar
7
+ * @package BulkDelete\Admin
8
+ */
9
+
10
+ defined( 'ABSPATH' ) || exit; // Exit if accessed directly
11
+
12
+ /**
13
+ * Add rating links to the admin dashboard
14
+ *
15
+ * @since 5.0
16
+ * @param string $footer_text The existing footer text
17
+ * @return string
18
+ */
19
+ function bd_add_rating_link( $footer_text ) {
20
+ $rating_text = sprintf( __( 'Thank you for using <a href = "%1$s">Bulk Delete</a> plugin! Kindly <a href = "%2$s">rate us</a> at <a href = "%2$s">WordPress.org</a>', 'bulk-delete' ),
21
+ 'http://bulkwp.com?utm_source=wpadmin&utm_campaign=BulkDelete&utm_medium=footer',
22
+ 'http://wordpress.org/support/view/plugin-reviews/bulk-delete?filter=5#postform'
23
+ );
24
+
25
+ $rating_text = apply_filters( 'bd_rating_link', $rating_text );
26
+ return str_replace( '</span>', '', $footer_text ) . ' | ' . $rating_text . '</span>';
27
+ }
28
+
29
+ /**
30
+ * Modify admin footer in Bulk Delete plugin pages
31
+ *
32
+ * @since 5.0
33
+ */
34
+ function bd_modify_admin_footer() {
35
+ add_filter( 'admin_footer_text', 'bd_add_rating_link' );
36
+ }
37
+
38
+ /**
39
+ * Adds setting links in plugin listing page.
40
+ * Based on http://striderweb.com/nerdaphernalia/2008/06/wp-use-action-links/
41
+ *
42
+ * @param array $links List of current links
43
+ * @param string $file Plugin filename
44
+ * @return array $links Modified list of links
45
+ */
46
+ function bd_add_plugin_action_links( $links, $file ) {
47
+ $this_plugin = plugin_basename( Bulk_Delete::$PLUGIN_FILE );
48
+
49
+ if ( $file == $this_plugin ) {
50
+ $delete_posts_link = '<a href="admin.php?page=' . Bulk_Delete::POSTS_PAGE_SLUG . '">' . __( 'Bulk Delete Posts', 'bulk-delete' ) . '</a>';
51
+ array_unshift( $links, $delete_posts_link ); // before other links
52
+ }
53
+
54
+ return $links;
55
+ }
56
+
57
+ /**
58
+ * Add additional links in the Plugin listing page.
59
+ * Based on http://zourbuth.com/archives/751/creating-additional-wordpress-plugin-links-row-meta/
60
+ *
61
+ * @param array $links List of current links
62
+ * @param string $file Plugin filename
63
+ * @return array $links Modified list of links
64
+ */
65
+ function bd_add_links_in_plugin_listing( $links, $file ) {
66
+ $plugin = plugin_basename( Bulk_Delete::$PLUGIN_FILE );
67
+
68
+ if ( $file == $plugin ) { // only for this plugin
69
+ return array_merge( $links, array(
70
+ '<a href="http://bulkwp.com/addons?utm_source=wpadmin&utm_campaign=BulkDelete&utm_medium=plugin-page" target="_blank">' . __( 'Buy Addons', 'bulk-delete' ) . '</a>'
71
+ ) );
72
+ }
73
+
74
+ return $links;
75
+ }
76
+
77
+ // Modify admin footer
78
+ add_action( 'bd_admin_footer_posts_page', 'bd_modify_admin_footer' );
79
+ add_action( 'bd_admin_footer_pages_page', 'bd_modify_admin_footer' );
80
+ add_action( 'bd_admin_footer_cron_page' , 'bd_modify_admin_footer' );
81
+ add_action( 'bd_admin_footer_addon_page', 'bd_modify_admin_footer' );
82
+ add_action( 'bd_admin_footer_info_page' , 'bd_modify_admin_footer' );
83
+
84
+ // Change plugin listing page
85
+ add_filter( 'plugin_action_links', 'bd_add_plugin_action_links', 10, 2 );
86
+ add_filter( 'plugin_row_meta', 'bd_add_links_in_plugin_listing', 10, 2 );
87
+ ?>
include/ui/class-bulk-delete-help-screen.php ADDED
@@ -0,0 +1,112 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Bulk Delete Help Screen
4
+ *
5
+ * Displays the help tab on top of Bulk Delete Admin pages
6
+ *
7
+ * @since 5.1
8
+ * @author Sudar
9
+ * @package BulkDelete\Help
10
+ */
11
+
12
+ defined( 'ABSPATH' ) || exit; // Exit if accessed directly
13
+
14
+ class Bulk_Delete_Help_Screen {
15
+
16
+ /**
17
+ * Add contextual help to admin screens
18
+ *
19
+ * @since 5.1
20
+ * @static
21
+ *
22
+ * @param string $screen Screen name
23
+ */
24
+ public static function add_contextual_help( $screen ) {
25
+ $help_tabs = self::get_help_tabs( $screen );
26
+
27
+ foreach ( $help_tabs as $help_tab ) {
28
+ get_current_screen()->add_help_tab( $help_tab );
29
+ }
30
+
31
+ // Add help sidebar
32
+ get_current_screen()->set_help_sidebar(
33
+ '<p><strong>' . __( 'More information', 'bulk-delete' ) . '</strong></p>' .
34
+ '<p><a href = "http://bulkwp.com/support/?utm_source=wpadmin&utm_campaign=BulkDelete&utm_medium=helptab">' . __( 'Support Forums', 'bulk-delete' ) . '</a></p>' .
35
+ '<p><a href = "http://bulkwp.com/addons/?utm_source=wpadmin&utm_campaign=BulkDelete&utm_medium=helptab">' . __( 'Buy pro addons', 'bulk-delete' ) . '</a></p>' .
36
+ '<p><a href = "http://sudarmuthu.com/blog">' . __( "Plugin author's blog", 'bulk-delete' ) . '</a></p>' .
37
+ '<p><a href = "http://sudarmuthu.com/wordpress/">' . __( "Other Plugin's by Author", 'bulk-delete' ) . '</a></p>'
38
+ );
39
+ }
40
+
41
+ /**
42
+ * Get the list of help tabs for a given screen
43
+ *
44
+ * @since 5.1
45
+ * @static
46
+ * @access private
47
+ *
48
+ * @param string $screen Screen name
49
+ * @return array $help_tabs List of tabs
50
+ */
51
+ private static function get_help_tabs( $screen ) {
52
+ $bd = BULK_DELETE();
53
+ $help_tabs = array();
54
+
55
+ switch ( $screen ) {
56
+ case $bd->posts_page:
57
+ $overview_tab = array(
58
+ 'title' => __( 'Overview', 'bulk-delete' ),
59
+ 'id' => 'overview_tab',
60
+ 'content' => '<p>' . __( 'This screen contains different modules that allows you to delete posts or schedule them for deletion.', 'bulk-delete' ) . '</p>',
61
+ 'callback' => false,
62
+ );
63
+
64
+ $help_tabs['overview_tab'] = $overview_tab;
65
+ break;
66
+
67
+ case $bd->pages_page:
68
+ // Overview tab
69
+ $overview_tab = array(
70
+ 'title' => __( 'Overview', 'bulk-delete' ),
71
+ 'id' => 'overview_tab',
72
+ 'content' => '<p>' . __( 'This screen contains different modules that allows you to delete pages or schedule them for deletion.', 'bulk-delete' ) . '</p>',
73
+ 'callback' => false,
74
+ );
75
+
76
+ $help_tabs['overview_tab'] = $overview_tab;
77
+ break;
78
+ }
79
+
80
+ // about plugin tab
81
+ $about_plugin_tab = array(
82
+ 'title' => __( 'About Plugin', 'bulk-delete' ),
83
+ 'id' => 'about_plugin_tab',
84
+ 'content' => '',
85
+ 'callback' => array( 'Bulk_Delete_Help_Screen', 'print_about_plugin_tab_content' ),
86
+ );
87
+
88
+ $help_tabs['about_plugin_tab'] = $about_plugin_tab;
89
+
90
+ /**
91
+ * Filters help tab content for admin screens
92
+ *
93
+ * @since 5.1
94
+ */
95
+ return apply_filters( 'bd_admin_help_tabs', $help_tabs, $screen );
96
+ }
97
+
98
+ /**
99
+ * print the about plugin tab content
100
+ *
101
+ * @since 5.1
102
+ * @static
103
+ */
104
+ public static function print_about_plugin_tab_content() {
105
+ echo '<p>' . __( 'This plugin allows you to perform bulk operations in WordPress easily.', 'bulk-delete' ) . '</p>';
106
+ echo '<p>' . __( 'This plugin can be used to delete the posts, pages or users using various filters and conditions.', 'bulk-delete' ) . '</p>';
107
+ }
108
+ }
109
+
110
+ // hooks
111
+ add_action( 'bd_add_contextual_help', array( 'Bulk_Delete_Help_Screen', 'add_contextual_help' ) );
112
+ ?>
include/ui/form.php ADDED
@@ -0,0 +1,179 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Utility functions for displaying form.
4
+ *
5
+ * @since 5.5
6
+ * @author Sudar
7
+ * @package BulkDelete\Ui
8
+ */
9
+
10
+ defined( 'ABSPATH' ) || exit; // Exit if accessed directly
11
+
12
+ /**
13
+ * Render filtering table header.
14
+ *
15
+ * @since 5.5
16
+ */
17
+ function bd_render_filtering_table_header() {
18
+ ?>
19
+ <tr>
20
+ <td colspan="2">
21
+ <h4><?php _e( 'Choose your filtering options', 'bulk-delete' ); ?></h4>
22
+ </td>
23
+ </tr>
24
+ <?php
25
+ }
26
+
27
+ /**
28
+ * Render "restrict by created date" dropdown.
29
+ *
30
+ * @since 5.5
31
+ * @param string $slug The slug to be used in field names.
32
+ * @param string $item (optional) Item for which form is displayed. Default is 'posts'.
33
+ */
34
+ function bd_render_restrict_settings( $slug, $item = 'posts' ) {
35
+ ?>
36
+ <tr>
37
+ <td scope="row">
38
+ <input name="smbd_<?php echo $slug; ?>_restrict" id="smbd_<?php echo $slug; ?>_restrict" value="true" type="checkbox">
39
+ </td>
40
+ <td>
41
+ <?php printf( __( 'Only restrict to %s which are ', 'bulk-delete' ), $item );?>
42
+ <select name="smbd_<?php echo $slug; ?>_op" id="smbd_<?php echo $slug; ?>_op" disabled>
43
+ <option value="before"><?php _e( 'older than', 'bulk-delete' );?></option>
44
+ <option value="after"><?php _e( 'posted within last', 'bulk-delete' );?></option>
45
+ </select>
46
+ <input type="number" name="smbd_<?php echo $slug; ?>_days" id="smbd_<?php echo $slug; ?>_days" class="screen-per-page" disabled value="0" min="0"><?php _e( 'days', 'bulk-delete' );?>
47
+ </td>
48
+ </tr>
49
+ <?php
50
+ }
51
+
52
+ /**
53
+ * Render "force delete" setting fields.
54
+ *
55
+ * @since 5.5
56
+ * @param string $slug The slug to be used in field names.
57
+ */
58
+ function bd_render_delete_settings( $slug ) {
59
+ ?>
60
+ <tr>
61
+ <td scope="row" colspan="2">
62
+ <input name="smbd_<?php echo $slug; ?>_force_delete" value="false" type="radio" checked> <?php _e( 'Move to Trash', 'bulk-delete' ); ?>
63
+ <input name="smbd_<?php echo $slug; ?>_force_delete" value="true" type="radio"> <?php _e( 'Delete permanently', 'bulk-delete' ); ?>
64
+ </td>
65
+ </tr>
66
+ <?php
67
+ }
68
+
69
+ /**
70
+ * Render the "private post" setting fields.
71
+ *
72
+ * @since 5.5
73
+ * @param string $slug The slug to be used in field names.
74
+ */
75
+ function bd_render_private_post_settings( $slug ) {
76
+ ?>
77
+ <tr>
78
+ <td scope="row" colspan="2">
79
+ <input name="smbd_<?php echo $slug; ?>_private" value="false" type="radio" checked> <?php _e( 'Public posts', 'bulk-delete' ); ?>
80
+ <input name="smbd_<?php echo $slug; ?>_private" value="true" type="radio"> <?php _e( 'Private Posts', 'bulk-delete' ); ?>
81
+ </td>
82
+ </tr>
83
+ <?php
84
+ }
85
+
86
+ /**
87
+ * Render the "limit" setting fields.
88
+ *
89
+ * @since 5.5
90
+ * @param string $slug The slug to be used in field names.
91
+ * @param string $item (Optional) Item type. Possible values are 'posts', 'pages', 'users'
92
+ */
93
+ function bd_render_limit_settings( $slug, $item = 'posts' ) {
94
+ ?>
95
+ <tr>
96
+ <td scope="row">
97
+ <input name="smbd_<?php echo $slug; ?>_limit" id="smbd_<?php echo $slug; ?>_limit" value="true" type="checkbox">
98
+ </td>
99
+ <td>
100
+ <?php _e( 'Only delete first ', 'bulk-delete' );?>
101
+ <input type="number" name="smbd_<?php echo $slug; ?>_limit_to" id="smbd_<?php echo $slug; ?>_limit_to" class="screen-per-page" disabled value="0" min="0"> <?php echo $item;?>.
102
+ <?php printf( __( 'Use this option if there are more than 1000 %s and the script timesout.', 'bulk-delete' ), $item ); ?>
103
+ </td>
104
+ </tr>
105
+ <?php
106
+ }
107
+
108
+ /**
109
+ * Render cron setting fields.
110
+ *
111
+ * @since 5.5
112
+ * @param string $slug The slug to be used in field names.
113
+ * @param string $addon_url Url for the pro addon.
114
+ */
115
+ function bd_render_cron_settings( $slug, $addon_url ) {
116
+ $pro_class = 'bd-' . str_replace( '_', '-', $slug ) . '-pro';
117
+ ?>
118
+ <tr>
119
+ <td scope="row" colspan="2">
120
+ <input name="smbd_<?php echo $slug; ?>_cron" value="false" type="radio" checked="checked"> <?php _e( 'Delete now', 'bulk-delete' ); ?>
121
+ <input name="smbd_<?php echo $slug; ?>_cron" value="true" type="radio" id="smbd_<?php echo $slug; ?>_cron" disabled > <?php _e( 'Schedule', 'bulk-delete' ); ?>
122
+ <input name="smbd_<?php echo $slug; ?>_cron_start" id="smbd_<?php echo $slug; ?>_cron_start" value="now" type="text" disabled><?php _e( 'repeat ', 'bulk-delete' );?>
123
+ <select name="smbd_<?php echo $slug; ?>_cron_freq" id="smbd_<?php echo $slug; ?>_cron_freq" disabled>
124
+ <option value="-1"><?php _e( "Don't repeat", 'bulk-delete' ); ?></option>
125
+ <?php
126
+ $schedules = wp_get_schedules();
127
+ foreach ( $schedules as $key => $value ) {
128
+ ?>
129
+ <option value="<?php echo $key; ?>"><?php echo $value['display']; ?></option>
130
+ <?php } ?>
131
+ </select>
132
+ <span class="<?php echo sanitize_html_class( apply_filters( 'bd_pro_class', $pro_class, $slug ) ); ?>" style="color:red"><?php _e( 'Only available in Pro Addon', 'bulk-delete' ); ?> <a href="<?php echo $addon_url; ?>">Buy now</a></span>
133
+ </td>
134
+ </tr>
135
+
136
+ <tr>
137
+ <td scope="row" colspan="2">
138
+ <?php _e( 'Enter time in Y-m-d H:i:s format or enter now to use current time', 'bulk-delete' );?>
139
+ </td>
140
+ </tr>
141
+ <?php
142
+ }
143
+
144
+ /**
145
+ * Render the submit button.
146
+ *
147
+ * @since 5.5
148
+ * @param string $action The action attribute of the submit button.
149
+ */
150
+ function bd_render_submit_button( $action ) {
151
+ ?>
152
+ <p class="submit">
153
+ <button type="submit" name="bd_action" value="<?php echo esc_attr( $action ); ?>" class="button-primary"><?php _e( 'Bulk Delete ', 'bulk-delete' ); ?>&raquo;</button>
154
+ </p>
155
+ <?php
156
+ }
157
+
158
+ /**
159
+ * Render the post type dropdown.
160
+ *
161
+ * @since 5.5
162
+ * @param string $slug The slug to be used in field names.
163
+ */
164
+ function bd_render_post_type_dropdown( $slug ) {
165
+ $types = get_post_types( array( '_builtin' => false ), 'names' );
166
+ array_unshift( $types, 'post' );
167
+ ?>
168
+ <tr>
169
+ <td scope="row" >
170
+ <select class="select2" name="smbd_<?php echo $slug; ?>_post_type">
171
+ <?php foreach ( $types as $type ) { ?>
172
+ <option value="<?php echo esc_attr( $type ); ?>"><?php echo esc_html( $type ); ?></option>
173
+ <?php } ?>
174
+ </select>
175
+ </td>
176
+ </tr>
177
+ <?php
178
+ }
179
+ ?>
include/users/class-bd-users-page.php ADDED
@@ -0,0 +1,95 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Bulk Delete Users Page.
4
+ * Shows the list of modules that allows you to delete users.
5
+ *
6
+ * @since 5.5
7
+ * @author Sudar
8
+ * @package BulkDelete\Users
9
+ */
10
+
11
+ defined( 'ABSPATH' ) || exit; // Exit if accessed directly
12
+
13
+ /**
14
+ * Delete Users Page.
15
+ *
16
+ * @since 5.5
17
+ */
18
+ class BD_Users_Page extends BD_Page {
19
+ /**
20
+ * Make this class a "hybrid Singleton".
21
+ *
22
+ * @static
23
+ * @since 5.5
24
+ */
25
+ public static function factory() {
26
+ static $instance = false;
27
+
28
+ if ( ! $instance ) {
29
+ $instance = new self;
30
+ }
31
+
32
+ return $instance;
33
+ }
34
+
35
+ /**
36
+ * Initialize and setup variables.
37
+ *
38
+ * @since 5.5
39
+ */
40
+ protected function initialize() {
41
+ $this->page_slug = 'bulk-delete-users';
42
+ $this->item_type = 'users';
43
+ $this->capability = 'delete_users';
44
+
45
+ $this->label = array(
46
+ 'page_title' => __( 'Bulk Delete Users', 'bulk-delete' ),
47
+ 'menu_title' => __( 'Bulk Delete Users', 'bulk-delete' ),
48
+ );
49
+
50
+ $this->messages = array(
51
+ 'warning_message' => __( 'WARNING: Users deleted once cannot be retrieved back. Use with caution.', 'bulk-delete' ),
52
+ );
53
+
54
+ add_filter( 'plugin_action_links', array( $this, 'add_plugin_action_links' ), 10, 2 );
55
+ }
56
+
57
+ /**
58
+ * Adds setting links in plugin listing page.
59
+ * Based on http://striderweb.com/nerdaphernalia/2008/06/wp-use-action-links/
60
+ *
61
+ * @param array $links List of current links
62
+ * @param string $file Plugin filename
63
+ * @return array $links Modified list of links
64
+ */
65
+ public function add_plugin_action_links( $links, $file ) {
66
+ $this_plugin = plugin_basename( Bulk_Delete::$PLUGIN_FILE );
67
+
68
+ if ( $file == $this_plugin ) {
69
+ $delete_users_link = '<a href="admin.php?page=' . $this->page_slug . '">' . __( 'Bulk Delete Users', 'bulk-delete' ) . '</a>';
70
+ array_unshift( $links, $delete_users_link ); // before other links
71
+ }
72
+
73
+ return $links;
74
+ }
75
+
76
+ /**
77
+ * Add Help tabs.
78
+ *
79
+ * @since 5.5
80
+ */
81
+ protected function add_help_tab( $help_tabs ) {
82
+ $overview_tab = array(
83
+ 'title' => __( 'Overview', 'bulk-delete' ),
84
+ 'id' => 'overview_tab',
85
+ 'content' => '<p>' . __( 'This screen contains different modules that allows you to delete users or schedule them for deletion.', 'bulk-delete' ) . '</p>',
86
+ 'callback' => false,
87
+ );
88
+ $help_tabs['overview_tab'] = $overview_tab;
89
+
90
+ return $help_tabs;
91
+ }
92
+ }
93
+
94
+ BD_Users_Page::factory();
95
+ ?>
include/users/modules/class-bulk-delete-users-by-user-meta.php ADDED
@@ -0,0 +1,207 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Bulk Delete Users by User Meta.
4
+ *
5
+ * @since 5.5
6
+ * @author Sudar
7
+ * @package BulkDelete\Users\Modules
8
+ */
9
+
10
+ defined( 'ABSPATH' ) || exit; // Exit if accessed directly
11
+
12
+ /**
13
+ * Bulk Delete Users by User Meta.
14
+ *
15
+ * @since 5.5
16
+ */
17
+ class Bulk_Delete_Users_By_User_Meta extends BD_Meta_Box_Module {
18
+ /**
19
+ * Make this class a "hybrid Singleton".
20
+ *
21
+ * @static
22
+ * @since 5.5
23
+ */
24
+ public static function factory() {
25
+ static $instance = false;
26
+
27
+ if ( ! $instance ) {
28
+ $instance = new self;
29
+ }
30
+
31
+ return $instance;
32
+ }
33
+
34
+ /**
35
+ * Initialize and setup variables.
36
+ *
37
+ * @since 5.5
38
+ */
39
+ protected function initialize() {
40
+ $this->item_type = 'users';
41
+ $this->field_slug = 'u_meta';
42
+ $this->meta_box_slug = 'bd_users_by_meta';
43
+ $this->meta_box_hook = "bd_add_meta_box_for_{$this->item_type}";
44
+ $this->delete_action = 'delete_users_by_meta';
45
+ $this->cron_hook = 'do-bulk-delete-users-by-meta';
46
+ $this->scheduler_url = 'http://bulkwp.com/addons/scheduler-for-deleting-users-by-meta/?utm_source=wpadmin&utm_campaign=BulkDelete&utm_medium=buynow&utm_content=bd-u-ma';
47
+ $this->messages = array(
48
+ 'box_label' => __( 'By User Meta', 'bulk-delete' ),
49
+ 'scheduled' => __( 'Users from with the selected user meta are scheduled for deletion.', 'bulk-delete' ),
50
+ 'deleted_single' => __( 'Deleted %d user with the selected user meta', 'bulk-delete' ),
51
+ 'deleted_plural' => __( 'Deleted %d users with the selected user meta', 'bulk-delete' ),
52
+ );
53
+ }
54
+
55
+ /**
56
+ * Render delete users box.
57
+ *
58
+ * @since 5.5
59
+ */
60
+ public function render() {
61
+ ?>
62
+ <!-- Users Start-->
63
+ <h4><?php _e( 'Select the user meta from which you want to delete users', 'bulk-delete' ); ?></h4>
64
+
65
+ <fieldset class="options">
66
+ <table class="optiontable">
67
+ <select name="smbd_u_meta_key" class="select2">
68
+ <?php
69
+ $meta_keys = $this->get_unique_meta_keys();
70
+ foreach ( $meta_keys as $meta_key ) {
71
+ printf( '<option value="%s">%s</option>', $meta_key, $meta_key );
72
+ }
73
+ ?>
74
+ </select>
75
+ <select name="smbd_u_meta_compare">
76
+ <option value="=">=</option>
77
+ <option value="!=">!=</option>
78
+ <option value=">">></option>
79
+ <option value=">=">>=</option>
80
+ <option value="<"><</option>
81
+ <option value="<="><=</option>
82
+ </select>
83
+ <input type="text" name="smbd_u_meta_value" id="smbd_u_meta_value" placeholder="<?php _e( 'Meta Value', 'bulk-delete' );?>">
84
+
85
+ </table>
86
+
87
+ <table class="optiontable">
88
+ <?php
89
+ $this->render_filtering_table_header();
90
+ $this->render_user_login_restrict_settings();
91
+ $this->render_user_with_no_posts_settings();
92
+ $this->render_limit_settings();
93
+ $this->render_cron_settings();
94
+ ?>
95
+ </table>
96
+ </fieldset>
97
+ <!-- Users end-->
98
+ <?php
99
+ $this->render_submit_button();
100
+ }
101
+
102
+ /**
103
+ * Process the request for deleting users by meta.
104
+ *
105
+ * @since 5.5
106
+ */
107
+ public function process() {
108
+ $delete_options = array();
109
+ $delete_options['meta_key'] = array_get( $_POST, 'smbd_u_meta_key' );
110
+ $delete_options['meta_compare'] = array_get( $_POST, 'smbd_u_meta_compare', '=' );
111
+ $delete_options['meta_value'] = array_get( $_POST, 'smbd_u_meta_value' );
112
+
113
+ $delete_options['login_restrict'] = array_get_bool( $_POST, "smbd_{$this->field_slug}_login_restrict", false );
114
+ $delete_options['login_days'] = absint( array_get( $_POST, "smbd_{$this->field_slug}_login_days", 0 ) );
115
+
116
+ $delete_options['no_posts'] = array_get_bool( $_POST, "smbd_{$this->field_slug}_no_posts", false );
117
+ $delete_options['limit_to'] = absint( array_get( $_POST, "smbd_{$this->field_slug}_limit_to", 0 ) );
118
+
119
+ $this->process_delete( $delete_options );
120
+ }
121
+
122
+ /**
123
+ * Delete users by user meta.
124
+ *
125
+ * @since 5.5
126
+ * @param array $delete_options Delete Options
127
+ * @return int Number of users deleted
128
+ */
129
+ public function delete( $delete_options ) {
130
+ if ( ! function_exists( 'wp_delete_user' ) ) {
131
+ require_once ABSPATH . 'wp-admin/includes/user.php';
132
+ }
133
+
134
+ $count = 0;
135
+
136
+ $options = array(
137
+ 'meta_key' => $delete_options['meta_key'],
138
+ 'meta_value' => $delete_options['meta_value'],
139
+ 'meta_compare' => $delete_options['meta_compare'],
140
+ );
141
+
142
+ if ( $delete_options['limit_to'] > 0 ) {
143
+ $options['number'] = $delete_options['limit_to'];
144
+ }
145
+
146
+ $users = get_users( $options );
147
+
148
+ foreach ( $users as $user ) {
149
+ if ( $delete_options['no_posts'] && count_user_posts( $user->ID ) > 0 ) {
150
+ continue;
151
+ }
152
+
153
+ if ( $delete_options['login_restrict'] ) {
154
+ $login_days = $delete_options['login_days'];
155
+ $last_login = bd_get_last_login( $user->ID );
156
+
157
+ if ( null != $last_login ) {
158
+ if ( strtotime( $last_login ) > strtotime( '-' . $login_days . 'days' ) ) {
159
+ continue;
160
+ }
161
+ } else {
162
+ continue;
163
+ }
164
+ }
165
+
166
+ wp_delete_user( $user->ID );
167
+ $count ++;
168
+ }
169
+
170
+ return $count;
171
+ }
172
+
173
+ /**
174
+ * Filter JS Array and add validation hooks.
175
+ *
176
+ * @since 5.5
177
+ * @param array $js_array JavaScript Array
178
+ * @return array Modified JavaScript Array
179
+ */
180
+ public function filter_js_array( $js_array ) {
181
+ $js_array['dt_iterators'][] = '_' . $this->field_slug;
182
+ $js_array['validators'][ $this->delete_action ] = 'validateUserMeta';
183
+
184
+ $js_array['pre_action_msg'][ $this->delete_action ] = 'deleteUsersByMetaWarning';
185
+ $js_array['msg']['deleteUsersByMetaWarning'] = __( 'Are you sure you want to delete all the users from the selected user meta?', 'bulk-delete' );
186
+
187
+ $js_array['error_msg'][ $this->delete_action ] = 'enterUserMetaValue';
188
+ $js_array['msg']['enterUserMetaValue'] = __( 'Please enter the value for the user meta field based on which you want to delete users', 'bulk-delete' );
189
+
190
+ return $js_array;
191
+ }
192
+
193
+ /**
194
+ * Get unique user meta keys.
195
+ *
196
+ * @since 5.5
197
+ * @return array List of unique meta keys.
198
+ */
199
+ private function get_unique_meta_keys() {
200
+ global $wpdb;
201
+
202
+ return $wpdb->get_col( "SELECT DISTINCT(meta_key) FROM {$wpdb->prefix}usermeta ORDER BY meta_key" );
203
+ }
204
+ }
205
+
206
+ Bulk_Delete_Users_By_User_Meta::factory();
207
+ ?>
include/users/modules/class-bulk-delete-users-by-user-role.php ADDED
@@ -0,0 +1,184 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Bulk Delete Users by User Role
4
+ *
5
+ * @since 5.5
6
+ * @author Sudar
7
+ * @package BulkDelete\Users\Modules
8
+ */
9
+
10
+ defined( 'ABSPATH' ) || exit; // Exit if accessed directly
11
+
12
+ /**
13
+ * Bulk Delete Users by User Role.
14
+ *
15
+ * @since 5.5
16
+ */
17
+ class Bulk_Delete_Users_By_User_Role extends BD_Meta_Box_Module {
18
+ /**
19
+ * Make this class a "hybrid Singleton".
20
+ *
21
+ * @static
22
+ * @since 5.5
23
+ */
24
+ public static function factory() {
25
+ static $instance = false;
26
+
27
+ if ( ! $instance ) {
28
+ $instance = new self;
29
+ }
30
+
31
+ return $instance;
32
+ }
33
+
34
+ /**
35
+ * Initialize and setup variables.
36
+ *
37
+ * @since 5.5
38
+ */
39
+ protected function initialize() {
40
+ $this->item_type = 'users';
41
+ $this->field_slug = 'u_role';
42
+ $this->meta_box_slug = 'bd_users_by_role';
43
+ $this->meta_box_hook = "bd_add_meta_box_for_{$this->item_type}";
44
+ $this->delete_action = 'delete_users_by_role';
45
+ $this->cron_hook = 'do-bulk-delete-users-by-role';
46
+ $this->scheduler_url = 'http://bulkwp.com/addons/scheduler-for-deleting-users-by-role/?utm_source=wpadmin&utm_campaign=BulkDelete&utm_medium=buynow&utm_content=bd-u-ur';
47
+ $this->messages = array(
48
+ 'box_label' => __( 'By User Role', 'bulk-delete' ),
49
+ 'scheduled' => __( 'Users from the selected userrole are scheduled for deletion.', 'bulk-delete' ),
50
+ 'deleted_single' => __( 'Deleted %d user from the selected roles', 'bulk-delete' ),
51
+ 'deleted_plural' => __( 'Deleted %d users from the selected roles', 'bulk-delete' ),
52
+ );
53
+ }
54
+
55
+ /**
56
+ * Render delete users box.
57
+ *
58
+ * @since 5.5
59
+ */
60
+ public function render() {
61
+ ?>
62
+ <!-- Users Start-->
63
+ <h4><?php _e( 'Select the user roles from which you want to delete users', 'bulk-delete' ); ?></h4>
64
+
65
+ <fieldset class="options">
66
+ <table class="optiontable">
67
+ <?php
68
+ $users_count = count_users();
69
+ foreach ( $users_count['avail_roles'] as $role => $count ) {
70
+ ?>
71
+ <tr>
72
+ <td scope="row" >
73
+ <input name="smbd_u_roles[]" value = "<?php echo $role; ?>" type = "checkbox">
74
+ <label for="smbd_u_roles"><?php echo $role; ?> (<?php echo $count . ' '; _e( 'Users', 'bulk-delete' ); ?>)</label>
75
+ </td>
76
+ </tr>
77
+ <?php
78
+ }
79
+ ?>
80
+ </table>
81
+
82
+ <table class="optiontable">
83
+ <?php
84
+ $this->render_filtering_table_header();
85
+ $this->render_user_login_restrict_settings();
86
+ $this->render_user_with_no_posts_settings();
87
+ $this->render_limit_settings();
88
+ $this->render_cron_settings();
89
+ ?>
90
+ </table>
91
+ </fieldset>
92
+ <!-- Users end-->
93
+ <?php
94
+ $this->render_submit_button();
95
+ }
96
+
97
+ /**
98
+ * Process the request for deleting users by role.
99
+ *
100
+ * @since 5.5
101
+ */
102
+ public function process() {
103
+ $delete_options = array();
104
+ $delete_options['selected_roles'] = array_get( $_POST, 'smbd_u_roles' );
105
+ $delete_options['no_posts'] = array_get_bool( $_POST, "smbd_{$this->field_slug}_no_posts", false );
106
+
107
+ $delete_options['login_restrict'] = array_get_bool( $_POST, "smbd_{$this->field_slug}_login_restrict", false );
108
+ $delete_options['login_days'] = absint( array_get( $_POST, "smbd_{$this->field_slug}_login_days", 0 ) );
109
+
110
+ $delete_options['limit_to'] = absint( array_get( $_POST, "smbd_{$this->field_slug}_limit_to", 0 ) );
111
+
112
+ $this->process_delete( $delete_options );
113
+ }
114
+
115
+ /**
116
+ * Delete users by user role.
117
+ *
118
+ * @since 5.5
119
+ * @param array $delete_options Delete Options
120
+ * @return int Number of users deleted
121
+ */
122
+ public function delete( $delete_options ) {
123
+ if ( ! function_exists( 'wp_delete_user' ) ) {
124
+ require_once ABSPATH . 'wp-admin/includes/user.php';
125
+ }
126
+
127
+ $count = 0;
128
+
129
+ foreach ( $delete_options['selected_roles'] as $role ) {
130
+ $options = array('role' => $role);
131
+ if ( $delete_options['limit_to'] > 0 ) {
132
+ $options['number'] = $delete_options['limit_to'];
133
+ }
134
+
135
+ $users = get_users( $options );
136
+
137
+ foreach ( $users as $user ) {
138
+ if ( $delete_options['no_posts'] && count_user_posts( $user->ID ) > 0 ) {
139
+ continue;
140
+ }
141
+
142
+ if ( $delete_options['login_restrict'] ) {
143
+ $login_days = $delete_options['login_days'];
144
+ $last_login = bd_get_last_login( $user->ID );
145
+
146
+ if ( null != $last_login ) {
147
+ if ( strtotime( $last_login ) > strtotime( '-' . $login_days . 'days' ) ) {
148
+ continue;
149
+ }
150
+ } else {
151
+ continue;
152
+ }
153
+ }
154
+
155
+ wp_delete_user( $user->ID );
156
+ $count ++;
157
+ }
158
+ }
159
+
160
+ return $count;
161
+ }
162
+
163
+ /**
164
+ * Filter JS Array and add validation hooks
165
+ *
166
+ * @since 5.5
167
+ * @param array $js_array JavaScript Array
168
+ * @return array Modified JavaScript Array
169
+ */
170
+ public function filter_js_array( $js_array ) {
171
+ $js_array['dt_iterators'][] = '_' . $this->field_slug;
172
+
173
+ $js_array['pre_action_msg'][ $this->delete_action ] = 'deleteUsersWarning';
174
+ $js_array['msg']['deleteUsersWarning'] = __( 'Are you sure you want to delete all the users from the selected user role?', 'bulk-delete' );
175
+
176
+ $js_array['error_msg'][ $this->delete_action ] = 'selectOneUserRole';
177
+ $js_array['msg']['selectOneUserRole'] = __( 'Select at least one user role from which users should be deleted', 'bulk-delete' );
178
+
179
+ return $js_array;
180
+ }
181
+ }
182
+
183
+ Bulk_Delete_Users_By_User_Role::factory();
184
+ ?>
include/util.php DELETED
@@ -1,26 +0,0 @@
1
- <?php
2
- /**
3
- * Utility functions for Bulk Delete Plugin
4
- *
5
- * http://sudarmuthu.com/wordpress/bulk-delete
6
- *
7
- * @author: Sudar <http://sudarmuthu.com>
8
- *
9
- */
10
-
11
- /**
12
- * Check whether a key is present. If present returns the value, else returns the default value
13
- *
14
- * @param <array> $array - Array whose key has to be checked
15
- * @param <string> $key - key that has to be checked
16
- * @param <string> $default - the default value that has to be used, if the key is not found (optional)
17
- *
18
- * @return <mixed> If present returns the value, else returns the default value
19
- * @author Sudar
20
- */
21
- if (!function_exists('array_get')) {
22
- function array_get($array, $key, $default = NULL) {
23
- return isset($array[$key]) ? $array[$key] : $default;
24
- }
25
- }
26
- ?>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
include/util/class-bd-util.php ADDED
@@ -0,0 +1,264 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Utility classes and functions.
4
+ *
5
+ * @author Sudar
6
+ * @package BulkDelete\Util
7
+ */
8
+
9
+ defined( 'ABSPATH' ) || exit; // Exit if accessed directly
10
+
11
+ /**
12
+ * Utility class.
13
+ *
14
+ * Ideally most of the functions should be inside the `BulkDelete\Util` and not as static functions.
15
+ */
16
+ class BD_Util {
17
+ // Meta boxes
18
+ const VISIBLE_POST_BOXES = 'metaboxhidden_toplevel_page_bulk-delete-posts';
19
+ const VISIBLE_PAGE_BOXES = 'metaboxhidden_bulk-delete_page_bulk-delete-pages';
20
+ const VISIBLE_USER_BOXES = 'metaboxhidden_bulk-delete_page_bulk-delete-users';
21
+
22
+ /**
23
+ * Check whether the meta box in posts page is hidden or not
24
+ *
25
+ * @static
26
+ * @access public
27
+ * @param string $box The name of the box
28
+ * @return bool True if the box is hidden, False otherwise
29
+ */
30
+ public static function is_posts_box_hidden( $box ) {
31
+ $hidden_boxes = self::get_posts_hidden_boxes();
32
+ return is_array( $hidden_boxes ) && in_array( $box, $hidden_boxes );
33
+ }
34
+
35
+ /**
36
+ * Get the list of hidden boxes in posts page
37
+ *
38
+ * @static
39
+ * @access public
40
+ * @return array The list of hidden meta boxes
41
+ */
42
+ public static function get_posts_hidden_boxes() {
43
+ $current_user = wp_get_current_user();
44
+ return get_user_meta( $current_user->ID, self::VISIBLE_POST_BOXES, true );
45
+ }
46
+
47
+ /**
48
+ * Check whether the meta box in pages page is hidden or not
49
+ *
50
+ * @since 5.0
51
+ * @static
52
+ * @access public
53
+ * @param string $box The name of the box to check
54
+ * @return bool True if the box is hidden, False otherwise
55
+ */
56
+ public static function is_pages_box_hidden( $box ) {
57
+ $hidden_boxes = self::get_pages_hidden_boxes();
58
+ return is_array( $hidden_boxes ) && in_array( $box, $hidden_boxes );
59
+ }
60
+
61
+ /**
62
+ * Get the list of hidden boxes in posts page
63
+ *
64
+ * @since 5.0
65
+ * @static
66
+ * @access public
67
+ * @return the array of hidden meta boxes
68
+ */
69
+ public static function get_pages_hidden_boxes() {
70
+ $current_user = wp_get_current_user();
71
+ return get_user_meta( $current_user->ID, self::VISIBLE_PAGE_BOXES, true );
72
+ }
73
+
74
+ /**
75
+ * Check whether the meta box in users page is hidden or not
76
+ *
77
+ * @static
78
+ * @access public
79
+ * @param string $box The name of the box to check
80
+ * @return bool True if the box is hidden, False otherwise
81
+ */
82
+ public static function is_users_box_hidden( $box ) {
83
+ $hidden_boxes = self::get_users_hidden_boxes();
84
+ return is_array( $hidden_boxes ) && in_array( $box, $hidden_boxes );
85
+ }
86
+
87
+ /**
88
+ * Get the list of hidden boxes in users page
89
+ *
90
+ * @static
91
+ * @access public
92
+ * @return array The array of hidden meta boxes
93
+ */
94
+ public static function get_users_hidden_boxes() {
95
+ $current_user = wp_get_current_user();
96
+ return get_user_meta( $current_user->ID, self::VISIBLE_USER_BOXES, true );
97
+ }
98
+
99
+ /**
100
+ * Get the list of cron schedules
101
+ *
102
+ * @static
103
+ * @access public
104
+ * @return array The list of cron schedules
105
+ */
106
+ public static function get_cron_schedules() {
107
+
108
+ $cron_items = array();
109
+ $cron = _get_cron_array();
110
+ $date_format = _x( 'M j, Y @ G:i', 'Cron table date format', 'bulk-delete' );
111
+ $i = 0;
112
+
113
+ foreach ( $cron as $timestamp => $cronhooks ) {
114
+ foreach ( (array) $cronhooks as $hook => $events ) {
115
+ if ( 'do-bulk-delete-' == substr( $hook, 0, 15 ) ) {
116
+ $cron_item = array();
117
+
118
+ foreach ( (array) $events as $key => $event ) {
119
+ $cron_item['timestamp'] = $timestamp;
120
+ $cron_item['due'] = date_i18n( $date_format, $timestamp + ( get_option( 'gmt_offset' ) * 60 * 60 ) );
121
+ $cron_item['schedule'] = $event['schedule'];
122
+ $cron_item['type'] = $hook;
123
+ $cron_item['args'] = $event['args'];
124
+ $cron_item['id'] = $i;
125
+ }
126
+
127
+ $cron_items[ $i ] = $cron_item;
128
+ $i++;
129
+ }
130
+ }
131
+ }
132
+ return $cron_items;
133
+ }
134
+
135
+ /**
136
+ * Generate display name from post type and status
137
+ *
138
+ * @static
139
+ * @param string $str
140
+ * @return string Label
141
+ */
142
+ public static function display_post_type_status( $str ) {
143
+ $type_status = self::split_post_type_status( $str );
144
+
145
+ $status = $type_status['status'];
146
+ $type = $type_status['type'];
147
+ $label = '';
148
+
149
+ switch ( $status ) {
150
+ case 'private':
151
+ $label = $type . ' - Private Posts';
152
+ break;
153
+ case 'future':
154
+ $label = $type . ' - Scheduled Posts';
155
+ break;
156
+ case 'draft':
157
+ $label = $type . ' - Draft Posts';
158
+ break;
159
+ case 'pending':
160
+ $label = $type . ' - Pending Posts';
161
+ break;
162
+ case 'publish':
163
+ $label = $type . ' - Published Posts';
164
+ break;
165
+ }
166
+
167
+ return $label;
168
+ }
169
+
170
+ /**
171
+ * Split post type and status
172
+ *
173
+ * @static
174
+ * @access public
175
+ * @param string $str
176
+ * @return array
177
+ */
178
+ public static function split_post_type_status( $str ) {
179
+ $type_status = array();
180
+
181
+ $str_arr = explode( '-', $str );
182
+
183
+ if ( count( $str_arr ) > 1 ) {
184
+ $type_status['status'] = end( $str_arr );
185
+ $type_status['type'] = implode( '-', array_slice( $str_arr, 0, -1 ) );
186
+ } else {
187
+ $type_status['status'] = 'publish';
188
+ $type_status['type'] = $str;
189
+ }
190
+
191
+ return $type_status;
192
+ }
193
+ }
194
+
195
+ if ( ! function_exists( 'array_get' ) ) {
196
+ /**
197
+ * Get a value from an array based on key.
198
+ * If key is present returns the value, else returns the default value
199
+ *
200
+ * @param array $array Array from which value has to be retrieved
201
+ * @param string $key Key, whose value to be retrieved
202
+ * @param string $default Optional. Default value to be returned, if the key is not found
203
+ * @return mixed Value if key is present, else the default value
204
+ */
205
+ function array_get( $array, $key, $default = null ) {
206
+ return isset( $array[ $key ] ) ? $array[ $key ] : $default;
207
+ }
208
+ }
209
+
210
+ if ( ! function_exists( 'array_get_bool' ) ) {
211
+ /**
212
+ * Get a value from an array based on key and convert it into bool.
213
+ *
214
+ * @param array $array Array from which value has to be retrieved
215
+ * @param string $key Key, whose value to be retrieved
216
+ * @param bool $default (Optional) Default value to be returned, if the key is not found
217
+ * @return mixed Boolean converted Value if key is present, else the default value
218
+ */
219
+ function array_get_bool( $array, $key, $default = false ) {
220
+ return filter_var( array_get( $array, $key, $default ), FILTER_VALIDATE_BOOLEAN );
221
+ }
222
+ }
223
+
224
+ /**
225
+ * Convert a string value into boolean, based on whether the value "True" or "False" is present.
226
+ *
227
+ * @since 5.5
228
+ * @param string $string String value to compare.
229
+ * @return bool True if string is "True", False otherwise.
230
+ */
231
+ function bd_to_bool( $string ) {
232
+ return filter_var( $string, FILTER_VALIDATE_BOOLEAN );
233
+ }
234
+
235
+ /**
236
+ * Get the formatted list of allowed mime types.
237
+ * This function was originally defined in the Bulk Delete Attachment addon.
238
+ *
239
+ * @since 5.5
240
+ * @return array List of allowed mime types after formatting
241
+ */
242
+ function bd_get_allowed_mime_types() {
243
+ $mime_types = get_allowed_mime_types();
244
+ sort( $mime_types );
245
+
246
+ $processed_mime_types = array();
247
+ $processed_mime_types['all'] = __( 'All mime types', 'bulk-delete' );
248
+
249
+ $last_value = '';
250
+ foreach ( $mime_types as $key => $value ) {
251
+ $splitted = explode( '/', $value, 2 );
252
+ $prefix = $splitted[0];
253
+
254
+ if ( '' == $last_value || $prefix != $last_value ) {
255
+ $processed_mime_types[ $prefix ] = __( 'All', 'bulk-delete' ) . ' ' . $prefix;
256
+ $last_value = $prefix;
257
+ }
258
+
259
+ $processed_mime_types[ $value ] = $value;
260
+ }
261
+
262
+ return $processed_mime_types;
263
+ }
264
+ ?>
include/util/class-bulk-delete-by-days.php ADDED
@@ -0,0 +1,55 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Class that encapsulates the deletion of posts based on days
4
+ *
5
+ * @author Sudar
6
+ * @package BulkDelete
7
+ */
8
+
9
+ defined( 'ABSPATH' ) || exit; // Exit if accessed directly
10
+
11
+ class Bulk_Delete_By_Days {
12
+ var $days;
13
+ var $op;
14
+
15
+ /**
16
+ * Default constructor.
17
+ */
18
+ public function __construct() {
19
+ add_action( 'parse_query', array( $this, 'parse_query' ) );
20
+ }
21
+
22
+ /**
23
+ * Parse the query.
24
+ *
25
+ * @param array $query
26
+ */
27
+ public function parse_query( $query ) {
28
+ if ( isset( $query->query_vars['days'] ) ) {
29
+ $this->days = $query->query_vars['days'];
30
+ $this->op = $query->query_vars['op'];
31
+
32
+ add_filter( 'posts_where', array( $this, 'filter_where' ) );
33
+ add_filter( 'posts_selection', array( $this, 'remove_where' ) );
34
+ }
35
+ }
36
+
37
+ /**
38
+ * Modify the where clause.
39
+ *
40
+ * @param string $where (optional)
41
+ * @return string
42
+ */
43
+ public function filter_where( $where = '' ) {
44
+ $where .= ' AND post_date ' . $this->op . " '" . date( 'y-m-d', strtotime( '-' . $this->days . ' days' ) ) . "'";
45
+ return $where;
46
+ }
47
+
48
+ /**
49
+ * Remove the `posts_where` filter.
50
+ */
51
+ public function remove_where() {
52
+ remove_filter( 'posts_where', array( $this, 'filter_where' ) );
53
+ }
54
+ }
55
+ ?>
include/util/query.php ADDED
@@ -0,0 +1,79 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Utility and wrapper functions for WP_Query.
4
+ *
5
+ * @since 5.5
6
+ * @author Sudar
7
+ * @package BulkDelete\Util
8
+ */
9
+
10
+ defined( 'ABSPATH' ) || exit; // Exit if accessed directly
11
+
12
+ /**
13
+ * Process delete options array and build query.
14
+ *
15
+ * @param array $delete_options Delete Options
16
+ * @param array $options (optional) Options query
17
+ */
18
+ function bd_build_query_options( $delete_options, $options = array() ) {
19
+ // private posts
20
+ if ( isset( $delete_options['private'] ) ) {
21
+ if ( $delete_options['private'] ) {
22
+ $options['post_status'] = 'private';
23
+ } else {
24
+ if ( ! isset( $options['post_status'] ) ) {
25
+ $options['post_status'] = 'publish';
26
+ }
27
+ }
28
+ }
29
+
30
+ // limit to query
31
+ if ( $delete_options['limit_to'] > 0 ) {
32
+ $options['showposts'] = $delete_options['limit_to'];
33
+ } else {
34
+ $options['nopaging'] = 'true';
35
+ }
36
+
37
+ // post type
38
+ if ( isset( $delete_options['post_type'] ) ) {
39
+ $options['post_type'] = $delete_options['post_type'];
40
+ }
41
+
42
+ // date query
43
+ if ( $delete_options['restrict'] ) {
44
+ if ( 'before' === $delete_options['date_op'] || 'after' === $delete_options['date_op'] ) {
45
+ $options['date_query'] = array(
46
+ array(
47
+ 'column' => 'post_date',
48
+ $delete_options['date_op'] => "{$delete_options['days']} day ago",
49
+ ),
50
+ );
51
+ }
52
+ }
53
+
54
+ return $options;
55
+ }
56
+
57
+ /**
58
+ * Wrapper for WP_query.
59
+ *
60
+ * Adds some performance enhancing defaults.
61
+ *
62
+ * @since 5.5
63
+ * @param array $options List of options
64
+ * @return array Result array
65
+ */
66
+ function bd_query( $options ) {
67
+ $defaults = array(
68
+ 'cache_results' => false, // don't cache results
69
+ 'update_post_meta_cache' => false, // No need to fetch post meta fields
70
+ 'update_post_term_cache' => false, // No need to fetch taxonomy fields
71
+ 'no_found_rows' => true, // No need for pagination
72
+ 'fields' => 'ids', // retrieve only ids
73
+ );
74
+ $options = wp_parse_args( $options, $defaults );
75
+
76
+ $wp_query = new WP_Query();
77
+ return $wp_query->query( $options );
78
+ }
79
+ ?>
js/bulk-delete.js DELETED
@@ -1,144 +0,0 @@
1
- /**
2
- * JavaScript for Bulk Delete Plugin
3
- *
4
- * http://sudarmuthu.com/wordpress/bulk-delete
5
- *
6
- * @author: Sudar <http://sudarmuthu.com>
7
- *
8
- */
9
-
10
- /*jslint browser: true, devel: true*/
11
- /*global BulkWP, jQuery, document, postboxes, pagenow*/
12
- jQuery(document).ready(function () {
13
- /**
14
- * Enable Postbox handling
15
- */
16
- postboxes.add_postbox_toggles(pagenow);
17
-
18
- /**
19
- * Toggle the date restrict fields
20
- */
21
- function toggle_date_restrict(el) {
22
- if (jQuery("#smbd" + el + "_restrict").is(":checked")) {
23
- jQuery("#smbd" + el + "_op").removeAttr('disabled');
24
- jQuery("#smbd" + el + "_days").removeAttr('disabled');
25
- } else {
26
- jQuery("#smbd" + el + "_op").attr('disabled', 'true');
27
- jQuery("#smbd" + el + "_days").attr('disabled', 'true');
28
- }
29
- }
30
-
31
- /**
32
- * Toggle limit restrict fields
33
- */
34
- function toggle_limit_restrict(el) {
35
- if (jQuery("#smbd" + el + "_limit").is(":checked")) {
36
- jQuery("#smbd" + el + "_limit_to").removeAttr('disabled');
37
- } else {
38
- jQuery("#smbd" + el + "_limit_to").attr('disabled', 'true');
39
- }
40
- }
41
-
42
- // hide all terms
43
- function hideAllTerms() {
44
- jQuery('table.terms').hide();
45
- jQuery('input.terms').attr('checked', false);
46
- }
47
- // call it for the first time
48
- hideAllTerms();
49
-
50
- // taxonomy click handling
51
- jQuery('.custom-tax').change(function () {
52
- var $this = jQuery(this),
53
- $tax = $this.val(),
54
- $terms = jQuery('table.terms_' + $tax);
55
-
56
- if ($this.is(':checked')) {
57
- hideAllTerms();
58
- $terms.show('slow');
59
- }
60
- });
61
-
62
- // Handle selection of all checkboxes of cats
63
- jQuery('#smbd_cats_all').change(function () {
64
- if (jQuery(this).is(':checked')) {
65
- jQuery('input[name="smbd_cats[]"]').attr('checked', true);
66
- } else {
67
- jQuery('input[name="smbd_cats[]"]').attr('checked', false);
68
- }
69
- });
70
-
71
- // Handle selection of all checkboxes of tags
72
- jQuery('#smbd_tags_all').change(function () {
73
- if (jQuery(this).is(':checked')) {
74
- jQuery('input[name="smbd_tags[]"]').attr('checked', true);
75
- } else {
76
- jQuery('input[name="smbd_tags[]"]').attr('checked', false);
77
- }
78
- });
79
-
80
- // date time picker
81
- jQuery.each(BulkWP.dt_iterators, function (index, value) {
82
- // invoke the date time picker
83
- jQuery('#smbd' + value + '_cron_start').datetimepicker({
84
- timeFormat: 'HH:mm:ss'
85
- });
86
-
87
- jQuery('#smbd' + value + '_restrict').change(function () {
88
- toggle_date_restrict(value);
89
- });
90
-
91
- jQuery('#smbd' + value + '_limit').change(function () {
92
- toggle_limit_restrict(value);
93
- });
94
-
95
- });
96
-
97
- // Validate user action
98
- jQuery('button[name="bd_action"]').click(function () {
99
- var currentButton = jQuery(this).val(),
100
- valid = false,
101
- msg_key = "deletePostsWarning",
102
- error_key = "selectPostOption";
103
-
104
- if (currentButton in BulkWP.validators) {
105
- valid = BulkWP[BulkWP.validators[currentButton]](this)
106
- } else {
107
- if (jQuery(this).parent().prev().children('table').find(":checkbox:checked[value!='true']").size() > 0) {
108
- // monstrous selector
109
- valid = true;
110
- }
111
- }
112
-
113
- if (valid) {
114
- if (currentButton in BulkWP.pre_action_msg) {
115
- msg_key = BulkWP.pre_action_msg[currentButton];
116
- }
117
-
118
- return confirm(BulkWP.msg[msg_key])
119
- } else {
120
- if (currentButton in BulkWP.error_msg) {
121
- error_key = BulkWP.error_msg[currentButton];
122
- }
123
-
124
- alert(BulkWP.msg[error_key]);
125
- }
126
-
127
- return false;
128
- });
129
-
130
- /**
131
- * Validation functions
132
- */
133
- BulkWP.noValidation = function(that) {
134
- return true;
135
- }
136
-
137
- BulkWP.validateUrl = function(that) {
138
- if (jQuery(that).parent().prev().children('table').find("textarea").val() !== '') {
139
- return true;
140
- } else {
141
- return false;
142
- }
143
- }
144
- });
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
js/jquery-ui-timepicker.js DELETED
@@ -1,2134 +0,0 @@
1
- /*! jQuery Timepicker Addon - v1.4 - 2013-08-11
2
- * http://trentrichardson.com/examples/timepicker
3
- * Copyright (c) 2013 Trent Richardson; Licensed MIT */
4
- (function ($) {
5
-
6
- /*
7
- * Lets not redefine timepicker, Prevent "Uncaught RangeError: Maximum call stack size exceeded"
8
- */
9
- $.ui.timepicker = $.ui.timepicker || {};
10
- if ($.ui.timepicker.version) {
11
- return;
12
- }
13
-
14
- /*
15
- * Extend jQueryUI, get it started with our version number
16
- */
17
- $.extend($.ui, {
18
- timepicker: {
19
- version: "1.4"
20
- }
21
- });
22
-
23
- /*
24
- * Timepicker manager.
25
- * Use the singleton instance of this class, $.timepicker, to interact with the time picker.
26
- * Settings for (groups of) time pickers are maintained in an instance object,
27
- * allowing multiple different settings on the same page.
28
- */
29
- var Timepicker = function () {
30
- this.regional = []; // Available regional settings, indexed by language code
31
- this.regional[''] = { // Default regional settings
32
- currentText: 'Now',
33
- closeText: 'Done',
34
- amNames: ['AM', 'A'],
35
- pmNames: ['PM', 'P'],
36
- timeFormat: 'HH:mm',
37
- timeSuffix: '',
38
- timeOnlyTitle: 'Choose Time',
39
- timeText: 'Time',
40
- hourText: 'Hour',
41
- minuteText: 'Minute',
42
- secondText: 'Second',
43
- millisecText: 'Millisecond',
44
- microsecText: 'Microsecond',
45
- timezoneText: 'Time Zone',
46
- isRTL: false
47
- };
48
- this._defaults = { // Global defaults for all the datetime picker instances
49
- showButtonPanel: true,
50
- timeOnly: false,
51
- showHour: null,
52
- showMinute: null,
53
- showSecond: null,
54
- showMillisec: null,
55
- showMicrosec: null,
56
- showTimezone: null,
57
- showTime: true,
58
- stepHour: 1,
59
- stepMinute: 1,
60
- stepSecond: 1,
61
- stepMillisec: 1,
62
- stepMicrosec: 1,
63
- hour: 0,
64
- minute: 0,
65
- second: 0,
66
- millisec: 0,
67
- microsec: 0,
68
- timezone: null,
69
- hourMin: 0,
70
- minuteMin: 0,
71
- secondMin: 0,
72
- millisecMin: 0,
73
- microsecMin: 0,
74
- hourMax: 23,
75
- minuteMax: 59,
76
- secondMax: 59,
77
- millisecMax: 999,
78
- microsecMax: 999,
79
- minDateTime: null,
80
- maxDateTime: null,
81
- onSelect: null,
82
- hourGrid: 0,
83
- minuteGrid: 0,
84
- secondGrid: 0,
85
- millisecGrid: 0,
86
- microsecGrid: 0,
87
- alwaysSetTime: true,
88
- separator: ' ',
89
- altFieldTimeOnly: true,
90
- altTimeFormat: null,
91
- altSeparator: null,
92
- altTimeSuffix: null,
93
- pickerTimeFormat: null,
94
- pickerTimeSuffix: null,
95
- showTimepicker: true,
96
- timezoneList: null,
97
- addSliderAccess: false,
98
- sliderAccessArgs: null,
99
- controlType: 'slider',
100
- defaultValue: null,
101
- parse: 'strict'
102
- };
103
- $.extend(this._defaults, this.regional['']);
104
- };
105
-
106
- $.extend(Timepicker.prototype, {
107
- $input: null,
108
- $altInput: null,
109
- $timeObj: null,
110
- inst: null,
111
- hour_slider: null,
112
- minute_slider: null,
113
- second_slider: null,
114
- millisec_slider: null,
115
- microsec_slider: null,
116
- timezone_select: null,
117
- hour: 0,
118
- minute: 0,
119
- second: 0,
120
- millisec: 0,
121
- microsec: 0,
122
- timezone: null,
123
- hourMinOriginal: null,
124
- minuteMinOriginal: null,
125
- secondMinOriginal: null,
126
- millisecMinOriginal: null,
127
- microsecMinOriginal: null,
128
- hourMaxOriginal: null,
129
- minuteMaxOriginal: null,
130
- secondMaxOriginal: null,
131
- millisecMaxOriginal: null,
132
- microsecMaxOriginal: null,
133
- ampm: '',
134
- formattedDate: '',
135
- formattedTime: '',
136
- formattedDateTime: '',
137
- timezoneList: null,
138
- units: ['hour', 'minute', 'second', 'millisec', 'microsec'],
139
- support: {},
140
- control: null,
141
-
142
- /*
143
- * Override the default settings for all instances of the time picker.
144
- * @param {Object} settings object - the new settings to use as defaults (anonymous object)
145
- * @return {Object} the manager object
146
- */
147
- setDefaults: function (settings) {
148
- extendRemove(this._defaults, settings || {});
149
- return this;
150
- },
151
-
152
- /*
153
- * Create a new Timepicker instance
154
- */
155
- _newInst: function ($input, opts) {
156
- var tp_inst = new Timepicker(),
157
- inlineSettings = {},
158
- fns = {},
159
- overrides, i;
160
-
161
- for (var attrName in this._defaults) {
162
- if (this._defaults.hasOwnProperty(attrName)) {
163
- var attrValue = $input.attr('time:' + attrName);
164
- if (attrValue) {
165
- try {
166
- inlineSettings[attrName] = eval(attrValue);
167
- } catch (err) {
168
- inlineSettings[attrName] = attrValue;
169
- }
170
- }
171
- }
172
- }
173
-
174
- overrides = {
175
- beforeShow: function (input, dp_inst) {
176
- if ($.isFunction(tp_inst._defaults.evnts.beforeShow)) {
177
- return tp_inst._defaults.evnts.beforeShow.call($input[0], input, dp_inst, tp_inst);
178
- }
179
- },
180
- onChangeMonthYear: function (year, month, dp_inst) {
181
- // Update the time as well : this prevents the time from disappearing from the $input field.
182
- tp_inst._updateDateTime(dp_inst);
183
- if ($.isFunction(tp_inst._defaults.evnts.onChangeMonthYear)) {
184
- tp_inst._defaults.evnts.onChangeMonthYear.call($input[0], year, month, dp_inst, tp_inst);
185
- }
186
- },
187
- onClose: function (dateText, dp_inst) {
188
- if (tp_inst.timeDefined === true && $input.val() !== '') {
189
- tp_inst._updateDateTime(dp_inst);
190
- }
191
- if ($.isFunction(tp_inst._defaults.evnts.onClose)) {
192
- tp_inst._defaults.evnts.onClose.call($input[0], dateText, dp_inst, tp_inst);
193
- }
194
- }
195
- };
196
- for (i in overrides) {
197
- if (overrides.hasOwnProperty(i)) {
198
- fns[i] = opts[i] || null;
199
- }
200
- }
201
-
202
- tp_inst._defaults = $.extend({}, this._defaults, inlineSettings, opts, overrides, {
203
- evnts: fns,
204
- timepicker: tp_inst // add timepicker as a property of datepicker: $.datepicker._get(dp_inst, 'timepicker');
205
- });
206
- tp_inst.amNames = $.map(tp_inst._defaults.amNames, function (val) {
207
- return val.toUpperCase();
208
- });
209
- tp_inst.pmNames = $.map(tp_inst._defaults.pmNames, function (val) {
210
- return val.toUpperCase();
211
- });
212
-
213
- // detect which units are supported
214
- tp_inst.support = detectSupport(
215
- tp_inst._defaults.timeFormat +
216
- (tp_inst._defaults.pickerTimeFormat ? tp_inst._defaults.pickerTimeFormat : '') +
217
- (tp_inst._defaults.altTimeFormat ? tp_inst._defaults.altTimeFormat : ''));
218
-
219
- // controlType is string - key to our this._controls
220
- if (typeof(tp_inst._defaults.controlType) === 'string') {
221
- if (tp_inst._defaults.controlType === 'slider' && typeof($.ui.slider) === 'undefined') {
222
- tp_inst._defaults.controlType = 'select';
223
- }
224
- tp_inst.control = tp_inst._controls[tp_inst._defaults.controlType];
225
- }
226
- // controlType is an object and must implement create, options, value methods
227
- else {
228
- tp_inst.control = tp_inst._defaults.controlType;
229
- }
230
-
231
- // prep the timezone options
232
- var timezoneList = [-720, -660, -600, -570, -540, -480, -420, -360, -300, -270, -240, -210, -180, -120, -60,
233
- 0, 60, 120, 180, 210, 240, 270, 300, 330, 345, 360, 390, 420, 480, 525, 540, 570, 600, 630, 660, 690, 720, 765, 780, 840];
234
- if (tp_inst._defaults.timezoneList !== null) {
235
- timezoneList = tp_inst._defaults.timezoneList;
236
- }
237
- var tzl = timezoneList.length, tzi = 0, tzv = null;
238
- if (tzl > 0 && typeof timezoneList[0] !== 'object') {
239
- for (; tzi < tzl; tzi++) {
240
- tzv = timezoneList[tzi];
241
- timezoneList[tzi] = { value: tzv, label: $.timepicker.timezoneOffsetString(tzv, tp_inst.support.iso8601) };
242
- }
243
- }
244
- tp_inst._defaults.timezoneList = timezoneList;
245
-
246
- // set the default units
247
- tp_inst.timezone = tp_inst._defaults.timezone !== null ? $.timepicker.timezoneOffsetNumber(tp_inst._defaults.timezone) :
248
- ((new Date()).getTimezoneOffset() * -1);
249
- tp_inst.hour = tp_inst._defaults.hour < tp_inst._defaults.hourMin ? tp_inst._defaults.hourMin :
250
- tp_inst._defaults.hour > tp_inst._defaults.hourMax ? tp_inst._defaults.hourMax : tp_inst._defaults.hour;
251
- tp_inst.minute = tp_inst._defaults.minute < tp_inst._defaults.minuteMin ? tp_inst._defaults.minuteMin :
252
- tp_inst._defaults.minute > tp_inst._defaults.minuteMax ? tp_inst._defaults.minuteMax : tp_inst._defaults.minute;
253
- tp_inst.second = tp_inst._defaults.second < tp_inst._defaults.secondMin ? tp_inst._defaults.secondMin :
254
- tp_inst._defaults.second > tp_inst._defaults.secondMax ? tp_inst._defaults.secondMax : tp_inst._defaults.second;
255
- tp_inst.millisec = tp_inst._defaults.millisec < tp_inst._defaults.millisecMin ? tp_inst._defaults.millisecMin :
256
- tp_inst._defaults.millisec > tp_inst._defaults.millisecMax ? tp_inst._defaults.millisecMax : tp_inst._defaults.millisec;
257
- tp_inst.microsec = tp_inst._defaults.microsec < tp_inst._defaults.microsecMin ? tp_inst._defaults.microsecMin :
258
- tp_inst._defaults.microsec > tp_inst._defaults.microsecMax ? tp_inst._defaults.microsecMax : tp_inst._defaults.microsec;
259
- tp_inst.ampm = '';
260
- tp_inst.$input = $input;
261
-
262
- if (tp_inst._defaults.altField) {
263
- tp_inst.$altInput = $(tp_inst._defaults.altField).css({
264
- cursor: 'pointer'
265
- }).focus(function () {
266
- $input.trigger("focus");
267
- });
268
- }
269
-
270
- if (tp_inst._defaults.minDate === 0 || tp_inst._defaults.minDateTime === 0) {
271
- tp_inst._defaults.minDate = new Date();
272
- }
273
- if (tp_inst._defaults.maxDate === 0 || tp_inst._defaults.maxDateTime === 0) {
274
- tp_inst._defaults.maxDate = new Date();
275
- }
276
-
277
- // datepicker needs minDate/maxDate, timepicker needs minDateTime/maxDateTime..
278
- if (tp_inst._defaults.minDate !== undefined && tp_inst._defaults.minDate instanceof Date) {
279
- tp_inst._defaults.minDateTime = new Date(tp_inst._defaults.minDate.getTime());
280
- }
281
- if (tp_inst._defaults.minDateTime !== undefined && tp_inst._defaults.minDateTime instanceof Date) {
282
- tp_inst._defaults.minDate = new Date(tp_inst._defaults.minDateTime.getTime());
283
- }
284
- if (tp_inst._defaults.maxDate !== undefined && tp_inst._defaults.maxDate instanceof Date) {
285
- tp_inst._defaults.maxDateTime = new Date(tp_inst._defaults.maxDate.getTime());
286
- }
287
- if (tp_inst._defaults.maxDateTime !== undefined && tp_inst._defaults.maxDateTime instanceof Date) {
288
- tp_inst._defaults.maxDate = new Date(tp_inst._defaults.maxDateTime.getTime());
289
- }
290
- tp_inst.$input.bind('focus', function () {
291
- tp_inst._onFocus();
292
- });
293
-
294
- return tp_inst;
295
- },
296
-
297
- /*
298
- * add our sliders to the calendar
299
- */
300
- _addTimePicker: function (dp_inst) {
301
- var currDT = (this.$altInput && this._defaults.altFieldTimeOnly) ? this.$input.val() + ' ' + this.$altInput.val() : this.$input.val();
302
-
303
- this.timeDefined = this._parseTime(currDT);
304
- this._limitMinMaxDateTime(dp_inst, false);
305
- this._injectTimePicker();
306
- },
307
-
308
- /*
309
- * parse the time string from input value or _setTime
310
- */
311
- _parseTime: function (timeString, withDate) {
312
- if (!this.inst) {
313
- this.inst = $.datepicker._getInst(this.$input[0]);
314
- }
315
-
316
- if (withDate || !this._defaults.timeOnly) {
317
- var dp_dateFormat = $.datepicker._get(this.inst, 'dateFormat');
318
- try {
319
- var parseRes = parseDateTimeInternal(dp_dateFormat, this._defaults.timeFormat, timeString, $.datepicker._getFormatConfig(this.inst), this._defaults);
320
- if (!parseRes.timeObj) {
321
- return false;
322
- }
323
- $.extend(this, parseRes.timeObj);
324
- } catch (err) {
325
- $.timepicker.log("Error parsing the date/time string: " + err +
326
- "\ndate/time string = " + timeString +
327
- "\ntimeFormat = " + this._defaults.timeFormat +
328
- "\ndateFormat = " + dp_dateFormat);
329
- return false;
330
- }
331
- return true;
332
- } else {
333
- var timeObj = $.datepicker.parseTime(this._defaults.timeFormat, timeString, this._defaults);
334
- if (!timeObj) {
335
- return false;
336
- }
337
- $.extend(this, timeObj);
338
- return true;
339
- }
340
- },
341
-
342
- /*
343
- * generate and inject html for timepicker into ui datepicker
344
- */
345
- _injectTimePicker: function () {
346
- var $dp = this.inst.dpDiv,
347
- o = this.inst.settings,
348
- tp_inst = this,
349
- litem = '',
350
- uitem = '',
351
- show = null,
352
- max = {},
353
- gridSize = {},
354
- size = null,
355
- i = 0,
356
- l = 0;
357
-
358
- // Prevent displaying twice
359
- if ($dp.find("div.ui-timepicker-div").length === 0 && o.showTimepicker) {
360
- var noDisplay = ' style="display:none;"',
361
- html = '<div class="ui-timepicker-div' + (o.isRTL ? ' ui-timepicker-rtl' : '') + '"><dl>' + '<dt class="ui_tpicker_time_label"' + ((o.showTime) ? '' : noDisplay) + '>' + o.timeText + '</dt>' +
362
- '<dd class="ui_tpicker_time"' + ((o.showTime) ? '' : noDisplay) + '></dd>';
363
-
364
- // Create the markup
365
- for (i = 0, l = this.units.length; i < l; i++) {
366
- litem = this.units[i];
367
- uitem = litem.substr(0, 1).toUpperCase() + litem.substr(1);
368
- show = o['show' + uitem] !== null ? o['show' + uitem] : this.support[litem];
369
-
370
- // Added by Peter Medeiros:
371
- // - Figure out what the hour/minute/second max should be based on the step values.
372
- // - Example: if stepMinute is 15, then minMax is 45.
373
- max[litem] = parseInt((o[litem + 'Max'] - ((o[litem + 'Max'] - o[litem + 'Min']) % o['step' + uitem])), 10);
374
- gridSize[litem] = 0;
375
-
376
- html += '<dt class="ui_tpicker_' + litem + '_label"' + (show ? '' : noDisplay) + '>' + o[litem + 'Text'] + '</dt>' +
377
- '<dd class="ui_tpicker_' + litem + '"><div class="ui_tpicker_' + litem + '_slider"' + (show ? '' : noDisplay) + '></div>';
378
-
379
- if (show && o[litem + 'Grid'] > 0) {
380
- html += '<div style="padding-left: 1px"><table class="ui-tpicker-grid-label"><tr>';
381
-
382
- if (litem === 'hour') {
383
- for (var h = o[litem + 'Min']; h <= max[litem]; h += parseInt(o[litem + 'Grid'], 10)) {
384
- gridSize[litem]++;
385
- var tmph = $.datepicker.formatTime(this.support.ampm ? 'hht' : 'HH', {hour: h}, o);
386
- html += '<td data-for="' + litem + '">' + tmph + '</td>';
387
- }
388
- }
389
- else {
390
- for (var m = o[litem + 'Min']; m <= max[litem]; m += parseInt(o[litem + 'Grid'], 10)) {
391
- gridSize[litem]++;
392
- html += '<td data-for="' + litem + '">' + ((m < 10) ? '0' : '') + m + '</td>';
393
- }
394
- }
395
-
396
- html += '</tr></table></div>';
397
- }
398
- html += '</dd>';
399
- }
400
-
401
- // Timezone
402
- var showTz = o.showTimezone !== null ? o.showTimezone : this.support.timezone;
403
- html += '<dt class="ui_tpicker_timezone_label"' + (showTz ? '' : noDisplay) + '>' + o.timezoneText + '</dt>';
404
- html += '<dd class="ui_tpicker_timezone" ' + (showTz ? '' : noDisplay) + '></dd>';
405
-
406
- // Create the elements from string
407
- html += '</dl></div>';
408
- var $tp = $(html);
409
-
410
- // if we only want time picker...
411
- if (o.timeOnly === true) {
412
- $tp.prepend('<div class="ui-widget-header ui-helper-clearfix ui-corner-all">' + '<div class="ui-datepicker-title">' + o.timeOnlyTitle + '</div>' + '</div>');
413
- $dp.find('.ui-datepicker-header, .ui-datepicker-calendar').hide();
414
- }
415
-
416
- // add sliders, adjust grids, add events
417
- for (i = 0, l = tp_inst.units.length; i < l; i++) {
418
- litem = tp_inst.units[i];
419
- uitem = litem.substr(0, 1).toUpperCase() + litem.substr(1);
420
- show = o['show' + uitem] !== null ? o['show' + uitem] : this.support[litem];
421
-
422
- // add the slider
423
- tp_inst[litem + '_slider'] = tp_inst.control.create(tp_inst, $tp.find('.ui_tpicker_' + litem + '_slider'), litem, tp_inst[litem], o[litem + 'Min'], max[litem], o['step' + uitem]);
424
-
425
- // adjust the grid and add click event
426
- if (show && o[litem + 'Grid'] > 0) {
427
- size = 100 * gridSize[litem] * o[litem + 'Grid'] / (max[litem] - o[litem + 'Min']);
428
- $tp.find('.ui_tpicker_' + litem + ' table').css({
429
- width: size + "%",
430
- marginLeft: o.isRTL ? '0' : ((size / (-2 * gridSize[litem])) + "%"),
431
- marginRight: o.isRTL ? ((size / (-2 * gridSize[litem])) + "%") : '0',
432
- borderCollapse: 'collapse'
433
- }).find("td").click(function (e) {
434
- var $t = $(this),
435
- h = $t.html(),
436
- n = parseInt(h.replace(/[^0-9]/g), 10),
437
- ap = h.replace(/[^apm]/ig),
438
- f = $t.data('for'); // loses scope, so we use data-for
439
-
440
- if (f === 'hour') {
441
- if (ap.indexOf('p') !== -1 && n < 12) {
442
- n += 12;
443
- }
444
- else {
445
- if (ap.indexOf('a') !== -1 && n === 12) {
446
- n = 0;
447
- }
448
- }
449
- }
450
-
451
- tp_inst.control.value(tp_inst, tp_inst[f + '_slider'], litem, n);
452
-
453
- tp_inst._onTimeChange();
454
- tp_inst._onSelectHandler();
455
- }).css({
456
- cursor: 'pointer',
457
- width: (100 / gridSize[litem]) + '%',
458
- textAlign: 'center',
459
- overflow: 'hidden'
460
- });
461
- } // end if grid > 0
462
- } // end for loop
463
-
464
- // Add timezone options
465
- this.timezone_select = $tp.find('.ui_tpicker_timezone').append('<select></select>').find("select");
466
- $.fn.append.apply(this.timezone_select,
467
- $.map(o.timezoneList, function (val, idx) {
468
- return $("<option />").val(typeof val === "object" ? val.value : val).text(typeof val === "object" ? val.label : val);
469
- }));
470
- if (typeof(this.timezone) !== "undefined" && this.timezone !== null && this.timezone !== "") {
471
- var local_timezone = (new Date(this.inst.selectedYear, this.inst.selectedMonth, this.inst.selectedDay, 12)).getTimezoneOffset() * -1;
472
- if (local_timezone === this.timezone) {
473
- selectLocalTimezone(tp_inst);
474
- } else {
475
- this.timezone_select.val(this.timezone);
476
- }
477
- } else {
478
- if (typeof(this.hour) !== "undefined" && this.hour !== null && this.hour !== "") {
479
- this.timezone_select.val(o.timezone);
480
- } else {
481
- selectLocalTimezone(tp_inst);
482
- }
483
- }
484
- this.timezone_select.change(function () {
485
- tp_inst._onTimeChange();
486
- tp_inst._onSelectHandler();
487
- });
488
- // End timezone options
489
-
490
- // inject timepicker into datepicker
491
- var $buttonPanel = $dp.find('.ui-datepicker-buttonpane');
492
- if ($buttonPanel.length) {
493
- $buttonPanel.before($tp);
494
- } else {
495
- $dp.append($tp);
496
- }
497
-
498
- this.$timeObj = $tp.find('.ui_tpicker_time');
499
-
500
- if (this.inst !== null) {
501
- var timeDefined = this.timeDefined;
502
- this._onTimeChange();
503
- this.timeDefined = timeDefined;
504
- }
505
-
506
- // slideAccess integration: http://trentrichardson.com/2011/11/11/jquery-ui-sliders-and-touch-accessibility/
507
- if (this._defaults.addSliderAccess) {
508
- var sliderAccessArgs = this._defaults.sliderAccessArgs,
509
- rtl = this._defaults.isRTL;
510
- sliderAccessArgs.isRTL = rtl;
511
-
512
- setTimeout(function () { // fix for inline mode
513
- if ($tp.find('.ui-slider-access').length === 0) {
514
- $tp.find('.ui-slider:visible').sliderAccess(sliderAccessArgs);
515
-
516
- // fix any grids since sliders are shorter
517
- var sliderAccessWidth = $tp.find('.ui-slider-access:eq(0)').outerWidth(true);
518
- if (sliderAccessWidth) {
519
- $tp.find('table:visible').each(function () {
520
- var $g = $(this),
521
- oldWidth = $g.outerWidth(),
522
- oldMarginLeft = $g.css(rtl ? 'marginRight' : 'marginLeft').toString().replace('%', ''),
523
- newWidth = oldWidth - sliderAccessWidth,
524
- newMarginLeft = ((oldMarginLeft * newWidth) / oldWidth) + '%',
525
- css = { width: newWidth, marginRight: 0, marginLeft: 0 };
526
- css[rtl ? 'marginRight' : 'marginLeft'] = newMarginLeft;
527
- $g.css(css);
528
- });
529
- }
530
- }
531
- }, 10);
532
- }
533
- // end slideAccess integration
534
-
535
- tp_inst._limitMinMaxDateTime(this.inst, true);
536
- }
537
- },
538
-
539
- /*
540
- * This function tries to limit the ability to go outside the
541
- * min/max date range
542
- */
543
- _limitMinMaxDateTime: function (dp_inst, adjustSliders) {
544
- var o = this._defaults,
545
- dp_date = new Date(dp_inst.selectedYear, dp_inst.selectedMonth, dp_inst.selectedDay);
546
-
547
- if (!this._defaults.showTimepicker) {
548
- return;
549
- } // No time so nothing to check here
550
-
551
- if ($.datepicker._get(dp_inst, 'minDateTime') !== null && $.datepicker._get(dp_inst, 'minDateTime') !== undefined && dp_date) {
552
- var minDateTime = $.datepicker._get(dp_inst, 'minDateTime'),
553
- minDateTimeDate = new Date(minDateTime.getFullYear(), minDateTime.getMonth(), minDateTime.getDate(), 0, 0, 0, 0);
554
-
555
- if (this.hourMinOriginal === null || this.minuteMinOriginal === null || this.secondMinOriginal === null || this.millisecMinOriginal === null || this.microsecMinOriginal === null) {
556
- this.hourMinOriginal = o.hourMin;
557
- this.minuteMinOriginal = o.minuteMin;
558
- this.secondMinOriginal = o.secondMin;
559
- this.millisecMinOriginal = o.millisecMin;
560
- this.microsecMinOriginal = o.microsecMin;
561
- }
562
-
563
- if (dp_inst.settings.timeOnly || minDateTimeDate.getTime() === dp_date.getTime()) {
564
- this._defaults.hourMin = minDateTime.getHours();
565
- if (this.hour <= this._defaults.hourMin) {
566
- this.hour = this._defaults.hourMin;
567
- this._defaults.minuteMin = minDateTime.getMinutes();
568
- if (this.minute <= this._defaults.minuteMin) {
569
- this.minute = this._defaults.minuteMin;
570
- this._defaults.secondMin = minDateTime.getSeconds();
571
- if (this.second <= this._defaults.secondMin) {
572
- this.second = this._defaults.secondMin;
573
- this._defaults.millisecMin = minDateTime.getMilliseconds();
574
- if (this.millisec <= this._defaults.millisecMin) {
575
- this.millisec = this._defaults.millisecMin;
576
- this._defaults.microsecMin = minDateTime.getMicroseconds();
577
- } else {
578
- if (this.microsec < this._defaults.microsecMin) {
579
- this.microsec = this._defaults.microsecMin;
580
- }
581
- this._defaults.microsecMin = this.microsecMinOriginal;
582
- }
583
- } else {
584
- this._defaults.millisecMin = this.millisecMinOriginal;
585
- this._defaults.microsecMin = this.microsecMinOriginal;
586
- }
587
- } else {
588
- this._defaults.secondMin = this.secondMinOriginal;
589
- this._defaults.millisecMin = this.millisecMinOriginal;
590
- this._defaults.microsecMin = this.microsecMinOriginal;
591
- }
592
- } else {
593
- this._defaults.minuteMin = this.minuteMinOriginal;
594
- this._defaults.secondMin = this.secondMinOriginal;
595
- this._defaults.millisecMin = this.millisecMinOriginal;
596
- this._defaults.microsecMin = this.microsecMinOriginal;
597
- }
598
- } else {
599
- this._defaults.hourMin = this.hourMinOriginal;
600
- this._defaults.minuteMin = this.minuteMinOriginal;
601
- this._defaults.secondMin = this.secondMinOriginal;
602
- this._defaults.millisecMin = this.millisecMinOriginal;
603
- this._defaults.microsecMin = this.microsecMinOriginal;
604
- }
605
- }
606
-
607
- if ($.datepicker._get(dp_inst, 'maxDateTime') !== null && $.datepicker._get(dp_inst, 'maxDateTime') !== undefined && dp_date) {
608
- var maxDateTime = $.datepicker._get(dp_inst, 'maxDateTime'),
609
- maxDateTimeDate = new Date(maxDateTime.getFullYear(), maxDateTime.getMonth(), maxDateTime.getDate(), 0, 0, 0, 0);
610
-
611
- if (this.hourMaxOriginal === null || this.minuteMaxOriginal === null || this.secondMaxOriginal === null || this.millisecMaxOriginal === null) {
612
- this.hourMaxOriginal = o.hourMax;
613
- this.minuteMaxOriginal = o.minuteMax;
614
- this.secondMaxOriginal = o.secondMax;
615
- this.millisecMaxOriginal = o.millisecMax;
616
- this.microsecMaxOriginal = o.microsecMax;
617
- }
618
-
619
- if (dp_inst.settings.timeOnly || maxDateTimeDate.getTime() === dp_date.getTime()) {
620
- this._defaults.hourMax = maxDateTime.getHours();
621
- if (this.hour >= this._defaults.hourMax) {
622
- this.hour = this._defaults.hourMax;
623
- this._defaults.minuteMax = maxDateTime.getMinutes();
624
- if (this.minute >= this._defaults.minuteMax) {
625
- this.minute = this._defaults.minuteMax;
626
- this._defaults.secondMax = maxDateTime.getSeconds();
627
- if (this.second >= this._defaults.secondMax) {
628
- this.second = this._defaults.secondMax;
629
- this._defaults.millisecMax = maxDateTime.getMilliseconds();
630
- if (this.millisec >= this._defaults.millisecMax) {
631
- this.millisec = this._defaults.millisecMax;
632
- this._defaults.microsecMax = maxDateTime.getMicroseconds();
633
- } else {
634
- if (this.microsec > this._defaults.microsecMax) {
635
- this.microsec = this._defaults.microsecMax;
636
- }
637
- this._defaults.microsecMax = this.microsecMaxOriginal;
638
- }
639
- } else {
640
- this._defaults.millisecMax = this.millisecMaxOriginal;
641
- this._defaults.microsecMax = this.microsecMaxOriginal;
642
- }
643
- } else {
644
- this._defaults.secondMax = this.secondMaxOriginal;
645
- this._defaults.millisecMax = this.millisecMaxOriginal;
646
- this._defaults.microsecMax = this.microsecMaxOriginal;
647
- }
648
- } else {
649
- this._defaults.minuteMax = this.minuteMaxOriginal;
650
- this._defaults.secondMax = this.secondMaxOriginal;
651
- this._defaults.millisecMax = this.millisecMaxOriginal;
652
- this._defaults.microsecMax = this.microsecMaxOriginal;
653
- }
654
- } else {
655
- this._defaults.hourMax = this.hourMaxOriginal;
656
- this._defaults.minuteMax = this.minuteMaxOriginal;
657
- this._defaults.secondMax = this.secondMaxOriginal;
658
- this._defaults.millisecMax = this.millisecMaxOriginal;
659
- this._defaults.microsecMax = this.microsecMaxOriginal;
660
- }
661
- }
662
-
663
- if (adjustSliders !== undefined && adjustSliders === true) {
664
- var hourMax = parseInt((this._defaults.hourMax - ((this._defaults.hourMax - this._defaults.hourMin) % this._defaults.stepHour)), 10),
665
- minMax = parseInt((this._defaults.minuteMax - ((this._defaults.minuteMax - this._defaults.minuteMin) % this._defaults.stepMinute)), 10),
666
- secMax = parseInt((this._defaults.secondMax - ((this._defaults.secondMax - this._defaults.secondMin) % this._defaults.stepSecond)), 10),
667
- millisecMax = parseInt((this._defaults.millisecMax - ((this._defaults.millisecMax - this._defaults.millisecMin) % this._defaults.stepMillisec)), 10),
668
- microsecMax = parseInt((this._defaults.microsecMax - ((this._defaults.microsecMax - this._defaults.microsecMin) % this._defaults.stepMicrosec)), 10);
669
-
670
- if (this.hour_slider) {
671
- this.control.options(this, this.hour_slider, 'hour', { min: this._defaults.hourMin, max: hourMax });
672
- this.control.value(this, this.hour_slider, 'hour', this.hour - (this.hour % this._defaults.stepHour));
673
- }
674
- if (this.minute_slider) {
675
- this.control.options(this, this.minute_slider, 'minute', { min: this._defaults.minuteMin, max: minMax });
676
- this.control.value(this, this.minute_slider, 'minute', this.minute - (this.minute % this._defaults.stepMinute));
677
- }
678
- if (this.second_slider) {
679
- this.control.options(this, this.second_slider, 'second', { min: this._defaults.secondMin, max: secMax });
680
- this.control.value(this, this.second_slider, 'second', this.second - (this.second % this._defaults.stepSecond));
681
- }
682
- if (this.millisec_slider) {
683
- this.control.options(this, this.millisec_slider, 'millisec', { min: this._defaults.millisecMin, max: millisecMax });
684
- this.control.value(this, this.millisec_slider, 'millisec', this.millisec - (this.millisec % this._defaults.stepMillisec));
685
- }
686
- if (this.microsec_slider) {
687
- this.control.options(this, this.microsec_slider, 'microsec', { min: this._defaults.microsecMin, max: microsecMax });
688
- this.control.value(this, this.microsec_slider, 'microsec', this.microsec - (this.microsec % this._defaults.stepMicrosec));
689
- }
690
- }
691
-
692
- },
693
-
694
- /*
695
- * when a slider moves, set the internal time...
696
- * on time change is also called when the time is updated in the text field
697
- */
698
- _onTimeChange: function () {
699
- if (!this._defaults.showTimepicker) {
700
- return;
701
- }
702
- var hour = (this.hour_slider) ? this.control.value(this, this.hour_slider, 'hour') : false,
703
- minute = (this.minute_slider) ? this.control.value(this, this.minute_slider, 'minute') : false,
704
- second = (this.second_slider) ? this.control.value(this, this.second_slider, 'second') : false,
705
- millisec = (this.millisec_slider) ? this.control.value(this, this.millisec_slider, 'millisec') : false,
706
- microsec = (this.microsec_slider) ? this.control.value(this, this.microsec_slider, 'microsec') : false,
707
- timezone = (this.timezone_select) ? this.timezone_select.val() : false,
708
- o = this._defaults,
709
- pickerTimeFormat = o.pickerTimeFormat || o.timeFormat,
710
- pickerTimeSuffix = o.pickerTimeSuffix || o.timeSuffix;
711
-
712
- if (typeof(hour) === 'object') {
713
- hour = false;
714
- }
715
- if (typeof(minute) === 'object') {
716
- minute = false;
717
- }
718
- if (typeof(second) === 'object') {
719
- second = false;
720
- }
721
- if (typeof(millisec) === 'object') {
722
- millisec = false;
723
- }
724
- if (typeof(microsec) === 'object') {
725
- microsec = false;
726
- }
727
- if (typeof(timezone) === 'object') {
728
- timezone = false;
729
- }
730
-
731
- if (hour !== false) {
732
- hour = parseInt(hour, 10);
733
- }
734
- if (minute !== false) {
735
- minute = parseInt(minute, 10);
736
- }
737
- if (second !== false) {
738
- second = parseInt(second, 10);
739
- }
740
- if (millisec !== false) {
741
- millisec = parseInt(millisec, 10);
742
- }
743
- if (microsec !== false) {
744
- microsec = parseInt(microsec, 10);
745
- }
746
-
747
- var ampm = o[hour < 12 ? 'amNames' : 'pmNames'][0];
748
-
749
- // If the update was done in the input field, the input field should not be updated.
750
- // If the update was done using the sliders, update the input field.
751
- var hasChanged = (hour !== this.hour || minute !== this.minute || second !== this.second || millisec !== this.millisec || microsec !== this.microsec ||
752
- (this.ampm.length > 0 && (hour < 12) !== ($.inArray(this.ampm.toUpperCase(), this.amNames) !== -1)) || (this.timezone !== null && timezone !== this.timezone));
753
-
754
- if (hasChanged) {
755
-
756
- if (hour !== false) {
757
- this.hour = hour;
758
- }
759
- if (minute !== false) {
760
- this.minute = minute;
761
- }
762
- if (second !== false) {
763
- this.second = second;
764
- }
765
- if (millisec !== false) {
766
- this.millisec = millisec;
767
- }
768
- if (microsec !== false) {
769
- this.microsec = microsec;
770
- }
771
- if (timezone !== false) {
772
- this.timezone = timezone;
773
- }
774
-
775
- if (!this.inst) {
776
- this.inst = $.datepicker._getInst(this.$input[0]);
777
- }
778
-
779
- this._limitMinMaxDateTime(this.inst, true);
780
- }
781
- if (this.support.ampm) {
782
- this.ampm = ampm;
783
- }
784
-
785
- // Updates the time within the timepicker
786
- this.formattedTime = $.datepicker.formatTime(o.timeFormat, this, o);
787
- if (this.$timeObj) {
788
- if (pickerTimeFormat === o.timeFormat) {
789
- this.$timeObj.text(this.formattedTime + pickerTimeSuffix);
790
- }
791
- else {
792
- this.$timeObj.text($.datepicker.formatTime(pickerTimeFormat, this, o) + pickerTimeSuffix);
793
- }
794
- }
795
-
796
- this.timeDefined = true;
797
- if (hasChanged) {
798
- this._updateDateTime();
799
- }
800
- },
801
-
802
- /*
803
- * call custom onSelect.
804
- * bind to sliders slidestop, and grid click.
805
- */
806
- _onSelectHandler: function () {
807
- var onSelect = this._defaults.onSelect || this.inst.settings.onSelect;
808
- var inputEl = this.$input ? this.$input[0] : null;
809
- if (onSelect && inputEl) {
810
- onSelect.apply(inputEl, [this.formattedDateTime, this]);
811
- }
812
- },
813
-
814
- /*
815
- * update our input with the new date time..
816
- */
817
- _updateDateTime: function (dp_inst) {
818
- dp_inst = this.inst || dp_inst;
819
- var dtTmp = (dp_inst.currentYear > 0?
820
- new Date(dp_inst.currentYear, dp_inst.currentMonth, dp_inst.currentDay) :
821
- new Date(dp_inst.selectedYear, dp_inst.selectedMonth, dp_inst.selectedDay)),
822
- dt = $.datepicker._daylightSavingAdjust(dtTmp),
823
- //dt = $.datepicker._daylightSavingAdjust(new Date(dp_inst.selectedYear, dp_inst.selectedMonth, dp_inst.selectedDay)),
824
- //dt = $.datepicker._daylightSavingAdjust(new Date(dp_inst.currentYear, dp_inst.currentMonth, dp_inst.currentDay)),
825
- dateFmt = $.datepicker._get(dp_inst, 'dateFormat'),
826
- formatCfg = $.datepicker._getFormatConfig(dp_inst),
827
- timeAvailable = dt !== null && this.timeDefined;
828
- this.formattedDate = $.datepicker.formatDate(dateFmt, (dt === null ? new Date() : dt), formatCfg);
829
- var formattedDateTime = this.formattedDate;
830
-
831
- // if a slider was changed but datepicker doesn't have a value yet, set it
832
- if (dp_inst.lastVa === "") {
833
- dp_inst.currentYear = dp_inst.selectedYear;
834
- dp_inst.currentMonth = dp_inst.selectedMonth;
835
- dp_inst.currentDay = dp_inst.selectedDay;
836
- }
837
-
838
- /*
839
- * remove following lines to force every changes in date picker to change the input value
840
- * Bug descriptions: when an input field has a default value, and click on the field to pop up the date picker.
841
- * If the user manually empty the value in the input field, the date picker will never change selected value.
842
- */
843
- //if (dp_inst.lastVal !== undefined && (dp_inst.lastVal.length > 0 && this.$input.val().length === 0)) {
844
- // return;
845
- //}
846
-
847
- if (this._defaults.timeOnly === true) {
848
- formattedDateTime = this.formattedTime;
849
- } else if (this._defaults.timeOnly !== true && (this._defaults.alwaysSetTime || timeAvailable)) {
850
- formattedDateTime += this._defaults.separator + this.formattedTime + this._defaults.timeSuffix;
851
- }
852
-
853
- this.formattedDateTime = formattedDateTime;
854
-
855
- if (!this._defaults.showTimepicker) {
856
- this.$input.val(this.formattedDate);
857
- } else if (this.$altInput && this._defaults.timeOnly === false && this._defaults.altFieldTimeOnly === true) {
858
- this.$altInput.val(this.formattedTime);
859
- this.$input.val(this.formattedDate);
860
- } else if (this.$altInput) {
861
- this.$input.val(formattedDateTime);
862
- var altFormattedDateTime = '',
863
- altSeparator = this._defaults.altSeparator ? this._defaults.altSeparator : this._defaults.separator,
864
- altTimeSuffix = this._defaults.altTimeSuffix ? this._defaults.altTimeSuffix : this._defaults.timeSuffix;
865
-
866
- if (!this._defaults.timeOnly) {
867
- if (this._defaults.altFormat) {
868
- altFormattedDateTime = $.datepicker.formatDate(this._defaults.altFormat, (dt === null ? new Date() : dt), formatCfg);
869
- }
870
- else {
871
- altFormattedDateTime = this.formattedDate;
872
- }
873
-
874
- if (altFormattedDateTime) {
875
- altFormattedDateTime += altSeparator;
876
- }
877
- }
878
-
879
- if (this._defaults.altTimeFormat) {
880
- altFormattedDateTime += $.datepicker.formatTime(this._defaults.altTimeFormat, this, this._defaults) + altTimeSuffix;
881
- }
882
- else {
883
- altFormattedDateTime += this.formattedTime + altTimeSuffix;
884
- }
885
- this.$altInput.val(altFormattedDateTime);
886
- } else {
887
- this.$input.val(formattedDateTime);
888
- }
889
-
890
- this.$input.trigger("change");
891
- },
892
-
893
- _onFocus: function () {
894
- if (!this.$input.val() && this._defaults.defaultValue) {
895
- this.$input.val(this._defaults.defaultValue);
896
- var inst = $.datepicker._getInst(this.$input.get(0)),
897
- tp_inst = $.datepicker._get(inst, 'timepicker');
898
- if (tp_inst) {
899
- if (tp_inst._defaults.timeOnly && (inst.input.val() !== inst.lastVal)) {
900
- try {
901
- $.datepicker._updateDatepicker(inst);
902
- } catch (err) {
903
- $.timepicker.log(err);
904
- }
905
- }
906
- }
907
- }
908
- },
909
-
910
- /*
911
- * Small abstraction to control types
912
- * We can add more, just be sure to follow the pattern: create, options, value
913
- */
914
- _controls: {
915
- // slider methods
916
- slider: {
917
- create: function (tp_inst, obj, unit, val, min, max, step) {
918
- var rtl = tp_inst._defaults.isRTL; // if rtl go -60->0 instead of 0->60
919
- return obj.prop('slide', null).slider({
920
- orientation: "horizontal",
921
- value: rtl ? val * -1 : val,
922
- min: rtl ? max * -1 : min,
923
- max: rtl ? min * -1 : max,
924
- step: step,
925
- slide: function (event, ui) {
926
- tp_inst.control.value(tp_inst, $(this), unit, rtl ? ui.value * -1 : ui.value);
927
- tp_inst._onTimeChange();
928
- },
929
- stop: function (event, ui) {
930
- tp_inst._onSelectHandler();
931
- }
932
- });
933
- },
934
- options: function (tp_inst, obj, unit, opts, val) {
935
- if (tp_inst._defaults.isRTL) {
936
- if (typeof(opts) === 'string') {
937
- if (opts === 'min' || opts === 'max') {
938
- if (val !== undefined) {
939
- return obj.slider(opts, val * -1);
940
- }
941
- return Math.abs(obj.slider(opts));
942
- }
943
- return obj.slider(opts);
944
- }
945
- var min = opts.min,
946
- max = opts.max;
947
- opts.min = opts.max = null;
948
- if (min !== undefined) {
949
- opts.max = min * -1;
950
- }
951
- if (max !== undefined) {
952
- opts.min = max * -1;
953
- }
954
- return obj.slider(opts);
955
- }
956
- if (typeof(opts) === 'string' && val !== undefined) {
957
- return obj.slider(opts, val);
958
- }
959
- return obj.slider(opts);
960
- },
961
- value: function (tp_inst, obj, unit, val) {
962
- if (tp_inst._defaults.isRTL) {
963
- if (val !== undefined) {
964
- return obj.slider('value', val * -1);
965
- }
966
- return Math.abs(obj.slider('value'));
967
- }
968
- if (val !== undefined) {
969
- return obj.slider('value', val);
970
- }
971
- return obj.slider('value');
972
- }
973
- },
974
- // select methods
975
- select: {
976
- create: function (tp_inst, obj, unit, val, min, max, step) {
977
- var sel = '<select class="ui-timepicker-select" data-unit="' + unit + '" data-min="' + min + '" data-max="' + max + '" data-step="' + step + '">',
978
- format = tp_inst._defaults.pickerTimeFormat || tp_inst._defaults.timeFormat;
979
-
980
- for (var i = min; i <= max; i += step) {
981
- sel += '<option value="' + i + '"' + (i === val ? ' selected' : '') + '>';
982
- if (unit === 'hour') {
983
- sel += $.datepicker.formatTime($.trim(format.replace(/[^ht ]/ig, '')), {hour: i}, tp_inst._defaults);
984
- }
985
- else if (unit === 'millisec' || unit === 'microsec' || i >= 10) { sel += i; }
986
- else {sel += '0' + i.toString(); }
987
- sel += '</option>';
988
- }
989
- sel += '</select>';
990
-
991
- obj.children('select').remove();
992
-
993
- $(sel).appendTo(obj).change(function (e) {
994
- tp_inst._onTimeChange();
995
- tp_inst._onSelectHandler();
996
- });
997
-
998
- return obj;
999
- },
1000
- options: function (tp_inst, obj, unit, opts, val) {
1001
- var o = {},
1002
- $t = obj.children('select');
1003
- if (typeof(opts) === 'string') {
1004
- if (val === undefined) {
1005
- return $t.data(opts);
1006
- }
1007
- o[opts] = val;
1008
- }
1009
- else { o = opts; }
1010
- return tp_inst.control.create(tp_inst, obj, $t.data('unit'), $t.val(), o.min || $t.data('min'), o.max || $t.data('max'), o.step || $t.data('step'));
1011
- },
1012
- value: function (tp_inst, obj, unit, val) {
1013
- var $t = obj.children('select');
1014
- if (val !== undefined) {
1015
- return $t.val(val);
1016
- }
1017
- return $t.val();
1018
- }
1019
- }
1020
- } // end _controls
1021
-
1022
- });
1023
-
1024
- $.fn.extend({
1025
- /*
1026
- * shorthand just to use timepicker.
1027
- */
1028
- timepicker: function (o) {
1029
- o = o || {};
1030
- var tmp_args = Array.prototype.slice.call(arguments);
1031
-
1032
- if (typeof o === 'object') {
1033
- tmp_args[0] = $.extend(o, {
1034
- timeOnly: true
1035
- });
1036
- }
1037
-
1038
- return $(this).each(function () {
1039
- $.fn.datetimepicker.apply($(this), tmp_args);
1040
- });
1041
- },
1042
-
1043
- /*
1044
- * extend timepicker to datepicker
1045
- */
1046
- datetimepicker: function (o) {
1047
- o = o || {};
1048
- var tmp_args = arguments;
1049
-
1050
- if (typeof(o) === 'string') {
1051
- if (o === 'getDate') {
1052
- return $.fn.datepicker.apply($(this[0]), tmp_args);
1053
- } else {
1054
- return this.each(function () {
1055
- var $t = $(this);
1056
- $t.datepicker.apply($t, tmp_args);
1057
- });
1058
- }
1059
- } else {
1060
- return this.each(function () {
1061
- var $t = $(this);
1062
- $t.datepicker($.timepicker._newInst($t, o)._defaults);
1063
- });
1064
- }
1065
- }
1066
- });
1067
-
1068
- /*
1069
- * Public Utility to parse date and time
1070
- */
1071
- $.datepicker.parseDateTime = function (dateFormat, timeFormat, dateTimeString, dateSettings, timeSettings) {
1072
- var parseRes = parseDateTimeInternal(dateFormat, timeFormat, dateTimeString, dateSettings, timeSettings);
1073
- if (parseRes.timeObj) {
1074
- var t = parseRes.timeObj;
1075
- parseRes.date.setHours(t.hour, t.minute, t.second, t.millisec);
1076
- parseRes.date.setMicroseconds(t.microsec);
1077
- }
1078
-
1079
- return parseRes.date;
1080
- };
1081
-
1082
- /*
1083
- * Public utility to parse time
1084
- */
1085
- $.datepicker.parseTime = function (timeFormat, timeString, options) {
1086
- var o = extendRemove(extendRemove({}, $.timepicker._defaults), options || {}),
1087
- iso8601 = (timeFormat.replace(/\'.*?\'/g, '').indexOf('Z') !== -1);
1088
-
1089
- // Strict parse requires the timeString to match the timeFormat exactly
1090
- var strictParse = function (f, s, o) {
1091
-
1092
- // pattern for standard and localized AM/PM markers
1093
- var getPatternAmpm = function (amNames, pmNames) {
1094
- var markers = [];
1095
- if (amNames) {
1096
- $.merge(markers, amNames);
1097
- }
1098
- if (pmNames) {
1099
- $.merge(markers, pmNames);
1100
- }
1101
- markers = $.map(markers, function (val) {
1102
- return val.replace(/[.*+?|()\[\]{}\\]/g, '\\$&');
1103
- });
1104
- return '(' + markers.join('|') + ')?';
1105
- };
1106
-
1107
- // figure out position of time elements.. cause js cant do named captures
1108
- var getFormatPositions = function (timeFormat) {
1109
- var finds = timeFormat.toLowerCase().match(/(h{1,2}|m{1,2}|s{1,2}|l{1}|c{1}|t{1,2}|z|'.*?')/g),
1110
- orders = {
1111
- h: -1,
1112
- m: -1,
1113
- s: -1,
1114
- l: -1,
1115
- c: -1,
1116
- t: -1,
1117
- z: -1
1118
- };
1119
-
1120
- if (finds) {
1121
- for (var i = 0; i < finds.length; i++) {
1122
- if (orders[finds[i].toString().charAt(0)] === -1) {
1123
- orders[finds[i].toString().charAt(0)] = i + 1;
1124
- }
1125
- }
1126
- }
1127
- return orders;
1128
- };
1129
-
1130
- var regstr = '^' + f.toString()
1131
- .replace(/([hH]{1,2}|mm?|ss?|[tT]{1,2}|[zZ]|[lc]|'.*?')/g, function (match) {
1132
- var ml = match.length;
1133
- switch (match.charAt(0).toLowerCase()) {
1134
- case 'h':
1135
- return ml === 1 ? '(\\d?\\d)' : '(\\d{' + ml + '})';
1136
- case 'm':
1137
- return ml === 1 ? '(\\d?\\d)' : '(\\d{' + ml + '})';
1138
- case 's':
1139
- return ml === 1 ? '(\\d?\\d)' : '(\\d{' + ml + '})';
1140
- case 'l':
1141
- return '(\\d?\\d?\\d)';
1142
- case 'c':
1143
- return '(\\d?\\d?\\d)';
1144
- case 'z':
1145
- return '(z|[-+]\\d\\d:?\\d\\d|\\S+)?';
1146
- case 't':
1147
- return getPatternAmpm(o.amNames, o.pmNames);
1148
- default: // literal escaped in quotes
1149
- return '(' + match.replace(/\'/g, "").replace(/(\.|\$|\^|\\|\/|\(|\)|\[|\]|\?|\+|\*)/g, function (m) { return "\\" + m; }) + ')?';
1150
- }
1151
- })
1152
- .replace(/\s/g, '\\s?') +
1153
- o.timeSuffix + '$',
1154
- order = getFormatPositions(f),
1155
- ampm = '',
1156
- treg;
1157
-
1158
- treg = s.match(new RegExp(regstr, 'i'));
1159
-
1160
- var resTime = {
1161
- hour: 0,
1162
- minute: 0,
1163
- second: 0,
1164
- millisec: 0,
1165
- microsec: 0
1166
- };
1167
-
1168
- if (treg) {
1169
- if (order.t !== -1) {
1170
- if (treg[order.t] === undefined || treg[order.t].length === 0) {
1171
- ampm = '';
1172
- resTime.ampm = '';
1173
- } else {
1174
- ampm = $.inArray(treg[order.t].toUpperCase(), o.amNames) !== -1 ? 'AM' : 'PM';
1175
- resTime.ampm = o[ampm === 'AM' ? 'amNames' : 'pmNames'][0];
1176
- }
1177
- }
1178
-
1179
- if (order.h !== -1) {
1180
- if (ampm === 'AM' && treg[order.h] === '12') {
1181
- resTime.hour = 0; // 12am = 0 hour
1182
- } else {
1183
- if (ampm === 'PM' && treg[order.h] !== '12') {
1184
- resTime.hour = parseInt(treg[order.h], 10) + 12; // 12pm = 12 hour, any other pm = hour + 12
1185
- } else {
1186
- resTime.hour = Number(treg[order.h]);
1187
- }
1188
- }
1189
- }
1190
-
1191
- if (order.m !== -1) {
1192
- resTime.minute = Number(treg[order.m]);
1193
- }
1194
- if (order.s !== -1) {
1195
- resTime.second = Number(treg[order.s]);
1196
- }
1197
- if (order.l !== -1) {
1198
- resTime.millisec = Number(treg[order.l]);
1199
- }
1200
- if (order.c !== -1) {
1201
- resTime.microsec = Number(treg[order.c]);
1202
- }
1203
- if (order.z !== -1 && treg[order.z] !== undefined) {
1204
- resTime.timezone = $.timepicker.timezoneOffsetNumber(treg[order.z]);
1205
- }
1206
-
1207
-
1208
- return resTime;
1209
- }
1210
- return false;
1211
- };// end strictParse
1212
-
1213
- // First try JS Date, if that fails, use strictParse
1214
- var looseParse = function (f, s, o) {
1215
- try {
1216
- var d = new Date('2012-01-01 ' + s);
1217
- if (isNaN(d.getTime())) {
1218
- d = new Date('2012-01-01T' + s);
1219
- if (isNaN(d.getTime())) {
1220
- d = new Date('01/01/2012 ' + s);
1221
- if (isNaN(d.getTime())) {
1222
- throw "Unable to parse time with native Date: " + s;
1223
- }
1224
- }
1225
- }
1226
-
1227
- return {
1228
- hour: d.getHours(),
1229
- minute: d.getMinutes(),
1230
- second: d.getSeconds(),
1231
- millisec: d.getMilliseconds(),
1232
- microsec: d.getMicroseconds(),
1233
- timezone: d.getTimezoneOffset() * -1
1234
- };
1235
- }
1236
- catch (err) {
1237
- try {
1238
- return strictParse(f, s, o);
1239
- }
1240
- catch (err2) {
1241
- $.timepicker.log("Unable to parse \ntimeString: " + s + "\ntimeFormat: " + f);
1242
- }
1243
- }
1244
- return false;
1245
- }; // end looseParse
1246
-
1247
- if (typeof o.parse === "function") {
1248
- return o.parse(timeFormat, timeString, o);
1249
- }
1250
- if (o.parse === 'loose') {
1251
- return looseParse(timeFormat, timeString, o);
1252
- }
1253
- return strictParse(timeFormat, timeString, o);
1254
- };
1255
-
1256
- /**
1257
- * Public utility to format the time
1258
- * @param {string} format format of the time
1259
- * @param {Object} time Object not a Date for timezones
1260
- * @param {Object} [options] essentially the regional[].. amNames, pmNames, ampm
1261
- * @returns {string} the formatted time
1262
- */
1263
- $.datepicker.formatTime = function (format, time, options) {
1264
- options = options || {};
1265
- options = $.extend({}, $.timepicker._defaults, options);
1266
- time = $.extend({
1267
- hour: 0,
1268
- minute: 0,
1269
- second: 0,
1270
- millisec: 0,
1271
- microsec: 0,
1272
- timezone: null
1273
- }, time);
1274
-
1275
- var tmptime = format,
1276
- ampmName = options.amNames[0],
1277
- hour = parseInt(time.hour, 10);
1278
-
1279
- if (hour > 11) {
1280
- ampmName = options.pmNames[0];
1281
- }
1282
-
1283
- tmptime = tmptime.replace(/(?:HH?|hh?|mm?|ss?|[tT]{1,2}|[zZ]|[lc]|'.*?')/g, function (match) {
1284
- switch (match) {
1285
- case 'HH':
1286
- return ('0' + hour).slice(-2);
1287
- case 'H':
1288
- return hour;
1289
- case 'hh':
1290
- return ('0' + convert24to12(hour)).slice(-2);
1291
- case 'h':
1292
- return convert24to12(hour);
1293
- case 'mm':
1294
- return ('0' + time.minute).slice(-2);
1295
- case 'm':
1296
- return time.minute;
1297
- case 'ss':
1298
- return ('0' + time.second).slice(-2);
1299
- case 's':
1300
- return time.second;
1301
- case 'l':
1302
- return ('00' + time.millisec).slice(-3);
1303
- case 'c':
1304
- return ('00' + time.microsec).slice(-3);
1305
- case 'z':
1306
- return $.timepicker.timezoneOffsetString(time.timezone === null ? options.timezone : time.timezone, false);
1307
- case 'Z':
1308
- return $.timepicker.timezoneOffsetString(time.timezone === null ? options.timezone : time.timezone, true);
1309
- case 'T':
1310
- return ampmName.charAt(0).toUpperCase();
1311
- case 'TT':
1312
- return ampmName.toUpperCase();
1313
- case 't':
1314
- return ampmName.charAt(0).toLowerCase();
1315
- case 'tt':
1316
- return ampmName.toLowerCase();
1317
- default:
1318
- return match.replace(/'/g, "");
1319
- }
1320
- });
1321
-
1322
- return tmptime;
1323
- };
1324
-
1325
- /*
1326
- * the bad hack :/ override datepicker so it doesn't close on select
1327
- // inspired: http://stackoverflow.com/questions/1252512/jquery-datepicker-prevent-closing-picker-when-clicking-a-date/1762378#1762378
1328
- */
1329
- $.datepicker._base_selectDate = $.datepicker._selectDate;
1330
- $.datepicker._selectDate = function (id, dateStr) {
1331
- var inst = this._getInst($(id)[0]),
1332
- tp_inst = this._get(inst, 'timepicker');
1333
-
1334
- if (tp_inst) {
1335
- tp_inst._limitMinMaxDateTime(inst, true);
1336
- inst.inline = inst.stay_open = true;
1337
- //This way the onSelect handler called from calendarpicker get the full dateTime
1338
- this._base_selectDate(id, dateStr);
1339
- inst.inline = inst.stay_open = false;
1340
- this._notifyChange(inst);
1341
- this._updateDatepicker(inst);
1342
- } else {
1343
- this._base_selectDate(id, dateStr);
1344
- }
1345
- };
1346
-
1347
- /*
1348
- * second bad hack :/ override datepicker so it triggers an event when changing the input field
1349
- * and does not redraw the datepicker on every selectDate event
1350
- */
1351
- $.datepicker._base_updateDatepicker = $.datepicker._updateDatepicker;
1352
- $.datepicker._updateDatepicker = function (inst) {
1353
-
1354
- // don't popup the datepicker if there is another instance already opened
1355
- var input = inst.input[0];
1356
- if ($.datepicker._curInst && $.datepicker._curInst !== inst && $.datepicker._datepickerShowing && $.datepicker._lastInput !== input) {
1357
- return;
1358
- }
1359
-
1360
- if (typeof(inst.stay_open) !== 'boolean' || inst.stay_open === false) {
1361
-
1362
- this._base_updateDatepicker(inst);
1363
-
1364
- // Reload the time control when changing something in the input text field.
1365
- var tp_inst = this._get(inst, 'timepicker');
1366
- if (tp_inst) {
1367
- tp_inst._addTimePicker(inst);
1368
- }
1369
- }
1370
- };
1371
-
1372
- /*
1373
- * third bad hack :/ override datepicker so it allows spaces and colon in the input field
1374
- */
1375
- $.datepicker._base_doKeyPress = $.datepicker._doKeyPress;
1376
- $.datepicker._doKeyPress = function (event) {
1377
- var inst = $.datepicker._getInst(event.target),
1378
- tp_inst = $.datepicker._get(inst, 'timepicker');
1379
-
1380
- if (tp_inst) {
1381
- if ($.datepicker._get(inst, 'constrainInput')) {
1382
- var ampm = tp_inst.support.ampm,
1383
- tz = tp_inst._defaults.showTimezone !== null ? tp_inst._defaults.showTimezone : tp_inst.support.timezone,
1384
- dateChars = $.datepicker._possibleChars($.datepicker._get(inst, 'dateFormat')),
1385
- datetimeChars = tp_inst._defaults.timeFormat.toString()
1386
- .replace(/[hms]/g, '')
1387
- .replace(/TT/g, ampm ? 'APM' : '')
1388
- .replace(/Tt/g, ampm ? 'AaPpMm' : '')
1389
- .replace(/tT/g, ampm ? 'AaPpMm' : '')
1390
- .replace(/T/g, ampm ? 'AP' : '')
1391
- .replace(/tt/g, ampm ? 'apm' : '')
1392
- .replace(/t/g, ampm ? 'ap' : '') +
1393
- " " + tp_inst._defaults.separator +
1394
- tp_inst._defaults.timeSuffix +
1395
- (tz ? tp_inst._defaults.timezoneList.join('') : '') +
1396
- (tp_inst._defaults.amNames.join('')) + (tp_inst._defaults.pmNames.join('')) +
1397
- dateChars,
1398
- chr = String.fromCharCode(event.charCode === undefined ? event.keyCode : event.charCode);
1399
- return event.ctrlKey || (chr < ' ' || !dateChars || datetimeChars.indexOf(chr) > -1);
1400
- }
1401
- }
1402
-
1403
- return $.datepicker._base_doKeyPress(event);
1404
- };
1405
-
1406
- /*
1407
- * Fourth bad hack :/ override _updateAlternate function used in inline mode to init altField
1408
- * Update any alternate field to synchronise with the main field.
1409
- */
1410
- $.datepicker._base_updateAlternate = $.datepicker._updateAlternate;
1411
- $.datepicker._updateAlternate = function (inst) {
1412
- var tp_inst = this._get(inst, 'timepicker');
1413
- if (tp_inst) {
1414
- var altField = tp_inst._defaults.altField;
1415
- if (altField) { // update alternate field too
1416
- var altFormat = tp_inst._defaults.altFormat || tp_inst._defaults.dateFormat,
1417
- date = this._getDate(inst),
1418
- formatCfg = $.datepicker._getFormatConfig(inst),
1419
- altFormattedDateTime = '',
1420
- altSeparator = tp_inst._defaults.altSeparator ? tp_inst._defaults.altSeparator : tp_inst._defaults.separator,
1421
- altTimeSuffix = tp_inst._defaults.altTimeSuffix ? tp_inst._defaults.altTimeSuffix : tp_inst._defaults.timeSuffix,
1422
- altTimeFormat = tp_inst._defaults.altTimeFormat !== null ? tp_inst._defaults.altTimeFormat : tp_inst._defaults.timeFormat;
1423
-
1424
- altFormattedDateTime += $.datepicker.formatTime(altTimeFormat, tp_inst, tp_inst._defaults) + altTimeSuffix;
1425
- if (!tp_inst._defaults.timeOnly && !tp_inst._defaults.altFieldTimeOnly && date !== null) {
1426
- if (tp_inst._defaults.altFormat) {
1427
- altFormattedDateTime = $.datepicker.formatDate(tp_inst._defaults.altFormat, date, formatCfg) + altSeparator + altFormattedDateTime;
1428
- }
1429
- else {
1430
- altFormattedDateTime = tp_inst.formattedDate + altSeparator + altFormattedDateTime;
1431
- }
1432
- }
1433
- $(altField).val(altFormattedDateTime);
1434
- }
1435
- }
1436
- else {
1437
- $.datepicker._base_updateAlternate(inst);
1438
- }
1439
- };
1440
-
1441
- /*
1442
- * Override key up event to sync manual input changes.
1443
- */
1444
- $.datepicker._base_doKeyUp = $.datepicker._doKeyUp;
1445
- $.datepicker._doKeyUp = function (event) {
1446
- var inst = $.datepicker._getInst(event.target),
1447
- tp_inst = $.datepicker._get(inst, 'timepicker');
1448
-
1449
- if (tp_inst) {
1450
- if (tp_inst._defaults.timeOnly && (inst.input.val() !== inst.lastVal)) {
1451
- try {
1452
- $.datepicker._updateDatepicker(inst);
1453
- } catch (err) {
1454
- $.timepicker.log(err);
1455
- }
1456
- }
1457
- }
1458
-
1459
- return $.datepicker._base_doKeyUp(event);
1460
- };
1461
-
1462
- /*
1463
- * override "Today" button to also grab the time.
1464
- */
1465
- $.datepicker._base_gotoToday = $.datepicker._gotoToday;
1466
- $.datepicker._gotoToday = function (id) {
1467
- var inst = this._getInst($(id)[0]),
1468
- $dp = inst.dpDiv;
1469
- this._base_gotoToday(id);
1470
- var tp_inst = this._get(inst, 'timepicker');
1471
- selectLocalTimezone(tp_inst);
1472
- var now = new Date();
1473
- this._setTime(inst, now);
1474
- $('.ui-datepicker-today', $dp).click();
1475
- };
1476
-
1477
- /*
1478
- * Disable & enable the Time in the datetimepicker
1479
- */
1480
- $.datepicker._disableTimepickerDatepicker = function (target) {
1481
- var inst = this._getInst(target);
1482
- if (!inst) {
1483
- return;
1484
- }
1485
-
1486
- var tp_inst = this._get(inst, 'timepicker');
1487
- $(target).datepicker('getDate'); // Init selected[Year|Month|Day]
1488
- if (tp_inst) {
1489
- inst.settings.showTimepicker = false;
1490
- tp_inst._defaults.showTimepicker = false;
1491
- tp_inst._updateDateTime(inst);
1492
- }
1493
- };
1494
-
1495
- $.datepicker._enableTimepickerDatepicker = function (target) {
1496
- var inst = this._getInst(target);
1497
- if (!inst) {
1498
- return;
1499
- }
1500
-
1501
- var tp_inst = this._get(inst, 'timepicker');
1502
- $(target).datepicker('getDate'); // Init selected[Year|Month|Day]
1503
- if (tp_inst) {
1504
- inst.settings.showTimepicker = true;
1505
- tp_inst._defaults.showTimepicker = true;
1506
- tp_inst._addTimePicker(inst); // Could be disabled on page load
1507
- tp_inst._updateDateTime(inst);
1508
- }
1509
- };
1510
-
1511
- /*
1512
- * Create our own set time function
1513
- */
1514
- $.datepicker._setTime = function (inst, date) {
1515
- var tp_inst = this._get(inst, 'timepicker');
1516
- if (tp_inst) {
1517
- var defaults = tp_inst._defaults;
1518
-
1519
- // calling _setTime with no date sets time to defaults
1520
- tp_inst.hour = date ? date.getHours() : defaults.hour;
1521
- tp_inst.minute = date ? date.getMinutes() : defaults.minute;
1522
- tp_inst.second = date ? date.getSeconds() : defaults.second;
1523
- tp_inst.millisec = date ? date.getMilliseconds() : defaults.millisec;
1524
- tp_inst.microsec = date ? date.getMicroseconds() : defaults.microsec;
1525
-
1526
- //check if within min/max times..
1527
- tp_inst._limitMinMaxDateTime(inst, true);
1528
-
1529
- tp_inst._onTimeChange();
1530
- tp_inst._updateDateTime(inst);
1531
- }
1532
- };
1533
-
1534
- /*
1535
- * Create new public method to set only time, callable as $().datepicker('setTime', date)
1536
- */
1537
- $.datepicker._setTimeDatepicker = function (target, date, withDate) {
1538
- var inst = this._getInst(target);
1539
- if (!inst) {
1540
- return;
1541
- }
1542
-
1543
- var tp_inst = this._get(inst, 'timepicker');
1544
-
1545
- if (tp_inst) {
1546
- this._setDateFromField(inst);
1547
- var tp_date;
1548
- if (date) {
1549
- if (typeof date === "string") {
1550
- tp_inst._parseTime(date, withDate);
1551
- tp_date = new Date();
1552
- tp_date.setHours(tp_inst.hour, tp_inst.minute, tp_inst.second, tp_inst.millisec);
1553
- tp_date.setMicroseconds(tp_inst.microsec);
1554
- } else {
1555
- tp_date = new Date(date.getTime());
1556
- tp_date.setMicroseconds(date.getMicroseconds());
1557
- }
1558
- if (tp_date.toString() === 'Invalid Date') {
1559
- tp_date = undefined;
1560
- }
1561
- this._setTime(inst, tp_date);
1562
- }
1563
- }
1564
-
1565
- };
1566
-
1567
- /*
1568
- * override setDate() to allow setting time too within Date object
1569
- */
1570
- $.datepicker._base_setDateDatepicker = $.datepicker._setDateDatepicker;
1571
- $.datepicker._setDateDatepicker = function (target, date) {
1572
- var inst = this._getInst(target);
1573
- if (!inst) {
1574
- return;
1575
- }
1576
-
1577
- if (typeof(date) === 'string') {
1578
- date = new Date(date);
1579
- if (!date.getTime()) {
1580
- $.timepicker.log("Error creating Date object from string.");
1581
- }
1582
- }
1583
-
1584
- var tp_inst = this._get(inst, 'timepicker');
1585
- var tp_date;
1586
- if (date instanceof Date) {
1587
- tp_date = new Date(date.getTime());
1588
- tp_date.setMicroseconds(date.getMicroseconds());
1589
- } else {
1590
- tp_date = date;
1591
- }
1592
-
1593
- // This is important if you are using the timezone option, javascript's Date
1594
- // object will only return the timezone offset for the current locale, so we
1595
- // adjust it accordingly. If not using timezone option this won't matter..
1596
- // If a timezone is different in tp, keep the timezone as is
1597
- if (tp_inst) {
1598
- // look out for DST if tz wasn't specified
1599
- if (!tp_inst.support.timezone && tp_inst._defaults.timezone === null) {
1600
- tp_inst.timezone = tp_date.getTimezoneOffset() * -1;
1601
- }
1602
- date = $.timepicker.timezoneAdjust(date, tp_inst.timezone);
1603
- tp_date = $.timepicker.timezoneAdjust(tp_date, tp_inst.timezone);
1604
- }
1605
-
1606
- this._updateDatepicker(inst);
1607
- this._base_setDateDatepicker.apply(this, arguments);
1608
- this._setTimeDatepicker(target, tp_date, true);
1609
- };
1610
-
1611
- /*
1612
- * override getDate() to allow getting time too within Date object
1613
- */
1614
- $.datepicker._base_getDateDatepicker = $.datepicker._getDateDatepicker;
1615
- $.datepicker._getDateDatepicker = function (target, noDefault) {
1616
- var inst = this._getInst(target);
1617
- if (!inst) {
1618
- return;
1619
- }
1620
-
1621
- var tp_inst = this._get(inst, 'timepicker');
1622
-
1623
- if (tp_inst) {
1624
- // if it hasn't yet been defined, grab from field
1625
- if (inst.lastVal === undefined) {
1626
- this._setDateFromField(inst, noDefault);
1627
- }
1628
-
1629
- var date = this._getDate(inst);
1630
- if (date && tp_inst._parseTime($(target).val(), tp_inst.timeOnly)) {
1631
- date.setHours(tp_inst.hour, tp_inst.minute, tp_inst.second, tp_inst.millisec);
1632
- date.setMicroseconds(tp_inst.microsec);
1633
-
1634
- // This is important if you are using the timezone option, javascript's Date
1635
- // object will only return the timezone offset for the current locale, so we
1636
- // adjust it accordingly. If not using timezone option this won't matter..
1637
- if (tp_inst.timezone != null) {
1638
- // look out for DST if tz wasn't specified
1639
- if (!tp_inst.support.timezone && tp_inst._defaults.timezone === null) {
1640
- tp_inst.timezone = date.getTimezoneOffset() * -1;
1641
- }
1642
- date = $.timepicker.timezoneAdjust(date, tp_inst.timezone);
1643
- }
1644
- }
1645
- return date;
1646
- }
1647
- return this._base_getDateDatepicker(target, noDefault);
1648
- };
1649
-
1650
- /*
1651
- * override parseDate() because UI 1.8.14 throws an error about "Extra characters"
1652
- * An option in datapicker to ignore extra format characters would be nicer.
1653
- */
1654
- $.datepicker._base_parseDate = $.datepicker.parseDate;
1655
- $.datepicker.parseDate = function (format, value, settings) {
1656
- var date;
1657
- try {
1658
- date = this._base_parseDate(format, value, settings);
1659
- } catch (err) {
1660
- // Hack! The error message ends with a colon, a space, and
1661
- // the "extra" characters. We rely on that instead of
1662
- // attempting to perfectly reproduce the parsing algorithm.
1663
- if (err.indexOf(":") >= 0) {
1664
- date = this._base_parseDate(format, value.substring(0, value.length - (err.length - err.indexOf(':') - 2)), settings);
1665
- $.timepicker.log("Error parsing the date string: " + err + "\ndate string = " + value + "\ndate format = " + format);
1666
- } else {
1667
- throw err;
1668
- }
1669
- }
1670
- return date;
1671
- };
1672
-
1673
- /*
1674
- * override formatDate to set date with time to the input
1675
- */
1676
- $.datepicker._base_formatDate = $.datepicker._formatDate;
1677
- $.datepicker._formatDate = function (inst, day, month, year) {
1678
- var tp_inst = this._get(inst, 'timepicker');
1679
- if (tp_inst) {
1680
- tp_inst._updateDateTime(inst);
1681
- return tp_inst.$input.val();
1682
- }
1683
- return this._base_formatDate(inst);
1684
- };
1685
-
1686
- /*
1687
- * override options setter to add time to maxDate(Time) and minDate(Time). MaxDate
1688
- */
1689
- $.datepicker._base_optionDatepicker = $.datepicker._optionDatepicker;
1690
- $.datepicker._optionDatepicker = function (target, name, value) {
1691
- var inst = this._getInst(target),
1692
- name_clone;
1693
- if (!inst) {
1694
- return null;
1695
- }
1696
-
1697
- var tp_inst = this._get(inst, 'timepicker');
1698
- if (tp_inst) {
1699
- var min = null,
1700
- max = null,
1701
- onselect = null,
1702
- overrides = tp_inst._defaults.evnts,
1703
- fns = {},
1704
- prop;
1705
- if (typeof name === 'string') { // if min/max was set with the string
1706
- if (name === 'minDate' || name === 'minDateTime') {
1707
- min = value;
1708
- } else if (name === 'maxDate' || name === 'maxDateTime') {
1709
- max = value;
1710
- } else if (name === 'onSelect') {
1711
- onselect = value;
1712
- } else if (overrides.hasOwnProperty(name)) {
1713
- if (typeof (value) === 'undefined') {
1714
- return overrides[name];
1715
- }
1716
- fns[name] = value;
1717
- name_clone = {}; //empty results in exiting function after overrides updated
1718
- }
1719
- } else if (typeof name === 'object') { //if min/max was set with the JSON
1720
- if (name.minDate) {
1721
- min = name.minDate;
1722
- } else if (name.minDateTime) {
1723
- min = name.minDateTime;
1724
- } else if (name.maxDate) {
1725
- max = name.maxDate;
1726
- } else if (name.maxDateTime) {
1727
- max = name.maxDateTime;
1728
- }
1729
- for (prop in overrides) {
1730
- if (overrides.hasOwnProperty(prop) && name[prop]) {
1731
- fns[prop] = name[prop];
1732
- }
1733
- }
1734
- }
1735
- for (prop in fns) {
1736
- if (fns.hasOwnProperty(prop)) {
1737
- overrides[prop] = fns[prop];
1738
- if (!name_clone) { name_clone = $.extend({}, name); }
1739
- delete name_clone[prop];
1740
- }
1741
- }
1742
- if (name_clone && isEmptyObject(name_clone)) { return; }
1743
- if (min) { //if min was set
1744
- if (min === 0) {
1745
- min = new Date();
1746
- } else {
1747
- min = new Date(min);
1748
- }
1749
- tp_inst._defaults.minDate = min;
1750
- tp_inst._defaults.minDateTime = min;
1751
- } else if (max) { //if max was set
1752
- if (max === 0) {
1753
- max = new Date();
1754
- } else {
1755
- max = new Date(max);
1756
- }
1757
- tp_inst._defaults.maxDate = max;
1758
- tp_inst._defaults.maxDateTime = max;
1759
- } else if (onselect) {
1760
- tp_inst._defaults.onSelect = onselect;
1761
- }
1762
- }
1763
- if (value === undefined) {
1764
- return this._base_optionDatepicker.call($.datepicker, target, name);
1765
- }
1766
- return this._base_optionDatepicker.call($.datepicker, target, name_clone || name, value);
1767
- };
1768
-
1769
- /*
1770
- * jQuery isEmptyObject does not check hasOwnProperty - if someone has added to the object prototype,
1771
- * it will return false for all objects
1772
- */
1773
- var isEmptyObject = function (obj) {
1774
- var prop;
1775
- for (prop in obj) {
1776
- if (obj.hasOwnProperty(prop)) {
1777
- return false;
1778
- }
1779
- }
1780
- return true;
1781
- };
1782
-
1783
- /*
1784
- * jQuery extend now ignores nulls!
1785
- */
1786
- var extendRemove = function (target, props) {
1787
- $.extend(target, props);
1788
- for (var name in props) {
1789
- if (props[name] === null || props[name] === undefined) {
1790
- target[name] = props[name];
1791
- }
1792
- }
1793
- return target;
1794
- };
1795
-
1796
- /*
1797
- * Determine by the time format which units are supported
1798
- * Returns an object of booleans for each unit
1799
- */
1800
- var detectSupport = function (timeFormat) {
1801
- var tf = timeFormat.replace(/'.*?'/g, '').toLowerCase(), // removes literals
1802
- isIn = function (f, t) { // does the format contain the token?
1803
- return f.indexOf(t) !== -1 ? true : false;
1804
- };
1805
- return {
1806
- hour: isIn(tf, 'h'),
1807
- minute: isIn(tf, 'm'),
1808
- second: isIn(tf, 's'),
1809
- millisec: isIn(tf, 'l'),
1810
- microsec: isIn(tf, 'c'),
1811
- timezone: isIn(tf, 'z'),
1812
- ampm: isIn(tf, 't') && isIn(timeFormat, 'h'),
1813
- iso8601: isIn(timeFormat, 'Z')
1814
- };
1815
- };
1816
-
1817
- /*
1818
- * Converts 24 hour format into 12 hour
1819
- * Returns 12 hour without leading 0
1820
- */
1821
- var convert24to12 = function (hour) {
1822
- hour %= 12;
1823
-
1824
- if (hour === 0) {
1825
- hour = 12;
1826
- }
1827
-
1828
- return String(hour);
1829
- };
1830
-
1831
- var computeEffectiveSetting = function (settings, property) {
1832
- return settings && settings[property] ? settings[property] : $.timepicker._defaults[property];
1833
- };
1834
-
1835
- /*
1836
- * Splits datetime string into date and time substrings.
1837
- * Throws exception when date can't be parsed
1838
- * Returns {dateString: dateString, timeString: timeString}
1839
- */
1840
- var splitDateTime = function (dateTimeString, timeSettings) {
1841
- // The idea is to get the number separator occurrences in datetime and the time format requested (since time has
1842
- // fewer unknowns, mostly numbers and am/pm). We will use the time pattern to split.
1843
- var separator = computeEffectiveSetting(timeSettings, 'separator'),
1844
- format = computeEffectiveSetting(timeSettings, 'timeFormat'),
1845
- timeParts = format.split(separator), // how many occurrences of separator may be in our format?
1846
- timePartsLen = timeParts.length,
1847
- allParts = dateTimeString.split(separator),
1848
- allPartsLen = allParts.length;
1849
-
1850
- if (allPartsLen > 1) {
1851
- return {
1852
- dateString: allParts.splice(0, allPartsLen - timePartsLen).join(separator),
1853
- timeString: allParts.splice(0, timePartsLen).join(separator)
1854
- };
1855
- }
1856
-
1857
- return {
1858
- dateString: dateTimeString,
1859
- timeString: ''
1860
- };
1861
- };
1862
-
1863
- /*
1864
- * Internal function to parse datetime interval
1865
- * Returns: {date: Date, timeObj: Object}, where
1866
- * date - parsed date without time (type Date)
1867
- * timeObj = {hour: , minute: , second: , millisec: , microsec: } - parsed time. Optional
1868
- */
1869
- var parseDateTimeInternal = function (dateFormat, timeFormat, dateTimeString, dateSettings, timeSettings) {
1870
- var date,
1871
- parts,
1872
- parsedTime;
1873
-
1874
- parts = splitDateTime(dateTimeString, timeSettings);
1875
- date = $.datepicker._base_parseDate(dateFormat, parts.dateString, dateSettings);
1876
-
1877
- if (parts.timeString === '') {
1878
- return {
1879
- date: date
1880
- };
1881
- }
1882
-
1883
- parsedTime = $.datepicker.parseTime(timeFormat, parts.timeString, timeSettings);
1884
-
1885
- if (!parsedTime) {
1886
- throw 'Wrong time format';
1887
- }
1888
-
1889
- return {
1890
- date: date,
1891
- timeObj: parsedTime
1892
- };
1893
- };
1894
-
1895
- /*
1896
- * Internal function to set timezone_select to the local timezone
1897
- */
1898
- var selectLocalTimezone = function (tp_inst, date) {
1899
- if (tp_inst && tp_inst.timezone_select) {
1900
- var now = date || new Date();
1901
- tp_inst.timezone_select.val(-now.getTimezoneOffset());
1902
- }
1903
- };
1904
-
1905
- /*
1906
- * Create a Singleton Instance
1907
- */
1908
- $.timepicker = new Timepicker();
1909
-
1910
- /**
1911
- * Get the timezone offset as string from a date object (eg '+0530' for UTC+5.5)
1912
- * @param {number} tzMinutes if not a number, less than -720 (-1200), or greater than 840 (+1400) this value is returned
1913
- * @param {boolean} iso8601 if true formats in accordance to iso8601 "+12:45"
1914
- * @return {string}
1915
- */
1916
- $.timepicker.timezoneOffsetString = function (tzMinutes, iso8601) {
1917
- if (isNaN(tzMinutes) || tzMinutes > 840 || tzMinutes < -720) {
1918
- return tzMinutes;
1919
- }
1920
-
1921
- var off = tzMinutes,
1922
- minutes = off % 60,
1923
- hours = (off - minutes) / 60,
1924
- iso = iso8601 ? ':' : '',
1925
- tz = (off >= 0 ? '+' : '-') + ('0' + Math.abs(hours)).slice(-2) + iso + ('0' + Math.abs(minutes)).slice(-2);
1926
-
1927
- if (tz === '+00:00') {
1928
- return 'Z';
1929
- }
1930
- return tz;
1931
- };
1932
-
1933
- /**
1934
- * Get the number in minutes that represents a timezone string
1935
- * @param {string} tzString formatted like "+0500", "-1245", "Z"
1936
- * @return {number} the offset minutes or the original string if it doesn't match expectations
1937
- */
1938
- $.timepicker.timezoneOffsetNumber = function (tzString) {
1939
- var normalized = tzString.toString().replace(':', ''); // excuse any iso8601, end up with "+1245"
1940
-
1941
- if (normalized.toUpperCase() === 'Z') { // if iso8601 with Z, its 0 minute offset
1942
- return 0;
1943
- }
1944
-
1945
- if (!/^(\-|\+)\d{4}$/.test(normalized)) { // possibly a user defined tz, so just give it back
1946
- return tzString;
1947
- }
1948
-
1949
- return ((normalized.substr(0, 1) === '-' ? -1 : 1) * // plus or minus
1950
- ((parseInt(normalized.substr(1, 2), 10) * 60) + // hours (converted to minutes)
1951
- parseInt(normalized.substr(3, 2), 10))); // minutes
1952
- };
1953
-
1954
- /**
1955
- * No way to set timezone in js Date, so we must adjust the minutes to compensate. (think setDate, getDate)
1956
- * @param {Date} date
1957
- * @param {string} toTimezone formatted like "+0500", "-1245"
1958
- * @return {Date}
1959
- */
1960
- $.timepicker.timezoneAdjust = function (date, toTimezone) {
1961
- var toTz = $.timepicker.timezoneOffsetNumber(toTimezone);
1962
- if (!isNaN(toTz)) {
1963
- date.setMinutes(date.getMinutes() + -date.getTimezoneOffset() - toTz);
1964
- }
1965
- return date;
1966
- };
1967
-
1968
- /**
1969
- * Calls `timepicker()` on the `startTime` and `endTime` elements, and configures them to
1970
- * enforce date range limits.
1971
- * n.b. The input value must be correctly formatted (reformatting is not supported)
1972
- * @param {Element} startTime
1973
- * @param {Element} endTime
1974
- * @param {Object} options Options for the timepicker() call
1975
- * @return {jQuery}
1976
- */
1977
- $.timepicker.timeRange = function (startTime, endTime, options) {
1978
- return $.timepicker.handleRange('timepicker', startTime, endTime, options);
1979
- };
1980
-
1981
- /**
1982
- * Calls `datetimepicker` on the `startTime` and `endTime` elements, and configures them to
1983
- * enforce date range limits.
1984
- * @param {Element} startTime
1985
- * @param {Element} endTime
1986
- * @param {Object} options Options for the `timepicker()` call. Also supports `reformat`,
1987
- * a boolean value that can be used to reformat the input values to the `dateFormat`.
1988
- * @param {string} method Can be used to specify the type of picker to be added
1989
- * @return {jQuery}
1990
- */
1991
- $.timepicker.datetimeRange = function (startTime, endTime, options) {
1992
- $.timepicker.handleRange('datetimepicker', startTime, endTime, options);
1993
- };
1994
-
1995
- /**
1996
- * Calls `datepicker` on the `startTime` and `endTime` elements, and configures them to
1997
- * enforce date range limits.
1998
- * @param {Element} startTime
1999
- * @param {Element} endTime
2000
- * @param {Object} options Options for the `timepicker()` call. Also supports `reformat`,
2001
- * a boolean value that can be used to reformat the input values to the `dateFormat`.
2002
- * @return {jQuery}
2003
- */
2004
- $.timepicker.dateRange = function (startTime, endTime, options) {
2005
- $.timepicker.handleRange('datepicker', startTime, endTime, options);
2006
- };
2007
-
2008
- /**
2009
- * Calls `method` on the `startTime` and `endTime` elements, and configures them to
2010
- * enforce date range limits.
2011
- * @param {string} method Can be used to specify the type of picker to be added
2012
- * @param {Element} startTime
2013
- * @param {Element} endTime
2014
- * @param {Object} options Options for the `timepicker()` call. Also supports `reformat`,
2015
- * a boolean value that can be used to reformat the input values to the `dateFormat`.
2016
- * @return {jQuery}
2017
- */
2018
- $.timepicker.handleRange = function (method, startTime, endTime, options) {
2019
- options = $.extend({}, {
2020
- minInterval: 0, // min allowed interval in milliseconds
2021
- maxInterval: 0, // max allowed interval in milliseconds
2022
- start: {}, // options for start picker
2023
- end: {} // options for end picker
2024
- }, options);
2025
-
2026
- function checkDates(changed, other) {
2027
- var startdt = startTime[method]('getDate'),
2028
- enddt = endTime[method]('getDate'),
2029
- changeddt = changed[method]('getDate');
2030
-
2031
- if (startdt !== null) {
2032
- var minDate = new Date(startdt.getTime()),
2033
- maxDate = new Date(startdt.getTime());
2034
-
2035
- minDate.setMilliseconds(minDate.getMilliseconds() + options.minInterval);
2036
- maxDate.setMilliseconds(maxDate.getMilliseconds() + options.maxInterval);
2037
-
2038
- if (options.minInterval > 0 && minDate > enddt) { // minInterval check
2039
- endTime[method]('setDate', minDate);
2040
- }
2041
- else if (options.maxInterval > 0 && maxDate < enddt) { // max interval check
2042
- endTime[method]('setDate', maxDate);
2043
- }
2044
- else if (startdt > enddt) {
2045
- other[method]('setDate', changeddt);
2046
- }
2047
- }
2048
- }
2049
-
2050
- function selected(changed, other, option) {
2051
- if (!changed.val()) {
2052
- return;
2053
- }
2054
- var date = changed[method].call(changed, 'getDate');
2055
- if (date !== null && options.minInterval > 0) {
2056
- if (option === 'minDate') {
2057
- date.setMilliseconds(date.getMilliseconds() + options.minInterval);
2058
- }
2059
- if (option === 'maxDate') {
2060
- date.setMilliseconds(date.getMilliseconds() - options.minInterval);
2061
- }
2062
- }
2063
- if (date.getTime) {
2064
- other[method].call(other, 'option', option, date);
2065
- }
2066
- }
2067
-
2068
- $.fn[method].call(startTime, $.extend({
2069
- onClose: function (dateText, inst) {
2070
- checkDates($(this), endTime);
2071
- },
2072
- onSelect: function (selectedDateTime) {
2073
- selected($(this), endTime, 'minDate');
2074
- }
2075
- }, options, options.start));
2076
- $.fn[method].call(endTime, $.extend({
2077
- onClose: function (dateText, inst) {
2078
- checkDates($(this), startTime);
2079
- },
2080
- onSelect: function (selectedDateTime) {
2081
- selected($(this), startTime, 'maxDate');
2082
- }
2083
- }, options, options.end));
2084
-
2085
- checkDates(startTime, endTime);
2086
- selected(startTime, endTime, 'minDate');
2087
- selected(endTime, startTime, 'maxDate');
2088
- return $([startTime.get(0), endTime.get(0)]);
2089
- };
2090
-
2091
- /**
2092
- * Log error or data to the console during error or debugging
2093
- * @param {Object} err pass any type object to log to the console during error or debugging
2094
- * @return {void}
2095
- */
2096
- $.timepicker.log = function (err) {
2097
- if (window.console) {
2098
- window.console.log(err);
2099
- }
2100
- };
2101
-
2102
- /*
2103
- * Add util object to allow access to private methods for testability.
2104
- */
2105
- $.timepicker._util = {
2106
- _extendRemove: extendRemove,
2107
- _isEmptyObject: isEmptyObject,
2108
- _convert24to12: convert24to12,
2109
- _detectSupport: detectSupport,
2110
- _selectLocalTimezone: selectLocalTimezone,
2111
- _computeEffectiveSetting: computeEffectiveSetting,
2112
- _splitDateTime: splitDateTime,
2113
- _parseDateTimeInternal: parseDateTimeInternal
2114
- };
2115
-
2116
- /*
2117
- * Microsecond support
2118
- */
2119
- if (!Date.prototype.getMicroseconds) {
2120
- Date.prototype.microseconds = 0;
2121
- Date.prototype.getMicroseconds = function () { return this.microseconds; };
2122
- Date.prototype.setMicroseconds = function (m) {
2123
- this.setMilliseconds(this.getMilliseconds() + Math.floor(m / 1000));
2124
- this.microseconds = m % 1000;
2125
- return this;
2126
- };
2127
- }
2128
-
2129
- /*
2130
- * Keep up with the version
2131
- */
2132
- $.timepicker.version = "1.4";
2133
-
2134
- })(jQuery);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
languages/bulk-delete.pot CHANGED
@@ -2,9 +2,9 @@
2
  # This file is distributed under the same license as the Bulk Delete package.
3
  msgid ""
4
  msgstr ""
5
- "Project-Id-Version: Bulk Delete 5.4.1\n"
6
  "Report-Msgid-Bugs-To: http://wordpress.org/tag/bulk-delete\n"
7
- "POT-Creation-Date: 2015-02-14 14:49:54+00:00\n"
8
  "MIME-Version: 1.0\n"
9
  "Content-Type: text/plain; charset=UTF-8\n"
10
  "Content-Transfer-Encoding: 8bit\n"
@@ -12,542 +12,573 @@ msgstr ""
12
  "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
13
  "Language-Team: LANGUAGE <LL@li.org>\n"
14
 
15
- #: bulk-delete.php:166 bulk-delete.php:178
16
  msgid "Cheatin&#8217; huh?"
17
  msgstr ""
18
 
19
- #: bulk-delete.php:261
20
  msgid "Bulk WP"
21
  msgstr ""
22
 
23
- #: bulk-delete.php:263 bulk-delete.php:475 include/admin-ui.php:52
24
  msgid "Bulk Delete Posts"
25
  msgstr ""
26
 
27
- #: bulk-delete.php:264 bulk-delete.php:527
28
  msgid "Bulk Delete Pages"
29
  msgstr ""
30
 
31
- #: bulk-delete.php:265 bulk-delete.php:577 include/admin-ui.php:49
32
  msgid "Bulk Delete Users"
33
  msgstr ""
34
 
35
- #: bulk-delete.php:285 bulk-delete.php:638
36
  msgid "Bulk Delete Schedules"
37
  msgstr ""
38
 
39
- #: bulk-delete.php:285
40
  msgid "Scheduled Jobs"
41
  msgstr ""
42
 
43
- #: bulk-delete.php:286 include/class-bd-license.php:30
44
  msgid "Addon Licenses"
45
  msgstr ""
46
 
47
- #: bulk-delete.php:287
48
  msgid "Bulk Delete System Info"
49
  msgstr ""
50
 
51
- #: bulk-delete.php:287
52
  msgid "System Info"
53
  msgstr ""
54
 
55
- #: bulk-delete.php:339
56
  msgid "By Post Status"
57
  msgstr ""
58
 
59
- #: bulk-delete.php:340
60
  msgid "By Category"
61
  msgstr ""
62
 
63
- #: bulk-delete.php:341
64
  msgid "By Tag"
65
  msgstr ""
66
 
67
- #: bulk-delete.php:342
68
  msgid "By Custom Taxonomy"
69
  msgstr ""
70
 
71
- #: bulk-delete.php:343
72
  msgid "By Custom Post Types"
73
  msgstr ""
74
 
75
- #: bulk-delete.php:344
76
  msgid "By URL"
77
  msgstr ""
78
 
79
- #: bulk-delete.php:345
80
  msgid "By Post Revision"
81
  msgstr ""
82
 
83
- #: bulk-delete.php:346
84
  msgid "By Custom Field"
85
  msgstr ""
86
 
87
- #: bulk-delete.php:347
88
  msgid "By Title"
89
  msgstr ""
90
 
91
- #: bulk-delete.php:348
92
  msgid "By Duplicate Title"
93
  msgstr ""
94
 
95
- #: bulk-delete.php:349 bulk-delete.php:423
96
  msgid "By User Role"
97
  msgstr ""
98
 
99
- #: bulk-delete.php:350 tmp_addon/bulk-delete-from-trash.php:151
100
  msgid "Posts in Trash"
101
  msgstr ""
102
 
103
- #: bulk-delete.php:388
104
  msgid "By Page status"
105
  msgstr ""
106
 
107
- #: bulk-delete.php:389
108
  msgid "Pages in Trash"
109
  msgstr ""
110
 
111
- #: bulk-delete.php:491 include/misc/class-bulk-delete-misc.php:111
112
  msgid "WARNING: Posts deleted once cannot be retrieved back. Use with caution."
113
  msgstr ""
114
 
115
- #: bulk-delete.php:543
116
  msgid "WARNING: Pages deleted once cannot be retrieved back. Use with caution."
117
  msgstr ""
118
 
119
- #: bulk-delete.php:593
120
  msgid "WARNING: Users deleted once cannot be retrieved back. Use with caution."
121
  msgstr ""
122
 
123
- #: include/admin-ui.php:19
124
  msgid ""
125
- "Thank you for using <a href = \"%1$s\">Bulk Delete</a> plugin! Kindly <a "
126
- "href = \"%2$s\">rate us</a> at <a href = \"%2$s\">WordPress.org</a>"
127
  msgstr ""
128
 
129
- #: include/admin-ui.php:72
130
- msgid "Buy Addons"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
131
  msgstr ""
132
 
133
- #: include/class-bd-license-handler.php:133
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
134
  msgid "Addon License Key"
135
  msgstr ""
136
 
137
- #: include/class-bd-license-handler.php:153
138
  msgid "Enter license key"
139
  msgstr ""
140
 
141
- #: include/class-bd-license.php:63
142
  msgid "Activate License"
143
  msgstr ""
144
 
145
- #: include/class-bd-license.php:190
146
  msgid "The license key for \"%s\" addon was successfully deactivated"
147
  msgstr ""
148
 
149
- #: include/class-bd-license.php:195
150
  msgid ""
151
  "There was some problem while trying to deactivate license key for \"%s\" "
152
  "addon. Kindly try again"
153
  msgstr ""
154
 
155
- #: include/class-bd-license.php:220
156
  msgid "The license key was successfully deleted"
157
  msgstr ""
158
 
159
- #: include/class-bd-license.php:264
160
  msgid ""
161
  "There was some problem in contacting our store to activate the license key "
162
  "for \"%s\" addon"
163
  msgstr ""
164
 
165
- #: include/class-bd-license.php:274
166
  msgid ""
167
  "The license key for \"%s\" addon was successfully activated. The addon will "
168
  "get updates automatically till the license key is valid."
169
  msgstr ""
170
 
171
- #: include/class-bd-license.php:282
172
  msgid ""
173
  "The license key for \"%s\" addon doesn't have any more activations left. "
174
  "Kindly buy a new license."
175
  msgstr ""
176
 
177
- #: include/class-bd-license.php:286
178
  msgid "The license key for \"%s\" addon is revoked. Kindly buy a new license."
179
  msgstr ""
180
 
181
- #: include/class-bd-license.php:290
182
  msgid "The license key for \"%s\" addon has expired. Kindly buy a new license."
183
  msgstr ""
184
 
185
- #: include/class-bd-license.php:294
186
  msgid "The license key for \"%s\" addon is invalid"
187
  msgstr ""
188
 
189
- #: include/class-bd-license.php:356
190
  msgid ""
191
  "The following are the list of pro addons that are currently available for "
192
  "purchase."
193
  msgstr ""
194
 
195
- #: include/class-bd-license.php:362
196
  msgid "Delete posts by custom field"
197
  msgstr ""
198
 
199
- #: include/class-bd-license.php:363
200
  msgid "Adds the ability to delete posts based on custom fields"
201
  msgstr ""
202
 
203
- #: include/class-bd-license.php:364 include/class-bd-license.php:370
204
- #: include/class-bd-license.php:376 include/class-bd-license.php:382
205
- #: include/class-bd-license.php:388 include/class-bd-license.php:394
206
- #: include/class-bd-license.php:400 include/class-bd-license.php:406
207
- #: include/class-bd-license.php:412 include/class-bd-license.php:418
208
- #: include/class-bd-license.php:424 include/class-bd-license.php:430
209
- #: include/class-bd-license.php:436 include/class-bd-license.php:442
210
- #: include/class-bd-license.php:448 include/class-bd-license.php:454
211
- #: include/class-bd-license.php:460 include/class-bd-license.php:466
 
 
 
 
 
 
 
 
 
212
  msgid "More Info"
213
  msgstr ""
214
 
215
- #: include/class-bd-license.php:368
216
  msgid "Delete posts by title"
217
  msgstr ""
218
 
219
- #: include/class-bd-license.php:369
220
  msgid "Adds the ability to delete posts based on title"
221
  msgstr ""
222
 
223
- #: include/class-bd-license.php:374
224
  msgid "Delete posts by duplicate title"
225
  msgstr ""
226
 
227
- #: include/class-bd-license.php:375
228
  msgid "Adds the ability to delete posts based on duplicate title"
229
  msgstr ""
230
 
231
- #: include/class-bd-license.php:380
232
  msgid "Delete posts by attachment"
233
  msgstr ""
234
 
235
- #: include/class-bd-license.php:381
236
  msgid ""
237
  "Adds the ability to delete posts based on whether it contains attachment or "
238
  "not"
239
  msgstr ""
240
 
241
- #: include/class-bd-license.php:386
242
  msgid "Delete posts by user role"
243
  msgstr ""
244
 
245
- #: include/class-bd-license.php:387
246
  msgid "Adds the ability to delete posts based on user role"
247
  msgstr ""
248
 
249
- #: include/class-bd-license.php:392
250
  msgid "Delete from trash"
251
  msgstr ""
252
 
253
- #: include/class-bd-license.php:393
254
  msgid "Adds the ability to delete posts and pages from trash"
255
  msgstr ""
256
 
257
- #: include/class-bd-license.php:398
258
  msgid "Scheduler Email"
259
  msgstr ""
260
 
261
- #: include/class-bd-license.php:399
262
  msgid "Sends an email every time a Bulk WP scheduler runs"
263
  msgstr ""
264
 
265
- #: include/class-bd-license.php:404
266
  msgid "Scheduler for deleting Posts by Category"
267
  msgstr ""
268
 
269
- #: include/class-bd-license.php:405
270
  msgid "Adds the ability to schedule auto delete of posts based on category"
271
  msgstr ""
272
 
273
- #: include/class-bd-license.php:410
274
  msgid "Scheduler for deleting Posts by Tag"
275
  msgstr ""
276
 
277
- #: include/class-bd-license.php:411
278
  msgid "Adds the ability to schedule auto delete of posts based on tag"
279
  msgstr ""
280
 
281
- #: include/class-bd-license.php:416
282
  msgid "Scheduler for deleting Posts by Custom Taxonomy"
283
  msgstr ""
284
 
285
- #: include/class-bd-license.php:417
286
  msgid ""
287
  "Adds the ability to schedule auto delete of posts based on custom taxonomy"
288
  msgstr ""
289
 
290
- #: include/class-bd-license.php:422
291
  msgid "Scheduler for deleting Posts by Custom Post Type"
292
  msgstr ""
293
 
294
- #: include/class-bd-license.php:423
295
  msgid ""
296
  "Adds the ability to schedule auto delete of posts based on custom post type"
297
  msgstr ""
298
 
299
- #: include/class-bd-license.php:428
300
  msgid "Scheduler for deleting Posts by Post Status"
301
  msgstr ""
302
 
303
- #: include/class-bd-license.php:429
304
  msgid ""
305
  "Adds the ability to schedule auto delete of posts based on post status like "
306
  "drafts, pending posts, scheduled posts etc."
307
  msgstr ""
308
 
309
- #: include/class-bd-license.php:434
310
  msgid "Scheduler for deleting Pages by Status"
311
  msgstr ""
312
 
313
- #: include/class-bd-license.php:435
314
  msgid "Adds the ability to schedule auto delete pages based on status"
315
  msgstr ""
316
 
317
- #: include/class-bd-license.php:440
318
  msgid "Scheduler for deleting Users by User Role"
319
  msgstr ""
320
 
321
- #: include/class-bd-license.php:441
322
  msgid "Adds the ability to schedule auto delete of users based on user role"
323
  msgstr ""
324
 
325
- #: include/class-bd-license.php:446
326
  msgid "Delete Post Meta Fields"
327
  msgstr ""
328
 
329
- #: include/class-bd-license.php:447
330
  msgid ""
331
  "Adds the ability to delete post meta fields based on value and to schedule "
332
  "automatic deletion"
333
  msgstr ""
334
 
335
- #: include/class-bd-license.php:452
336
  msgid "Delete Comment Meta Fields"
337
  msgstr ""
338
 
339
- #: include/class-bd-license.php:453
340
  msgid ""
341
  "Adds the ability to delete comment meta fields based on value and to "
342
  "schedule automatic deletion"
343
  msgstr ""
344
 
345
- #: include/class-bd-license.php:458
346
  msgid "Delete User Meta Fields"
347
  msgstr ""
348
 
349
- #: include/class-bd-license.php:459
350
  msgid ""
351
  "Adds the ability to delete user meta fields based on value and to schedule "
352
  "automatic deletion"
353
  msgstr ""
354
 
355
- #: include/class-bd-license.php:464
356
  msgid "Delete Jetpack Contact Form Messages"
357
  msgstr ""
358
 
359
- #: include/class-bd-license.php:465
360
  msgid ""
361
  "Adds the ability to delete Jetpack Contact Form Messages based on filters "
362
  "and to schedule automatic deletion"
363
  msgstr ""
364
 
365
- #: include/class-bd-settings.php:26
366
- msgid "Add Addon License"
367
- msgstr ""
368
-
369
- #: include/class-bulk-delete-help-screen.php:31
370
- msgid "More information"
371
- msgstr ""
372
-
373
- #: include/class-bulk-delete-help-screen.php:32
374
- msgid "Support Forums"
375
- msgstr ""
376
-
377
- #: include/class-bulk-delete-help-screen.php:33
378
- msgid "Buy pro addons"
379
- msgstr ""
380
-
381
- #: include/class-bulk-delete-help-screen.php:34
382
- msgid "Plugin author's blog"
383
  msgstr ""
384
 
385
- #: include/class-bulk-delete-help-screen.php:35
386
- msgid "Other Plugin's by Author"
387
  msgstr ""
388
 
389
- #: include/class-bulk-delete-help-screen.php:56
390
- #: include/class-bulk-delete-help-screen.php:68
391
- #: include/class-bulk-delete-help-screen.php:80
392
- msgid "Overview"
393
  msgstr ""
394
 
395
- #: include/class-bulk-delete-help-screen.php:58
396
- msgid ""
397
- "This screen contains different modules that allows you to delete posts or "
398
- "schedule them for deletion."
399
  msgstr ""
400
 
401
- #: include/class-bulk-delete-help-screen.php:70
402
- msgid ""
403
- "This screen contains different modules that allows you to delete pages or "
404
- "schedule them for deletion."
405
  msgstr ""
406
 
407
- #: include/class-bulk-delete-help-screen.php:82
408
- msgid ""
409
- "This screen contains different modules that allows you to delete users or "
410
- "schedule them for deletion."
411
  msgstr ""
412
 
413
- #: include/class-bulk-delete-help-screen.php:92
414
- msgid "About Plugin"
415
  msgstr ""
416
 
417
- #: include/class-bulk-delete-help-screen.php:115
418
- msgid "This plugin allows you to perform bulk operations in WordPress easily."
419
  msgstr ""
420
 
421
- #: include/class-bulk-delete-help-screen.php:116
422
- msgid ""
423
- "This plugin can be used to delete the posts, pages or users using various "
424
- "filters and conditions."
425
  msgstr ""
426
 
427
- #: include/class-bulk-delete-pages.php:22
428
- #: include/class-bulk-delete-pages.php:261
429
- #: include/class-bulk-delete-posts.php:17
430
- #: include/class-bulk-delete-posts.php:302
431
- #: include/class-bulk-delete-posts.php:565
432
- #: include/class-bulk-delete-posts.php:782
433
- #: include/class-bulk-delete-posts.php:1082
434
- #: include/class-bulk-delete-posts.php:1326
435
- #: include/class-bulk-delete-posts.php:1410
436
- #: include/class-bulk-delete-posts.php:1491
437
- #: include/class-bulk-delete-posts.php:1520
438
- #: include/class-bulk-delete-posts.php:1550
439
- #: include/class-bulk-delete-posts.php:1579
440
- #: include/class-bulk-delete-posts.php:1606
441
- #: include/class-bulk-delete-users.php:17
442
- #: include/meta/class-bulk-delete-comment-meta.php:50
443
- #: include/meta/class-bulk-delete-post-meta.php:50
444
- #: include/meta/class-bulk-delete-user-meta.php:50
445
- #: include/misc/class-bulk-delete-jetpack-contact-form-messages.php:44
446
  msgid ""
447
  "This section just got enabled. Kindly <a href = \"%1$s\">refresh</a> the "
448
  "page to fully enable it."
449
  msgstr ""
450
 
451
- #: include/class-bulk-delete-pages.php:34
452
- msgid "Select the pages which you want to delete"
453
  msgstr ""
454
 
455
- #: include/class-bulk-delete-pages.php:41
456
- msgid "All Published Pages"
457
  msgstr ""
458
 
459
- #: include/class-bulk-delete-pages.php:41
460
- #: include/class-bulk-delete-pages.php:48
461
- #: include/class-bulk-delete-pages.php:55
462
- #: include/class-bulk-delete-pages.php:62
463
- #: include/class-bulk-delete-pages.php:69
464
- msgid "Pages"
465
  msgstr ""
466
 
467
- #: include/class-bulk-delete-pages.php:48
468
- msgid "All Draft Pages"
469
  msgstr ""
470
 
471
- #: include/class-bulk-delete-pages.php:55
472
- msgid "All Scheduled Pages"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
473
  msgstr ""
474
 
475
- #: include/class-bulk-delete-pages.php:62
476
- msgid "All Pending Pages"
477
  msgstr ""
478
 
479
- #: include/class-bulk-delete-pages.php:69
480
- msgid "All Private Pages"
 
 
481
  msgstr ""
482
 
483
- #: include/class-bulk-delete-pages.php:75
484
- #: include/class-bulk-delete-posts.php:78
485
- #: include/class-bulk-delete-posts.php:369
486
- #: include/class-bulk-delete-posts.php:602
487
- #: include/class-bulk-delete-posts.php:878
488
- #: include/class-bulk-delete-posts.php:1137
489
- #: include/class-bulk-delete-posts.php:1345
490
- #: include/class-bulk-delete-users.php:41
491
- #: tmp_addon/bulk-delete-attachments.php:261
492
- #: tmp_addon/bulk-delete-jetpack-contact-form-messages.php:123
493
- #: tmp_addon/bulk-delete-posts-by-attachment.php:163
494
- #: tmp_addon/bulk-delete-posts-by-content.php:186
495
- #: tmp_addon/bulk-delete-posts-by-custom-field.php:191
496
- #: tmp_addon/bulk-delete-posts-by-duplicate-title.php:156
497
- #: tmp_addon/bulk-delete-posts-by-title.php:137
498
- #: tmp_addon/bulk-delete-posts-by-user-role.php:127
499
- msgid "Choose your filtering options"
500
  msgstr ""
501
 
502
- #: include/class-bulk-delete-pages.php:82
503
- msgid "Only restrict to pages which are "
504
  msgstr ""
505
 
506
- #: include/class-bulk-delete-pages.php:84
507
- #: include/class-bulk-delete-posts.php:93
508
- #: include/class-bulk-delete-posts.php:380
509
- #: include/class-bulk-delete-posts.php:613
510
- #: include/class-bulk-delete-posts.php:889
511
- #: include/class-bulk-delete-posts.php:1148
512
- #: include/meta/class-bulk-delete-comment-meta.php:128
513
- #: include/meta/class-bulk-delete-post-meta.php:128
514
- #: include/misc/class-bulk-delete-jetpack-contact-form-messages.php:106
515
  #: tmp_addon/bulk-delete-attachments.php:272
516
  #: tmp_addon/bulk-delete-posts-by-attachment.php:174
517
  #: tmp_addon/bulk-delete-posts-by-content.php:194
518
  #: tmp_addon/bulk-delete-posts-by-custom-field.php:202
519
  #: tmp_addon/bulk-delete-posts-by-title.php:148
520
  #: tmp_addon/bulk-delete-posts-by-user-role.php:134
 
521
  msgid "older than"
522
  msgstr ""
523
 
524
- #: include/class-bulk-delete-pages.php:85
525
- #: include/class-bulk-delete-posts.php:94
526
- #: include/class-bulk-delete-posts.php:381
527
- #: include/class-bulk-delete-posts.php:614
528
- #: include/class-bulk-delete-posts.php:890
529
- #: include/class-bulk-delete-posts.php:1149
530
- #: include/meta/class-bulk-delete-post-meta.php:129
531
- #: include/misc/class-bulk-delete-jetpack-contact-form-messages.php:107
532
- #: tmp_addon/bulk-delete-attachments.php:273
533
- #: tmp_addon/bulk-delete-posts-by-attachment.php:175
534
- #: tmp_addon/bulk-delete-posts-by-content.php:195
535
- #: tmp_addon/bulk-delete-posts-by-custom-field.php:203
536
- #: tmp_addon/bulk-delete-posts-by-title.php:149
537
- #: tmp_addon/bulk-delete-posts-by-user-role.php:135
538
- msgid "posted within last"
539
  msgstr ""
540
 
541
- #: include/class-bulk-delete-pages.php:87
542
- #: include/class-bulk-delete-posts.php:96
543
- #: include/class-bulk-delete-posts.php:383
544
- #: include/class-bulk-delete-posts.php:616
545
- #: include/class-bulk-delete-posts.php:892
546
- #: include/class-bulk-delete-posts.php:1151
547
- #: include/class-bulk-delete-users.php:56
548
- #: include/meta/class-bulk-delete-comment-meta.php:131
549
- #: include/meta/class-bulk-delete-post-meta.php:131
550
- #: include/misc/class-bulk-delete-jetpack-contact-form-messages.php:109
551
  #: tmp_addon/bulk-delete-attachments.php:275
552
  #: tmp_addon/bulk-delete-from-trash.php:348
553
  #: tmp_addon/bulk-delete-posts-by-attachment.php:177
@@ -555,83 +586,46 @@ msgstr ""
555
  #: tmp_addon/bulk-delete-posts-by-custom-field.php:205
556
  #: tmp_addon/bulk-delete-posts-by-title.php:151
557
  #: tmp_addon/bulk-delete-posts-by-user-role.php:137
 
558
  msgid "days"
559
  msgstr ""
560
 
561
- #: include/class-bulk-delete-pages.php:93
562
- #: include/class-bulk-delete-posts.php:102
563
- #: include/class-bulk-delete-posts.php:389
564
- #: include/class-bulk-delete-posts.php:622
565
- #: include/class-bulk-delete-posts.php:898
566
- #: include/class-bulk-delete-posts.php:1157
567
- #: include/class-bulk-delete-posts.php:1351
568
- #: include/misc/class-bulk-delete-jetpack-contact-form-messages.php:132
569
- #: tmp_addon/bulk-delete-attachments.php:281
570
- #: tmp_addon/bulk-delete-posts-by-attachment.php:183
571
- #: tmp_addon/bulk-delete-posts-by-content.php:203
572
- #: tmp_addon/bulk-delete-posts-by-custom-field.php:211
573
- #: tmp_addon/bulk-delete-posts-by-duplicate-title.php:162
574
- #: tmp_addon/bulk-delete-posts-by-title.php:157
575
- #: tmp_addon/bulk-delete-posts-by-user-role.php:143
576
- msgid "Move to Trash"
577
- msgstr ""
578
-
579
- #: include/class-bulk-delete-pages.php:94
580
- #: include/class-bulk-delete-posts.php:103
581
- #: include/class-bulk-delete-posts.php:390
582
- #: include/class-bulk-delete-posts.php:623
583
- #: include/class-bulk-delete-posts.php:899
584
- #: include/class-bulk-delete-posts.php:1158
585
- #: include/class-bulk-delete-posts.php:1352
586
- #: include/misc/class-bulk-delete-jetpack-contact-form-messages.php:133
587
- #: tmp_addon/bulk-delete-attachments.php:282
588
- #: tmp_addon/bulk-delete-posts-by-attachment.php:184
589
- #: tmp_addon/bulk-delete-posts-by-content.php:204
590
- #: tmp_addon/bulk-delete-posts-by-custom-field.php:212
591
- #: tmp_addon/bulk-delete-posts-by-duplicate-title.php:163
592
- #: tmp_addon/bulk-delete-posts-by-title.php:158
593
- #: tmp_addon/bulk-delete-posts-by-user-role.php:144
594
- msgid "Delete permanently"
595
- msgstr ""
596
-
597
- #: include/class-bulk-delete-pages.php:101
598
- #: include/class-bulk-delete-posts.php:110
599
- #: include/class-bulk-delete-posts.php:406
600
- #: include/class-bulk-delete-posts.php:639
601
- #: include/class-bulk-delete-posts.php:915
602
- #: include/class-bulk-delete-posts.php:1167
603
- #: include/class-bulk-delete-users.php:79
604
- #: include/misc/class-bulk-delete-jetpack-contact-form-messages.php:118
605
- #: tmp_addon/bulk-delete-attachments.php:291
606
- #: tmp_addon/bulk-delete-posts-by-attachment.php:200
607
- #: tmp_addon/bulk-delete-posts-by-content.php:218
608
- #: tmp_addon/bulk-delete-posts-by-custom-field.php:228
609
- #: tmp_addon/bulk-delete-posts-by-duplicate-title.php:170
610
- #: tmp_addon/bulk-delete-posts-by-title.php:174
611
- #: tmp_addon/bulk-delete-posts-by-user-role.php:151
612
- msgid "Only delete first "
613
  msgstr ""
614
 
615
- #: include/class-bulk-delete-pages.php:102
616
- msgid "pages."
617
  msgstr ""
618
 
619
- #: include/class-bulk-delete-pages.php:103
 
 
 
 
 
 
 
 
 
 
 
 
620
  msgid ""
621
- "Use this option if there are more than 1000 pages and the script timesout."
622
  msgstr ""
623
 
624
- #: include/class-bulk-delete-pages.php:109
625
- #: include/class-bulk-delete-posts.php:118
626
- #: include/class-bulk-delete-posts.php:414
627
- #: include/class-bulk-delete-posts.php:647
628
- #: include/class-bulk-delete-posts.php:923
629
- #: include/class-bulk-delete-posts.php:1175
630
- #: include/class-bulk-delete-users.php:88
631
- #: include/meta/class-bulk-delete-comment-meta.php:146
632
- #: include/meta/class-bulk-delete-post-meta.php:146
633
- #: include/meta/class-bulk-delete-user-meta.php:126
634
- #: include/misc/class-bulk-delete-jetpack-contact-form-messages.php:139
635
  #: tmp_addon/bulk-delete-attachments.php:299
636
  #: tmp_addon/bulk-delete-posts-by-attachment.php:208
637
  #: tmp_addon/bulk-delete-posts-by-content.php:226
@@ -639,41 +633,21 @@ msgstr ""
639
  #: tmp_addon/bulk-delete-posts-by-duplicate-title.php:178
640
  #: tmp_addon/bulk-delete-posts-by-title.php:182
641
  #: tmp_addon/bulk-delete-posts-by-user-role.php:160
 
642
  msgid "Delete now"
643
  msgstr ""
644
 
645
- #: include/class-bulk-delete-pages.php:110
646
- #: include/class-bulk-delete-posts.php:119
647
- #: include/class-bulk-delete-posts.php:415
648
- #: include/class-bulk-delete-posts.php:648
649
- #: include/class-bulk-delete-posts.php:924
650
- #: include/class-bulk-delete-posts.php:1176
651
- #: include/class-bulk-delete-users.php:89 include/class-cron-list-table.php:56
652
- #: include/meta/class-bulk-delete-comment-meta.php:147
653
- #: include/meta/class-bulk-delete-post-meta.php:147
654
- #: include/meta/class-bulk-delete-user-meta.php:127
655
- #: include/misc/class-bulk-delete-jetpack-contact-form-messages.php:140
656
- #: tmp_addon/bulk-delete-attachments.php:300
657
- #: tmp_addon/bulk-delete-posts-by-attachment.php:209
658
- #: tmp_addon/bulk-delete-posts-by-content.php:227
659
- #: tmp_addon/bulk-delete-posts-by-custom-field.php:237
660
- #: tmp_addon/bulk-delete-posts-by-duplicate-title.php:179
661
- #: tmp_addon/bulk-delete-posts-by-title.php:183
662
- #: tmp_addon/bulk-delete-posts-by-user-role.php:161
663
- msgid "Schedule"
664
- msgstr ""
665
-
666
- #: include/class-bulk-delete-pages.php:111
667
- #: include/class-bulk-delete-posts.php:120
668
- #: include/class-bulk-delete-posts.php:416
669
- #: include/class-bulk-delete-posts.php:649
670
- #: include/class-bulk-delete-posts.php:925
671
- #: include/class-bulk-delete-posts.php:1177
672
- #: include/class-bulk-delete-users.php:90
673
- #: include/meta/class-bulk-delete-comment-meta.php:148
674
- #: include/meta/class-bulk-delete-post-meta.php:148
675
- #: include/meta/class-bulk-delete-user-meta.php:128
676
- #: include/misc/class-bulk-delete-jetpack-contact-form-messages.php:141
677
  #: tmp_addon/bulk-delete-attachments.php:301
678
  #: tmp_addon/bulk-delete-posts-by-attachment.php:210
679
  #: tmp_addon/bulk-delete-posts-by-content.php:228
@@ -681,20 +655,21 @@ msgstr ""
681
  #: tmp_addon/bulk-delete-posts-by-duplicate-title.php:180
682
  #: tmp_addon/bulk-delete-posts-by-title.php:184
683
  #: tmp_addon/bulk-delete-posts-by-user-role.php:162
 
684
  msgid "repeat "
685
  msgstr ""
686
 
687
- #: include/class-bulk-delete-pages.php:113
688
- #: include/class-bulk-delete-posts.php:122
689
- #: include/class-bulk-delete-posts.php:418
690
- #: include/class-bulk-delete-posts.php:651
691
- #: include/class-bulk-delete-posts.php:927
692
- #: include/class-bulk-delete-posts.php:1179
693
- #: include/class-bulk-delete-users.php:92
694
- #: include/meta/class-bulk-delete-comment-meta.php:150
695
- #: include/meta/class-bulk-delete-post-meta.php:150
696
- #: include/meta/class-bulk-delete-user-meta.php:130
697
- #: include/misc/class-bulk-delete-jetpack-contact-form-messages.php:143
698
  #: tmp_addon/bulk-delete-attachments.php:303
699
  #: tmp_addon/bulk-delete-posts-by-attachment.php:212
700
  #: tmp_addon/bulk-delete-posts-by-content.php:230
@@ -702,47 +677,39 @@ msgstr ""
702
  #: tmp_addon/bulk-delete-posts-by-duplicate-title.php:182
703
  #: tmp_addon/bulk-delete-posts-by-title.php:186
704
  #: tmp_addon/bulk-delete-posts-by-user-role.php:164
 
705
  msgid "Don't repeat"
706
  msgstr ""
707
 
708
- #: include/class-bulk-delete-pages.php:123
709
- #: include/class-bulk-delete-posts.php:132
710
- #: include/class-bulk-delete-posts.php:428
711
- #: include/class-bulk-delete-posts.php:661
712
- #: include/class-bulk-delete-posts.php:937
713
- #: include/class-bulk-delete-posts.php:1189
714
- #: include/class-bulk-delete-users.php:102
715
- #: include/meta/class-bulk-delete-comment-meta.php:95
716
- #: include/meta/class-bulk-delete-comment-meta.php:161
717
- #: include/meta/class-bulk-delete-post-meta.php:95
718
- #: include/meta/class-bulk-delete-post-meta.php:161
719
- #: include/meta/class-bulk-delete-user-meta.php:87
720
- #: include/meta/class-bulk-delete-user-meta.php:141
721
- #: include/misc/class-bulk-delete-jetpack-contact-form-messages.php:79
722
- #: include/misc/class-bulk-delete-jetpack-contact-form-messages.php:153
723
- #: tmp_addon/bulk-delete-attachments.php:313
724
- #: tmp_addon/bulk-delete-posts-by-attachment.php:222
725
- #: tmp_addon/bulk-delete-posts-by-content.php:240
726
- #: tmp_addon/bulk-delete-posts-by-custom-field.php:250
727
- #: tmp_addon/bulk-delete-posts-by-duplicate-title.php:192
728
- #: tmp_addon/bulk-delete-posts-by-title.php:196
729
- #: tmp_addon/bulk-delete-posts-by-user-role.php:174
730
- msgid "Only available in Pro Addon"
731
  msgstr ""
732
 
733
- #: include/class-bulk-delete-pages.php:130
734
- #: include/class-bulk-delete-posts.php:139
735
- #: include/class-bulk-delete-posts.php:442
736
- #: include/class-bulk-delete-posts.php:668
737
- #: include/class-bulk-delete-posts.php:944
738
- #: include/class-bulk-delete-posts.php:1196
739
- #: include/class-bulk-delete-posts.php:1360
740
- #: include/class-bulk-delete-posts.php:1434
741
- #: include/class-bulk-delete-users.php:116
742
- #: include/meta/class-bulk-delete-comment-meta.php:176
743
- #: include/meta/class-bulk-delete-post-meta.php:176
744
- #: include/meta/class-bulk-delete-user-meta.php:156
745
- #: include/misc/class-bulk-delete-jetpack-contact-form-messages.php:160
746
  #: tmp_addon/bulk-delete-attachments.php:326
747
  #: tmp_addon/bulk-delete-from-trash.php:162
748
  #: tmp_addon/bulk-delete-from-trash.php:270
@@ -752,24 +719,33 @@ msgstr ""
752
  #: tmp_addon/bulk-delete-posts-by-duplicate-title.php:206
753
  #: tmp_addon/bulk-delete-posts-by-title.php:210
754
  #: tmp_addon/bulk-delete-posts-by-user-role.php:188
 
755
  msgid "Bulk Delete "
756
  msgstr ""
757
 
758
- #: include/class-bulk-delete-pages.php:165
759
- msgid "The selected pages are scheduled for deletion."
 
 
760
  msgstr ""
761
 
762
- #: include/class-bulk-delete-pages.php:166
763
- #: include/class-bulk-delete-posts.php:177
764
- #: include/class-bulk-delete-posts.php:478
765
- #: include/class-bulk-delete-posts.php:707
766
- #: include/class-bulk-delete-posts.php:985
767
- #: include/class-bulk-delete-posts.php:1236
768
- #: include/class-bulk-delete-users.php:149
769
- #: include/meta/class-bulk-delete-comment-meta.php:237
770
- #: include/meta/class-bulk-delete-post-meta.php:237
771
- #: include/meta/class-bulk-delete-user-meta.php:213
772
- #: include/misc/class-bulk-delete-jetpack-contact-form-messages.php:220
 
 
 
 
 
 
773
  #: tmp_addon/bulk-delete-attachments.php:375
774
  #: tmp_addon/bulk-delete-posts-by-attachment.php:288
775
  #: tmp_addon/bulk-delete-posts-by-content.php:292
@@ -777,712 +753,763 @@ msgstr ""
777
  #: tmp_addon/bulk-delete-posts-by-duplicate-title.php:249
778
  #: tmp_addon/bulk-delete-posts-by-title.php:247
779
  #: tmp_addon/bulk-delete-posts-by-user-role.php:222
 
780
  msgid "See the full list of <a href = \"%s\">scheduled tasks</a>"
781
  msgstr ""
782
 
783
- #: include/class-bulk-delete-pages.php:169
784
- msgid "Deleted %d page"
785
- msgid_plural "Deleted %d pages"
786
  msgstr[0] ""
787
  msgstr[1] ""
788
 
789
- #: include/class-bulk-delete-pages.php:270
790
- msgid "You need \"Bulk Delete From Trash\" Addon, to delete pages in Trash."
791
- msgstr ""
792
-
793
- #: include/class-bulk-delete-posts.php:30
794
- #: include/class-bulk-delete-posts.php:1419
795
- msgid "Select the posts which you want to delete"
796
- msgstr ""
797
-
798
- #: include/class-bulk-delete-posts.php:37
799
- msgid "All publish posts"
800
- msgstr ""
801
-
802
- #: include/class-bulk-delete-posts.php:37
803
- #: include/class-bulk-delete-posts.php:51
804
- #: include/class-bulk-delete-posts.php:58
805
- #: include/class-bulk-delete-posts.php:65
806
- #: include/class-bulk-delete-posts.php:72
807
- #: include/class-bulk-delete-posts.php:350
808
- #: include/class-bulk-delete-posts.php:585
809
- #: include/class-bulk-delete-posts.php:865
810
- msgid "Posts"
811
  msgstr ""
812
 
813
- #: include/class-bulk-delete-posts.php:44
814
- msgid "All Draft Posts"
 
815
  msgstr ""
816
 
817
- #: include/class-bulk-delete-posts.php:44
818
- msgid "Drafts"
819
  msgstr ""
820
 
821
- #: include/class-bulk-delete-posts.php:51
822
- msgid "All Pending posts"
823
  msgstr ""
824
 
825
- #: include/class-bulk-delete-posts.php:58
826
- msgid "All scheduled posts"
827
  msgstr ""
828
 
829
- #: include/class-bulk-delete-posts.php:65
830
- msgid "All private posts"
831
  msgstr ""
832
 
833
- #: include/class-bulk-delete-posts.php:72
834
- msgid "All Sticky posts"
835
  msgstr ""
836
 
837
- #: include/class-bulk-delete-posts.php:84
838
- msgid "Note: The date filter will not work for sticky posts"
839
  msgstr ""
840
 
841
- #: include/class-bulk-delete-posts.php:91
842
- #: include/class-bulk-delete-posts.php:378
843
- #: include/class-bulk-delete-posts.php:611
844
- #: include/class-bulk-delete-posts.php:887
845
- #: include/class-bulk-delete-posts.php:1146
846
- #: include/meta/class-bulk-delete-post-meta.php:126
847
- #: include/misc/class-bulk-delete-jetpack-contact-form-messages.php:104
848
  #: tmp_addon/bulk-delete-posts-by-attachment.php:172
849
  #: tmp_addon/bulk-delete-posts-by-content.php:192
850
  #: tmp_addon/bulk-delete-posts-by-custom-field.php:200
851
  #: tmp_addon/bulk-delete-posts-by-title.php:146
852
  #: tmp_addon/bulk-delete-posts-by-user-role.php:132
 
853
  msgid "Only restrict to posts which are "
854
  msgstr ""
855
 
856
- #: include/class-bulk-delete-posts.php:111
857
- #: include/class-bulk-delete-posts.php:407
858
- #: include/class-bulk-delete-posts.php:640
859
- #: include/class-bulk-delete-posts.php:916
860
- #: include/class-bulk-delete-posts.php:1168
861
- #: include/meta/class-bulk-delete-post-meta.php:139
862
- #: include/misc/class-bulk-delete-jetpack-contact-form-messages.php:119
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
863
  #: tmp_addon/bulk-delete-posts-by-attachment.php:201
864
  #: tmp_addon/bulk-delete-posts-by-content.php:219
865
  #: tmp_addon/bulk-delete-posts-by-custom-field.php:229
866
  #: tmp_addon/bulk-delete-posts-by-title.php:175
867
  #: tmp_addon/bulk-delete-posts-by-user-role.php:153
 
868
  msgid "posts."
869
  msgstr ""
870
 
871
- #: include/class-bulk-delete-posts.php:112
872
- #: include/class-bulk-delete-posts.php:408
873
- #: include/class-bulk-delete-posts.php:641
874
- #: include/class-bulk-delete-posts.php:917
875
- #: include/class-bulk-delete-posts.php:1169
876
- #: include/meta/class-bulk-delete-comment-meta.php:140
877
- #: include/meta/class-bulk-delete-post-meta.php:140
878
- #: include/misc/class-bulk-delete-jetpack-contact-form-messages.php:120
879
- #: tmp_addon/bulk-delete-posts-by-attachment.php:202
880
- #: tmp_addon/bulk-delete-posts-by-content.php:220
881
- #: tmp_addon/bulk-delete-posts-by-custom-field.php:230
882
- #: tmp_addon/bulk-delete-posts-by-duplicate-title.php:172
883
- #: tmp_addon/bulk-delete-posts-by-title.php:176
884
  msgid ""
885
- "Use this option if there are more than 1000 posts and the script timesout."
 
886
  msgstr ""
887
 
888
- #: include/class-bulk-delete-posts.php:176
889
- msgid "Posts with the selected status are scheduled for deletion."
 
 
890
  msgstr ""
891
 
892
- #: include/class-bulk-delete-posts.php:180
893
- msgid "Deleted %d post with the selected post status"
894
- msgid_plural "Deleted %d posts with the selected post status"
895
  msgstr[0] ""
896
  msgstr[1] ""
897
 
898
- #: include/class-bulk-delete-posts.php:314
899
- msgid "Select the post type whose category posts you want to delete"
900
  msgstr ""
901
 
902
- #: include/class-bulk-delete-posts.php:333
903
- msgid "Select the categories whose post you want to delete"
904
  msgstr ""
905
 
906
- #: include/class-bulk-delete-posts.php:334
907
- msgid ""
908
- "Note: The post count below for each category is the total number of posts in "
909
- "that category, irrespective of post type"
910
  msgstr ""
911
 
912
- #: include/class-bulk-delete-posts.php:361
913
- msgid "All Categories"
914
  msgstr ""
915
 
916
- #: include/class-bulk-delete-posts.php:396
917
- #: include/class-bulk-delete-posts.php:629
918
- #: include/class-bulk-delete-posts.php:905
919
- #: tmp_addon/bulk-delete-posts-by-attachment.php:190
920
- #: tmp_addon/bulk-delete-posts-by-content.php:210
921
- #: tmp_addon/bulk-delete-posts-by-custom-field.php:218
922
- #: tmp_addon/bulk-delete-posts-by-title.php:164
923
- msgid "Public posts"
924
  msgstr ""
925
 
926
- #: include/class-bulk-delete-posts.php:397
927
- #: include/class-bulk-delete-posts.php:630
928
- #: include/class-bulk-delete-posts.php:906
929
- #: tmp_addon/bulk-delete-posts-by-attachment.php:191
930
- #: tmp_addon/bulk-delete-posts-by-content.php:211
931
- #: tmp_addon/bulk-delete-posts-by-custom-field.php:219
932
- #: tmp_addon/bulk-delete-posts-by-title.php:165
933
- msgid "Private Posts"
934
  msgstr ""
935
 
936
- #: include/class-bulk-delete-posts.php:434
937
- #: include/class-bulk-delete-users.php:108
938
- #: include/meta/class-bulk-delete-comment-meta.php:168
939
- #: include/meta/class-bulk-delete-post-meta.php:168
940
- #: include/meta/class-bulk-delete-user-meta.php:148
941
- #: tmp_addon/bulk-delete-attachments.php:319
942
- #: tmp_addon/bulk-delete-posts-by-attachment.php:228
943
- #: tmp_addon/bulk-delete-posts-by-content.php:246
944
- #: tmp_addon/bulk-delete-posts-by-custom-field.php:256
945
- #: tmp_addon/bulk-delete-posts-by-duplicate-title.php:198
946
- #: tmp_addon/bulk-delete-posts-by-title.php:202
947
- #: tmp_addon/bulk-delete-posts-by-user-role.php:180
948
- msgid "Enter time in Y-m-d H:i:s format or enter now to use current time"
949
  msgstr ""
950
 
951
- #: include/class-bulk-delete-posts.php:477
952
- msgid "Posts from the selected categories are scheduled for deletion."
953
  msgstr ""
954
 
955
- #: include/class-bulk-delete-posts.php:481
956
- msgid "Deleted %d post from the selected categories"
957
- msgid_plural "Deleted %d posts from the selected categories"
958
- msgstr[0] ""
959
- msgstr[1] ""
960
-
961
- #: include/class-bulk-delete-posts.php:572
962
- msgid "Select the tags whose post you want to delete"
963
  msgstr ""
964
 
965
- #: include/class-bulk-delete-posts.php:596
966
- msgid "All Tags"
 
967
  msgstr ""
968
 
969
- #: include/class-bulk-delete-posts.php:674
970
- msgid "You don't have any posts assigned to tags in this blog."
 
 
971
  msgstr ""
972
 
973
- #: include/class-bulk-delete-posts.php:706
974
- msgid "Posts from the selected tags are scheduled for deletion."
 
 
975
  msgstr ""
976
 
977
- #: include/class-bulk-delete-posts.php:710
978
- msgid "Deleted %d post from the selected tags"
979
- msgid_plural "Deleted %d posts from the selected tags"
980
  msgstr[0] ""
981
  msgstr[1] ""
982
 
983
- #: include/class-bulk-delete-posts.php:812
984
- msgid "Select the post type whose taxonomy posts you want to delete"
985
  msgstr ""
986
 
987
- #: include/class-bulk-delete-posts.php:832
988
- msgid "Select the taxonomies whose post you want to delete"
989
  msgstr ""
990
 
991
- #: include/class-bulk-delete-posts.php:851
992
- msgid ""
993
- "The selected taxonomy has the following terms. Select the terms whose post "
994
- "you want to delete"
995
  msgstr ""
996
 
997
- #: include/class-bulk-delete-posts.php:852
998
- msgid ""
999
- "Note: The post count below for each term is the total number of posts in "
1000
- "that term, irrespective of post type"
1001
  msgstr ""
1002
 
1003
- #: include/class-bulk-delete-posts.php:950
1004
- msgid "You don't have any posts assigned to custom taxonomies in this blog."
1005
  msgstr ""
1006
 
1007
- #: include/class-bulk-delete-posts.php:984
1008
- msgid "Posts from the selected custom taxonomies are scheduled for deletion."
1009
  msgstr ""
1010
 
1011
- #: include/class-bulk-delete-posts.php:988
1012
- msgid "Deleted %d post from the selected custom taxonomies"
1013
- msgid_plural "Deleted %d posts from the selected custom taxonomies"
1014
- msgstr[0] ""
1015
- msgstr[1] ""
1016
-
1017
- #: include/class-bulk-delete-posts.php:1117
1018
- msgid "Select the custom post type whose post you want to delete"
 
 
 
 
 
 
 
 
 
1019
  msgstr ""
1020
 
1021
- #: include/class-bulk-delete-posts.php:1202
1022
- msgid "You don't have any posts assigned to custom post types in this blog."
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1023
  msgstr ""
1024
 
1025
- #: include/class-bulk-delete-posts.php:1235
1026
- msgid "Posts from the selected custom post type are scheduled for deletion."
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1027
  msgstr ""
1028
 
1029
- #: include/class-bulk-delete-posts.php:1239
1030
- msgid "Deleted %d post from the selected custom post type"
1031
- msgid_plural "Deleted %d posts from the selected custom post type"
1032
- msgstr[0] ""
1033
- msgstr[1] ""
1034
-
1035
- #: include/class-bulk-delete-posts.php:1331
1036
- msgid "Delete posts and pages that have the following Permalink"
1037
  msgstr ""
1038
 
1039
- #: include/class-bulk-delete-posts.php:1337
1040
- msgid "Enter one post url (not post ids) per line"
 
 
1041
  msgstr ""
1042
 
1043
- #: include/class-bulk-delete-posts.php:1392
1044
- msgid "Deleted %d post with the specified urls"
1045
- msgid_plural "Deleted %d posts with the specified urls"
1046
  msgstr[0] ""
1047
  msgstr[1] ""
1048
 
1049
- #: include/class-bulk-delete-posts.php:1426
1050
- msgid "All Revisions"
1051
- msgstr ""
1052
-
1053
- #: include/class-bulk-delete-posts.php:1426
1054
- msgid "Revisions"
1055
  msgstr ""
1056
 
1057
- #: include/class-bulk-delete-posts.php:1450
1058
- msgid "Deleted %d post revision"
1059
- msgid_plural "Deleted %d post revisions"
1060
- msgstr[0] ""
1061
- msgstr[1] ""
1062
-
1063
- #: include/class-bulk-delete-posts.php:1500
1064
- msgid ""
1065
- "You need \"Bulk Delete Posts by Custom Field\" Addon, to delete post by "
1066
- "custom field."
1067
  msgstr ""
1068
 
1069
- #: include/class-bulk-delete-posts.php:1529
1070
- msgid "You need \"Bulk Delete Posts by Title\" Addon, to delete post by title."
1071
  msgstr ""
1072
 
1073
- #: include/class-bulk-delete-posts.php:1559
1074
- msgid ""
1075
- "You need \"Bulk Delete Posts by Duplicate Title\" Addon, to delete post by "
1076
- "duplicate title."
1077
  msgstr ""
1078
 
1079
- #: include/class-bulk-delete-posts.php:1587
1080
- msgid ""
1081
- "You need \"Bulk Delete Posts by User Role\" Addon, to delete post based on "
1082
- "User Role"
 
 
1083
  msgstr ""
1084
 
1085
- #: include/class-bulk-delete-posts.php:1615
1086
- msgid "You need \"Bulk Delete From Trash\" Addon, to delete post in Trash."
1087
  msgstr ""
1088
 
1089
- #: include/class-bulk-delete-posts.php:1640
1090
- msgid ""
1091
- "Are you sure you want to delete all the posts based on the selected option?"
1092
  msgstr ""
1093
 
1094
- #: include/class-bulk-delete-posts.php:1641
1095
- msgid "Please select posts from at least one option"
1096
  msgstr ""
1097
 
1098
- #: include/class-bulk-delete-posts.php:1645
1099
- msgid "Please enter at least one post url"
1100
  msgstr ""
1101
 
1102
- #: include/class-bulk-delete-posts.php:1669
1103
- msgid "The selected scheduled job was successfully deleted "
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1104
  msgstr ""
1105
 
1106
- #: include/class-bulk-delete-system-info.php:59
1107
- msgid "System Information"
1108
  msgstr ""
1109
 
1110
- #: include/class-bulk-delete-system-info.php:68
1111
- msgid "Please include this information when posting support requests."
1112
  msgstr ""
1113
 
1114
- #: include/class-bulk-delete-system-info.php:78
1115
  msgid ""
1116
- "To copy the system info, click below then press Ctrl + C (PC) or Cmd + C "
1117
- "(Mac)."
1118
- msgstr ""
1119
-
1120
- #: include/class-bulk-delete-users.php:22
1121
- msgid "Select the user roles from which you want to delete users"
1122
- msgstr ""
1123
-
1124
- #: include/class-bulk-delete-users.php:33
1125
- #: include/meta/class-bulk-delete-user-meta.php:65
1126
- #: tmp_addon/bulk-delete-posts-by-user-role.php:96
1127
- msgid "Users"
1128
- msgstr ""
1129
-
1130
- #: include/class-bulk-delete-users.php:55
1131
- msgid "Only restrict to users who have not logged in the last "
1132
  msgstr ""
1133
 
1134
- #: include/class-bulk-delete-users.php:61
1135
- msgid "Need Simple Login Log Plugin"
1136
  msgstr ""
1137
 
1138
- #: include/class-bulk-delete-users.php:72
1139
- msgid ""
1140
- "Only if user doesn't have any post. Only posts from 'post' post type would "
1141
- "be considered."
1142
- msgstr ""
1143
 
1144
- #: include/class-bulk-delete-users.php:81
1145
- #: include/meta/class-bulk-delete-user-meta.php:119
1146
- msgid "users."
1147
  msgstr ""
1148
 
1149
- #: include/class-bulk-delete-users.php:82
1150
- msgid ""
1151
- "Use this option if there are more than 1000 users or the script timesout."
1152
  msgstr ""
1153
 
1154
- #: include/class-bulk-delete-users.php:148
1155
- msgid "Users from the selected userrole are scheduled for deletion."
1156
  msgstr ""
1157
 
1158
- #: include/class-bulk-delete-users.php:152
1159
- msgid "Deleted %d user from the selected roles"
1160
- msgid_plural "Deleted %d users from the selected role"
1161
- msgstr[0] ""
1162
- msgstr[1] ""
1163
-
1164
- #: include/class-bulk-delete-users.php:224
1165
- msgid ""
1166
- "Are you sure you want to delete all the users from the selected user role?"
1167
  msgstr ""
1168
 
1169
- #: include/class-bulk-delete-users.php:227
1170
- msgid "Select at least one user role from which users should be deleted"
1171
  msgstr ""
1172
 
1173
- #: include/class-bulk-delete-util.php:125
1174
- msgctxt "Cron table date format"
1175
- msgid "M j, Y @ G:i"
1176
  msgstr ""
1177
-
1178
- #: include/class-cron-list-table.php:32
1179
- msgid ""
1180
- "This is the list of jobs that are currently scheduled for auto deleting "
1181
- "posts in Bulk Delete Plugin."
1182
  msgstr ""
1183
 
1184
- #: include/class-cron-list-table.php:40
1185
- msgid "Note: "
1186
  msgstr ""
1187
 
1188
- #: include/class-cron-list-table.php:42
1189
- msgid ""
1190
- "Scheduling auto post or user deletion is available only when you buy pro "
1191
- "addons."
1192
  msgstr ""
1193
 
1194
- #: include/class-cron-list-table.php:55
1195
- msgid "Next Due"
1196
  msgstr ""
1197
 
1198
- #: include/class-cron-list-table.php:57
1199
- msgid "Type"
1200
  msgstr ""
1201
 
1202
- #: include/class-cron-list-table.php:58
1203
- msgid "Options"
1204
  msgstr ""
1205
 
1206
- #: include/class-cron-list-table.php:112
1207
- #: include/class-license-list-table.php:90
1208
- msgid "Delete"
 
 
 
 
 
1209
  msgstr ""
1210
 
1211
- #: include/class-cron-list-table.php:138
1212
- msgid "You have not scheduled any bulk delete jobs."
1213
  msgstr ""
1214
 
1215
- #: include/class-license-list-table.php:35
1216
  msgid ""
1217
- "This is the list of addon license that are currently registered with the "
1218
- "plugin."
1219
  msgstr ""
1220
 
1221
- #: include/class-license-list-table.php:48
1222
- msgid "Addon Name"
1223
  msgstr ""
1224
 
1225
- #: include/class-license-list-table.php:49
1226
- msgid "License Code"
 
 
 
 
 
 
1227
  msgstr ""
1228
 
1229
- #: include/class-license-list-table.php:50
1230
- msgid "Validity"
 
 
 
 
 
 
1231
  msgstr ""
1232
 
1233
- #: include/class-license-list-table.php:51
1234
- msgid "Expires"
1235
  msgstr ""
1236
 
1237
- #: include/class-license-list-table.php:94
1238
- msgid "Deactivate"
 
 
 
 
 
 
1239
  msgstr ""
1240
 
1241
- #: include/class-license-list-table.php:152
1242
- msgid "N/A"
1243
  msgstr ""
1244
 
1245
- #: include/class-license-list-table.php:162
1246
- msgid "You don't have any valid addon license yet."
1247
  msgstr ""
1248
 
1249
- #: include/meta/class-bulk-delete-comment-meta.php:35
1250
- msgid "Bulk Delete Comment Meta"
1251
  msgstr ""
1252
 
1253
- #: include/meta/class-bulk-delete-comment-meta.php:65
1254
- msgid "Select the post type whose comment meta fields you want to delete"
 
 
 
 
 
 
1255
  msgstr ""
1256
 
1257
- #: include/meta/class-bulk-delete-comment-meta.php:81
1258
- msgid "Choose your comment meta field settings"
1259
  msgstr ""
1260
 
1261
- #: include/meta/class-bulk-delete-comment-meta.php:86
1262
- msgid "Delete based on comment meta key name only"
 
 
1263
  msgstr ""
1264
 
1265
- #: include/meta/class-bulk-delete-comment-meta.php:93
1266
- msgid "Delete based on comment meta key name and value"
 
 
1267
  msgstr ""
1268
 
1269
- #: include/meta/class-bulk-delete-comment-meta.php:102
1270
- msgid "Comment Meta Key "
1271
  msgstr ""
1272
 
1273
- #: include/meta/class-bulk-delete-comment-meta.php:103
1274
- #: include/meta/class-bulk-delete-post-meta.php:103
1275
- #: include/meta/class-bulk-delete-user-meta.php:95
1276
- msgid "Meta Key"
1277
  msgstr ""
1278
 
1279
- #: include/meta/class-bulk-delete-comment-meta.php:119
1280
- #: include/meta/class-bulk-delete-post-meta.php:119
1281
- #: include/meta/class-bulk-delete-user-meta.php:111
1282
- #: include/misc/class-bulk-delete-jetpack-contact-form-messages.php:126
1283
- msgid "Choose your deletion options"
 
 
 
1284
  msgstr ""
1285
 
1286
- #: include/meta/class-bulk-delete-comment-meta.php:126
1287
- msgid "Only restrict to comments which are "
1288
  msgstr ""
1289
 
1290
- #: include/meta/class-bulk-delete-comment-meta.php:129
1291
- msgid "commented within last"
1292
  msgstr ""
1293
 
1294
- #: include/meta/class-bulk-delete-comment-meta.php:138
1295
- msgid "Only delete comment meta field from first "
 
 
 
 
 
 
1296
  msgstr ""
1297
 
1298
- #: include/meta/class-bulk-delete-comment-meta.php:139
1299
- msgid "comments."
1300
  msgstr ""
1301
 
1302
- #: include/meta/class-bulk-delete-comment-meta.php:195
1303
- msgid ""
1304
- "Are you sure you want to delete all the comment meta fields that match the "
1305
- "selected filters?"
 
 
 
 
1306
  msgstr ""
1307
 
1308
- #: include/meta/class-bulk-delete-comment-meta.php:236
1309
- msgid ""
1310
- "Comment meta fields from the comments with the selected criteria are "
1311
- "scheduled for deletion."
1312
  msgstr ""
1313
 
1314
- #: include/meta/class-bulk-delete-comment-meta.php:240
1315
- msgid "Deleted comment meta field from %d comment"
1316
- msgid_plural "Deleted comment meta field from %d comments"
1317
  msgstr[0] ""
1318
  msgstr[1] ""
1319
 
1320
- #: include/meta/class-bulk-delete-meta.php:35
1321
- #: include/meta/class-bulk-delete-meta.php:36
1322
- #: include/meta/class-bulk-delete-meta.php:98
1323
- msgid "Bulk Delete Meta Fields"
1324
  msgstr ""
1325
 
1326
- #: include/meta/class-bulk-delete-meta.php:113
1327
- #: tmp_addon/bulk-delete-attachments.php:193
1328
- msgid "WARNING: Items deleted once cannot be retrieved back. Use with caution."
1329
  msgstr ""
1330
 
1331
- #: include/meta/class-bulk-delete-post-meta.php:35
1332
- msgid "Bulk Delete Post Meta"
 
 
1333
  msgstr ""
1334
 
1335
- #: include/meta/class-bulk-delete-post-meta.php:65
1336
- msgid "Select the post type whose post meta fields you want to delete"
 
 
1337
  msgstr ""
1338
 
1339
- #: include/meta/class-bulk-delete-post-meta.php:81
1340
- msgid "Choose your post meta field settings"
1341
  msgstr ""
1342
 
1343
- #: include/meta/class-bulk-delete-post-meta.php:86
1344
- msgid "Delete based on post meta key name only"
 
1345
  msgstr ""
1346
 
1347
- #: include/meta/class-bulk-delete-post-meta.php:93
1348
- msgid "Delete based on post meta key name and value"
1349
  msgstr ""
1350
 
1351
- #: include/meta/class-bulk-delete-post-meta.php:102
1352
- msgid "Post Meta Key "
1353
  msgstr ""
1354
 
1355
- #: include/meta/class-bulk-delete-post-meta.php:138
1356
- msgid "Only delete post meta field from first "
1357
  msgstr ""
1358
 
1359
- #: include/meta/class-bulk-delete-post-meta.php:195
1360
- msgid ""
1361
- "Are you sure you want to delete all the post meta fields that match the "
1362
- "selected filters?"
1363
  msgstr ""
1364
 
1365
- #: include/meta/class-bulk-delete-post-meta.php:236
1366
- msgid ""
1367
- "Post meta fields from the posts with the selected criteria are scheduled for "
1368
- "deletion."
1369
  msgstr ""
1370
 
1371
- #: include/meta/class-bulk-delete-post-meta.php:240
1372
- msgid "Deleted post meta field from %d post"
1373
- msgid_plural "Deleted post meta field from %d posts"
1374
- msgstr[0] ""
1375
- msgstr[1] ""
1376
 
1377
- #: include/meta/class-bulk-delete-user-meta.php:35
1378
- msgid "Bulk Delete User Meta"
 
 
1379
  msgstr ""
1380
 
1381
- #: include/meta/class-bulk-delete-user-meta.php:56
1382
- msgid "Select the user role whose user meta fields you want to delete"
1383
  msgstr ""
1384
 
1385
- #: include/meta/class-bulk-delete-user-meta.php:73
1386
- msgid "Choose your user meta field settings"
1387
  msgstr ""
1388
 
1389
- #: include/meta/class-bulk-delete-user-meta.php:78
1390
- msgid "Delete based on user meta key name only"
1391
  msgstr ""
1392
 
1393
- #: include/meta/class-bulk-delete-user-meta.php:85
1394
- msgid "Delete based on user meta key name and value"
1395
  msgstr ""
1396
 
1397
- #: include/meta/class-bulk-delete-user-meta.php:94
1398
- msgid "User Meta Key "
1399
  msgstr ""
1400
 
1401
- #: include/meta/class-bulk-delete-user-meta.php:118
1402
- msgid "Only delete user meta field from first "
 
 
 
 
 
 
1403
  msgstr ""
1404
 
1405
- #: include/meta/class-bulk-delete-user-meta.php:120
1406
  msgid ""
1407
- "Use this option if there are more than 1000 users and the script timesout."
 
1408
  msgstr ""
1409
 
1410
- #: include/meta/class-bulk-delete-user-meta.php:175
1411
  msgid ""
1412
- "Are you sure you want to delete all the user meta fields that match the "
1413
- "selected filters?"
1414
  msgstr ""
1415
 
1416
- #: include/meta/class-bulk-delete-user-meta.php:212
1417
  msgid ""
1418
- "User meta fields from the users with the selected criteria are scheduled for "
1419
- "deletion."
1420
  msgstr ""
1421
 
1422
- #: include/meta/class-bulk-delete-user-meta.php:216
1423
- msgid "Deleted user meta field from %d user"
1424
- msgid_plural "Deleted user meta field from %d users"
1425
- msgstr[0] ""
1426
- msgstr[1] ""
1427
 
1428
- #: include/misc/class-bulk-delete-jetpack-contact-form-messages.php:29
1429
- msgid "Bulk Delete Jetpack Contact Form Messages"
1430
  msgstr ""
1431
 
1432
- #: include/misc/class-bulk-delete-jetpack-contact-form-messages.php:53
1433
- msgid "Jetpack contact form is not enabled."
 
 
1434
  msgstr ""
1435
 
1436
- #: include/misc/class-bulk-delete-jetpack-contact-form-messages.php:69
1437
- msgid "Delete all Contact Form Messages"
1438
  msgstr ""
1439
 
1440
- #: include/misc/class-bulk-delete-jetpack-contact-form-messages.php:69
1441
- msgid "in total"
1442
  msgstr ""
1443
 
1444
- #: include/misc/class-bulk-delete-jetpack-contact-form-messages.php:78
1445
- msgid "Delete Messages based on filters"
 
 
1446
  msgstr ""
1447
 
1448
- #: include/misc/class-bulk-delete-jetpack-contact-form-messages.php:95
1449
- msgid "Choose your date options"
 
 
 
 
 
 
 
 
1450
  msgstr ""
1451
 
1452
- #: include/misc/class-bulk-delete-jetpack-contact-form-messages.php:180
1453
  msgid ""
1454
- "Are you sure you want to delete all the Jetpack contact form messages based "
1455
- "on the selected filters?"
1456
  msgstr ""
1457
 
1458
- #: include/misc/class-bulk-delete-jetpack-contact-form-messages.php:219
1459
  msgid ""
1460
- "Jetpack contact form messages with the selected criteria are scheduled for "
1461
- "deletion."
1462
  msgstr ""
1463
 
1464
- #: include/misc/class-bulk-delete-jetpack-contact-form-messages.php:223
1465
- msgid "Deleted %d Jetpack contact form message"
1466
- msgid_plural "Deleted %d Jetpack contact form messages"
 
 
 
 
1467
  msgstr[0] ""
1468
  msgstr[1] ""
1469
 
1470
- #: include/misc/class-bulk-delete-misc.php:32
1471
- #: include/misc/class-bulk-delete-misc.php:95
1472
- msgid "Bulk Delete Miscellaneous Items"
1473
- msgstr ""
1474
-
1475
- #: include/misc/class-bulk-delete-misc.php:33
1476
- msgid "Bulk Delete Misc"
1477
  msgstr ""
1478
 
1479
- #: include/settings/class-bd-settings-page.php:44
1480
- #: include/settings/class-bd-settings-page.php:89
1481
- msgid "Bulk Delete Settings"
1482
  msgstr ""
1483
 
1484
- #: include/settings/class-bd-settings-page.php:45
1485
- msgid "Settings"
 
1486
  msgstr ""
1487
 
1488
  #: tmp_addon/bulk-delete-attachments.php:118
@@ -1542,7 +1569,8 @@ msgstr[1] ""
1542
  #: tmp_addon/bulk-delete-posts-by-custom-field.php:501
1543
  #: tmp_addon/bulk-delete-posts-by-duplicate-title.php:354
1544
  #: tmp_addon/bulk-delete-posts-by-title.php:410
1545
- #: tmp_addon/bulk-delete-posts-by-user-role.php:326
 
1546
  #: tmp_addon/bulk-delete-scheduler-email.php:335
1547
  #: tmp_addon/bulk-delete-scheduler-for-deleting-attachments.php:112
1548
  #: tmp_addon/bulk-delete-scheduler-for-deleting-pages-by-status.php:108
@@ -1556,6 +1584,7 @@ msgstr[1] ""
1556
  #: tmp_addon/bulk-delete-scheduler-for-deleting-posts-by-tag.php:108
1557
  #: tmp_addon/bulk-delete-scheduler-for-deleting-posts-by-taxonomy.php:103
1558
  #: tmp_addon/bulk-delete-scheduler-for-deleting-posts-by-user-role.php:108
 
1559
  #: tmp_addon/bulk-delete-scheduler-for-deleting-users-by-role.php:108
1560
  #: tmp_addon/bulk-delete-user-meta.php:213
1561
  msgid ""
@@ -2063,10 +2092,12 @@ msgid "Select the user roles from which you want to delete posts"
2063
  msgstr ""
2064
 
2065
  #: tmp_addon/bulk-delete-posts-by-user-role.php:104
 
2066
  msgid "Select the post types from which you want to delete posts"
2067
  msgstr ""
2068
 
2069
  #: tmp_addon/bulk-delete-posts-by-user-role.php:154
 
2070
  msgid ""
2071
  "Use this option if there are more than 1000 posts or the script timesout."
2072
  msgstr ""
@@ -2081,16 +2112,39 @@ msgid_plural "Deleted %d posts from selected user roles"
2081
  msgstr[0] ""
2082
  msgstr[1] ""
2083
 
2084
- #: tmp_addon/bulk-delete-posts-by-user-role.php:306
2085
  msgid ""
2086
  "Are you sure you want to delete all the posts that belong to the selected "
2087
  "user role?"
2088
  msgstr ""
2089
 
2090
- #: tmp_addon/bulk-delete-posts-by-user-role.php:309
2091
  msgid "Please select the user role from which you want to delete posts"
2092
  msgstr ""
2093
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2094
  #: tmp_addon/bulk-delete-scheduler-email.php:91
2095
  msgid "Scheduler Email Settings"
2096
  msgstr ""
2
  # This file is distributed under the same license as the Bulk Delete package.
3
  msgid ""
4
  msgstr ""
5
+ "Project-Id-Version: Bulk Delete 5.4.2\n"
6
  "Report-Msgid-Bugs-To: http://wordpress.org/tag/bulk-delete\n"
7
+ "POT-Creation-Date: 2015-03-03 16:01:26+00:00\n"
8
  "MIME-Version: 1.0\n"
9
  "Content-Type: text/plain; charset=UTF-8\n"
10
  "Content-Transfer-Encoding: 8bit\n"
12
  "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
13
  "Language-Team: LANGUAGE <LL@li.org>\n"
14
 
15
+ #: bulk-delete.php:172 bulk-delete.php:184
16
  msgid "Cheatin&#8217; huh?"
17
  msgstr ""
18
 
19
+ #: bulk-delete.php:269
20
  msgid "Bulk WP"
21
  msgstr ""
22
 
23
+ #: bulk-delete.php:271 bulk-delete.php:483 include/ui/admin-ui.php:52
24
  msgid "Bulk Delete Posts"
25
  msgstr ""
26
 
27
+ #: bulk-delete.php:272 bulk-delete.php:535
28
  msgid "Bulk Delete Pages"
29
  msgstr ""
30
 
31
+ #: bulk-delete.php:273 bulk-delete.php:586 include/ui/admin-ui.php:49
32
  msgid "Bulk Delete Users"
33
  msgstr ""
34
 
35
+ #: bulk-delete.php:293 bulk-delete.php:647
36
  msgid "Bulk Delete Schedules"
37
  msgstr ""
38
 
39
+ #: bulk-delete.php:293
40
  msgid "Scheduled Jobs"
41
  msgstr ""
42
 
43
+ #: bulk-delete.php:294 include/license/class-bd-license.php:32
44
  msgid "Addon Licenses"
45
  msgstr ""
46
 
47
+ #: bulk-delete.php:295
48
  msgid "Bulk Delete System Info"
49
  msgstr ""
50
 
51
+ #: bulk-delete.php:295
52
  msgid "System Info"
53
  msgstr ""
54
 
55
+ #: bulk-delete.php:347
56
  msgid "By Post Status"
57
  msgstr ""
58
 
59
+ #: bulk-delete.php:348
60
  msgid "By Category"
61
  msgstr ""
62
 
63
+ #: bulk-delete.php:349
64
  msgid "By Tag"
65
  msgstr ""
66
 
67
+ #: bulk-delete.php:350
68
  msgid "By Custom Taxonomy"
69
  msgstr ""
70
 
71
+ #: bulk-delete.php:351
72
  msgid "By Custom Post Types"
73
  msgstr ""
74
 
75
+ #: bulk-delete.php:352
76
  msgid "By URL"
77
  msgstr ""
78
 
79
+ #: bulk-delete.php:353
80
  msgid "By Post Revision"
81
  msgstr ""
82
 
83
+ #: bulk-delete.php:354
84
  msgid "By Custom Field"
85
  msgstr ""
86
 
87
+ #: bulk-delete.php:355
88
  msgid "By Title"
89
  msgstr ""
90
 
91
+ #: bulk-delete.php:356
92
  msgid "By Duplicate Title"
93
  msgstr ""
94
 
95
+ #: bulk-delete.php:357 bulk-delete.php:431
96
  msgid "By User Role"
97
  msgstr ""
98
 
99
+ #: bulk-delete.php:358 tmp_addon/bulk-delete-from-trash.php:151
100
  msgid "Posts in Trash"
101
  msgstr ""
102
 
103
+ #: bulk-delete.php:396
104
  msgid "By Page status"
105
  msgstr ""
106
 
107
+ #: bulk-delete.php:397
108
  msgid "Pages in Trash"
109
  msgstr ""
110
 
111
+ #: bulk-delete.php:499 include/misc/class-bulk-delete-misc.php:113
112
  msgid "WARNING: Posts deleted once cannot be retrieved back. Use with caution."
113
  msgstr ""
114
 
115
+ #: bulk-delete.php:551
116
  msgid "WARNING: Pages deleted once cannot be retrieved back. Use with caution."
117
  msgstr ""
118
 
119
+ #: bulk-delete.php:602
120
  msgid "WARNING: Users deleted once cannot be retrieved back. Use with caution."
121
  msgstr ""
122
 
123
+ #: include/cron/class-cron-list-table.php:33
124
  msgid ""
125
+ "This is the list of jobs that are currently scheduled for auto deleting "
126
+ "posts in Bulk Delete Plugin."
127
  msgstr ""
128
 
129
+ #: include/cron/class-cron-list-table.php:41
130
+ msgid "Note: "
131
+ msgstr ""
132
+
133
+ #: include/cron/class-cron-list-table.php:43
134
+ msgid ""
135
+ "Scheduling auto post or user deletion is available only when you buy pro "
136
+ "addons."
137
+ msgstr ""
138
+
139
+ #: include/cron/class-cron-list-table.php:57
140
+ msgid "Next Due"
141
+ msgstr ""
142
+
143
+ #: include/cron/class-cron-list-table.php:58
144
+ #: include/meta/class-bulk-delete-comment-meta.php:150
145
+ #: include/meta/class-bulk-delete-post-meta.php:150
146
+ #: include/meta/class-bulk-delete-user-meta.php:130
147
+ #: include/misc/class-bulk-delete-jetpack-contact-form-messages.php:141
148
+ #: include/pages/class-bulk-delete-pages.php:111
149
+ #: include/posts/class-bulk-delete-posts.php:120
150
+ #: include/posts/class-bulk-delete-posts.php:414
151
+ #: include/posts/class-bulk-delete-posts.php:637
152
+ #: include/posts/class-bulk-delete-posts.php:914
153
+ #: include/posts/class-bulk-delete-posts.php:1163
154
+ #: include/users/class-bulk-delete-users.php:90
155
+ #: tmp_addon/bulk-delete-attachments.php:300
156
+ #: tmp_addon/bulk-delete-posts-by-attachment.php:209
157
+ #: tmp_addon/bulk-delete-posts-by-content.php:227
158
+ #: tmp_addon/bulk-delete-posts-by-custom-field.php:237
159
+ #: tmp_addon/bulk-delete-posts-by-duplicate-title.php:179
160
+ #: tmp_addon/bulk-delete-posts-by-title.php:183
161
+ #: tmp_addon/bulk-delete-posts-by-user-role.php:161
162
+ #: tmp_addon/bulk-delete-posts-by-user.php:205
163
+ msgid "Schedule"
164
  msgstr ""
165
 
166
+ #: include/cron/class-cron-list-table.php:59
167
+ msgid "Type"
168
+ msgstr ""
169
+
170
+ #: include/cron/class-cron-list-table.php:60
171
+ msgid "Options"
172
+ msgstr ""
173
+
174
+ #: include/cron/class-cron-list-table.php:119
175
+ #: include/license/class-license-list-table.php:93
176
+ msgid "Delete"
177
+ msgstr ""
178
+
179
+ #: include/cron/class-cron-list-table.php:160
180
+ msgid "You have not scheduled any bulk delete jobs."
181
+ msgstr ""
182
+
183
+ #: include/license/class-bd-license-handler.php:141
184
  msgid "Addon License Key"
185
  msgstr ""
186
 
187
+ #: include/license/class-bd-license-handler.php:161
188
  msgid "Enter license key"
189
  msgstr ""
190
 
191
+ #: include/license/class-bd-license.php:65
192
  msgid "Activate License"
193
  msgstr ""
194
 
195
+ #: include/license/class-bd-license.php:191
196
  msgid "The license key for \"%s\" addon was successfully deactivated"
197
  msgstr ""
198
 
199
+ #: include/license/class-bd-license.php:196
200
  msgid ""
201
  "There was some problem while trying to deactivate license key for \"%s\" "
202
  "addon. Kindly try again"
203
  msgstr ""
204
 
205
+ #: include/license/class-bd-license.php:221
206
  msgid "The license key was successfully deleted"
207
  msgstr ""
208
 
209
+ #: include/license/class-bd-license.php:265
210
  msgid ""
211
  "There was some problem in contacting our store to activate the license key "
212
  "for \"%s\" addon"
213
  msgstr ""
214
 
215
+ #: include/license/class-bd-license.php:275
216
  msgid ""
217
  "The license key for \"%s\" addon was successfully activated. The addon will "
218
  "get updates automatically till the license key is valid."
219
  msgstr ""
220
 
221
+ #: include/license/class-bd-license.php:283
222
  msgid ""
223
  "The license key for \"%s\" addon doesn't have any more activations left. "
224
  "Kindly buy a new license."
225
  msgstr ""
226
 
227
+ #: include/license/class-bd-license.php:287
228
  msgid "The license key for \"%s\" addon is revoked. Kindly buy a new license."
229
  msgstr ""
230
 
231
+ #: include/license/class-bd-license.php:291
232
  msgid "The license key for \"%s\" addon has expired. Kindly buy a new license."
233
  msgstr ""
234
 
235
+ #: include/license/class-bd-license.php:295
236
  msgid "The license key for \"%s\" addon is invalid"
237
  msgstr ""
238
 
239
+ #: include/license/class-bd-license.php:357
240
  msgid ""
241
  "The following are the list of pro addons that are currently available for "
242
  "purchase."
243
  msgstr ""
244
 
245
+ #: include/license/class-bd-license.php:363
246
  msgid "Delete posts by custom field"
247
  msgstr ""
248
 
249
+ #: include/license/class-bd-license.php:364
250
  msgid "Adds the ability to delete posts based on custom fields"
251
  msgstr ""
252
 
253
+ #: include/license/class-bd-license.php:365
254
+ #: include/license/class-bd-license.php:371
255
+ #: include/license/class-bd-license.php:377
256
+ #: include/license/class-bd-license.php:383
257
+ #: include/license/class-bd-license.php:389
258
+ #: include/license/class-bd-license.php:395
259
+ #: include/license/class-bd-license.php:401
260
+ #: include/license/class-bd-license.php:407
261
+ #: include/license/class-bd-license.php:413
262
+ #: include/license/class-bd-license.php:419
263
+ #: include/license/class-bd-license.php:425
264
+ #: include/license/class-bd-license.php:431
265
+ #: include/license/class-bd-license.php:437
266
+ #: include/license/class-bd-license.php:443
267
+ #: include/license/class-bd-license.php:449
268
+ #: include/license/class-bd-license.php:455
269
+ #: include/license/class-bd-license.php:461
270
+ #: include/license/class-bd-license.php:467
271
  msgid "More Info"
272
  msgstr ""
273
 
274
+ #: include/license/class-bd-license.php:369
275
  msgid "Delete posts by title"
276
  msgstr ""
277
 
278
+ #: include/license/class-bd-license.php:370
279
  msgid "Adds the ability to delete posts based on title"
280
  msgstr ""
281
 
282
+ #: include/license/class-bd-license.php:375
283
  msgid "Delete posts by duplicate title"
284
  msgstr ""
285
 
286
+ #: include/license/class-bd-license.php:376
287
  msgid "Adds the ability to delete posts based on duplicate title"
288
  msgstr ""
289
 
290
+ #: include/license/class-bd-license.php:381
291
  msgid "Delete posts by attachment"
292
  msgstr ""
293
 
294
+ #: include/license/class-bd-license.php:382
295
  msgid ""
296
  "Adds the ability to delete posts based on whether it contains attachment or "
297
  "not"
298
  msgstr ""
299
 
300
+ #: include/license/class-bd-license.php:387
301
  msgid "Delete posts by user role"
302
  msgstr ""
303
 
304
+ #: include/license/class-bd-license.php:388
305
  msgid "Adds the ability to delete posts based on user role"
306
  msgstr ""
307
 
308
+ #: include/license/class-bd-license.php:393
309
  msgid "Delete from trash"
310
  msgstr ""
311
 
312
+ #: include/license/class-bd-license.php:394
313
  msgid "Adds the ability to delete posts and pages from trash"
314
  msgstr ""
315
 
316
+ #: include/license/class-bd-license.php:399
317
  msgid "Scheduler Email"
318
  msgstr ""
319
 
320
+ #: include/license/class-bd-license.php:400
321
  msgid "Sends an email every time a Bulk WP scheduler runs"
322
  msgstr ""
323
 
324
+ #: include/license/class-bd-license.php:405
325
  msgid "Scheduler for deleting Posts by Category"
326
  msgstr ""
327
 
328
+ #: include/license/class-bd-license.php:406
329
  msgid "Adds the ability to schedule auto delete of posts based on category"
330
  msgstr ""
331
 
332
+ #: include/license/class-bd-license.php:411
333
  msgid "Scheduler for deleting Posts by Tag"
334
  msgstr ""
335
 
336
+ #: include/license/class-bd-license.php:412
337
  msgid "Adds the ability to schedule auto delete of posts based on tag"
338
  msgstr ""
339
 
340
+ #: include/license/class-bd-license.php:417
341
  msgid "Scheduler for deleting Posts by Custom Taxonomy"
342
  msgstr ""
343
 
344
+ #: include/license/class-bd-license.php:418
345
  msgid ""
346
  "Adds the ability to schedule auto delete of posts based on custom taxonomy"
347
  msgstr ""
348
 
349
+ #: include/license/class-bd-license.php:423
350
  msgid "Scheduler for deleting Posts by Custom Post Type"
351
  msgstr ""
352
 
353
+ #: include/license/class-bd-license.php:424
354
  msgid ""
355
  "Adds the ability to schedule auto delete of posts based on custom post type"
356
  msgstr ""
357
 
358
+ #: include/license/class-bd-license.php:429
359
  msgid "Scheduler for deleting Posts by Post Status"
360
  msgstr ""
361
 
362
+ #: include/license/class-bd-license.php:430
363
  msgid ""
364
  "Adds the ability to schedule auto delete of posts based on post status like "
365
  "drafts, pending posts, scheduled posts etc."
366
  msgstr ""
367
 
368
+ #: include/license/class-bd-license.php:435
369
  msgid "Scheduler for deleting Pages by Status"
370
  msgstr ""
371
 
372
+ #: include/license/class-bd-license.php:436
373
  msgid "Adds the ability to schedule auto delete pages based on status"
374
  msgstr ""
375
 
376
+ #: include/license/class-bd-license.php:441
377
  msgid "Scheduler for deleting Users by User Role"
378
  msgstr ""
379
 
380
+ #: include/license/class-bd-license.php:442
381
  msgid "Adds the ability to schedule auto delete of users based on user role"
382
  msgstr ""
383
 
384
+ #: include/license/class-bd-license.php:447
385
  msgid "Delete Post Meta Fields"
386
  msgstr ""
387
 
388
+ #: include/license/class-bd-license.php:448
389
  msgid ""
390
  "Adds the ability to delete post meta fields based on value and to schedule "
391
  "automatic deletion"
392
  msgstr ""
393
 
394
+ #: include/license/class-bd-license.php:453
395
  msgid "Delete Comment Meta Fields"
396
  msgstr ""
397
 
398
+ #: include/license/class-bd-license.php:454
399
  msgid ""
400
  "Adds the ability to delete comment meta fields based on value and to "
401
  "schedule automatic deletion"
402
  msgstr ""
403
 
404
+ #: include/license/class-bd-license.php:459
405
  msgid "Delete User Meta Fields"
406
  msgstr ""
407
 
408
+ #: include/license/class-bd-license.php:460
409
  msgid ""
410
  "Adds the ability to delete user meta fields based on value and to schedule "
411
  "automatic deletion"
412
  msgstr ""
413
 
414
+ #: include/license/class-bd-license.php:465
415
  msgid "Delete Jetpack Contact Form Messages"
416
  msgstr ""
417
 
418
+ #: include/license/class-bd-license.php:466
419
  msgid ""
420
  "Adds the ability to delete Jetpack Contact Form Messages based on filters "
421
  "and to schedule automatic deletion"
422
  msgstr ""
423
 
424
+ #: include/license/class-license-list-table.php:37
425
+ msgid ""
426
+ "This is the list of addon license that are currently registered with the "
427
+ "plugin."
 
 
 
 
 
 
 
 
 
 
 
 
 
 
428
  msgstr ""
429
 
430
+ #: include/license/class-license-list-table.php:50
431
+ msgid "Addon Name"
432
  msgstr ""
433
 
434
+ #: include/license/class-license-list-table.php:51
435
+ msgid "License Code"
 
 
436
  msgstr ""
437
 
438
+ #: include/license/class-license-list-table.php:52
439
+ msgid "Validity"
 
 
440
  msgstr ""
441
 
442
+ #: include/license/class-license-list-table.php:53
443
+ msgid "Expires"
 
 
444
  msgstr ""
445
 
446
+ #: include/license/class-license-list-table.php:97
447
+ msgid "Deactivate"
 
 
448
  msgstr ""
449
 
450
+ #: include/license/class-license-list-table.php:158
451
+ msgid "N/A"
452
  msgstr ""
453
 
454
+ #: include/license/class-license-list-table.php:168
455
+ msgid "You don't have any valid addon license yet."
456
  msgstr ""
457
 
458
+ #: include/meta/class-bulk-delete-comment-meta.php:38
459
+ msgid "Bulk Delete Comment Meta"
 
 
460
  msgstr ""
461
 
462
+ #: include/meta/class-bulk-delete-comment-meta.php:53
463
+ #: include/meta/class-bulk-delete-post-meta.php:53
464
+ #: include/meta/class-bulk-delete-user-meta.php:53
465
+ #: include/misc/class-bulk-delete-jetpack-contact-form-messages.php:45
466
+ #: include/pages/class-bulk-delete-pages.php:23
467
+ #: include/pages/class-bulk-delete-pages.php:264
468
+ #: include/posts/class-bulk-delete-posts.php:18
469
+ #: include/posts/class-bulk-delete-posts.php:301
470
+ #: include/posts/class-bulk-delete-posts.php:554
471
+ #: include/posts/class-bulk-delete-posts.php:772
472
+ #: include/posts/class-bulk-delete-posts.php:1069
473
+ #: include/posts/class-bulk-delete-posts.php:1311
474
+ #: include/posts/class-bulk-delete-posts.php:1395
475
+ #: include/posts/class-bulk-delete-posts.php:1478
476
+ #: include/posts/class-bulk-delete-posts.php:1507
477
+ #: include/posts/class-bulk-delete-posts.php:1537
478
+ #: include/posts/class-bulk-delete-posts.php:1566
479
+ #: include/posts/class-bulk-delete-posts.php:1593
480
+ #: include/users/class-bulk-delete-users.php:18
481
  msgid ""
482
  "This section just got enabled. Kindly <a href = \"%1$s\">refresh</a> the "
483
  "page to fully enable it."
484
  msgstr ""
485
 
486
+ #: include/meta/class-bulk-delete-comment-meta.php:68
487
+ msgid "Select the post type whose comment meta fields you want to delete"
488
  msgstr ""
489
 
490
+ #: include/meta/class-bulk-delete-comment-meta.php:84
491
+ msgid "Choose your comment meta field settings"
492
  msgstr ""
493
 
494
+ #: include/meta/class-bulk-delete-comment-meta.php:89
495
+ msgid "Delete based on comment meta key name only"
 
 
 
 
496
  msgstr ""
497
 
498
+ #: include/meta/class-bulk-delete-comment-meta.php:96
499
+ msgid "Delete based on comment meta key name and value"
500
  msgstr ""
501
 
502
+ #: include/meta/class-bulk-delete-comment-meta.php:98
503
+ #: include/meta/class-bulk-delete-comment-meta.php:164
504
+ #: include/meta/class-bulk-delete-post-meta.php:98
505
+ #: include/meta/class-bulk-delete-post-meta.php:164
506
+ #: include/meta/class-bulk-delete-user-meta.php:90
507
+ #: include/meta/class-bulk-delete-user-meta.php:144
508
+ #: include/misc/class-bulk-delete-jetpack-contact-form-messages.php:80
509
+ #: include/misc/class-bulk-delete-jetpack-contact-form-messages.php:154
510
+ #: include/pages/class-bulk-delete-pages.php:124
511
+ #: include/posts/class-bulk-delete-posts.php:133
512
+ #: include/posts/class-bulk-delete-posts.php:427
513
+ #: include/posts/class-bulk-delete-posts.php:650
514
+ #: include/posts/class-bulk-delete-posts.php:927
515
+ #: include/posts/class-bulk-delete-posts.php:1176
516
+ #: include/users/class-bulk-delete-users.php:103
517
+ #: tmp_addon/bulk-delete-attachments.php:313
518
+ #: tmp_addon/bulk-delete-posts-by-attachment.php:222
519
+ #: tmp_addon/bulk-delete-posts-by-content.php:240
520
+ #: tmp_addon/bulk-delete-posts-by-custom-field.php:250
521
+ #: tmp_addon/bulk-delete-posts-by-duplicate-title.php:192
522
+ #: tmp_addon/bulk-delete-posts-by-title.php:196
523
+ #: tmp_addon/bulk-delete-posts-by-user-role.php:174
524
+ #: tmp_addon/bulk-delete-posts-by-user.php:218
525
+ msgid "Only available in Pro Addon"
526
  msgstr ""
527
 
528
+ #: include/meta/class-bulk-delete-comment-meta.php:105
529
+ msgid "Comment Meta Key "
530
  msgstr ""
531
 
532
+ #: include/meta/class-bulk-delete-comment-meta.php:106
533
+ #: include/meta/class-bulk-delete-post-meta.php:106
534
+ #: include/meta/class-bulk-delete-user-meta.php:98
535
+ msgid "Meta Key"
536
  msgstr ""
537
 
538
+ #: include/meta/class-bulk-delete-comment-meta.php:122
539
+ #: include/meta/class-bulk-delete-post-meta.php:122
540
+ #: include/meta/class-bulk-delete-user-meta.php:114
541
+ #: include/misc/class-bulk-delete-jetpack-contact-form-messages.php:127
542
+ msgid "Choose your deletion options"
 
 
 
 
 
 
 
 
 
 
 
 
543
  msgstr ""
544
 
545
+ #: include/meta/class-bulk-delete-comment-meta.php:129
546
+ msgid "Only restrict to comments which are "
547
  msgstr ""
548
 
549
+ #: include/meta/class-bulk-delete-comment-meta.php:131
550
+ #: include/meta/class-bulk-delete-post-meta.php:131
551
+ #: include/misc/class-bulk-delete-jetpack-contact-form-messages.php:107
552
+ #: include/pages/class-bulk-delete-pages.php:85
553
+ #: include/posts/class-bulk-delete-posts.php:94
554
+ #: include/posts/class-bulk-delete-posts.php:379
555
+ #: include/posts/class-bulk-delete-posts.php:602
556
+ #: include/posts/class-bulk-delete-posts.php:879
557
+ #: include/posts/class-bulk-delete-posts.php:1135
558
  #: tmp_addon/bulk-delete-attachments.php:272
559
  #: tmp_addon/bulk-delete-posts-by-attachment.php:174
560
  #: tmp_addon/bulk-delete-posts-by-content.php:194
561
  #: tmp_addon/bulk-delete-posts-by-custom-field.php:202
562
  #: tmp_addon/bulk-delete-posts-by-title.php:148
563
  #: tmp_addon/bulk-delete-posts-by-user-role.php:134
564
+ #: tmp_addon/bulk-delete-posts-by-user.php:178
565
  msgid "older than"
566
  msgstr ""
567
 
568
+ #: include/meta/class-bulk-delete-comment-meta.php:132
569
+ msgid "commented within last"
 
 
 
 
 
 
 
 
 
 
 
 
 
570
  msgstr ""
571
 
572
+ #: include/meta/class-bulk-delete-comment-meta.php:134
573
+ #: include/meta/class-bulk-delete-post-meta.php:134
574
+ #: include/misc/class-bulk-delete-jetpack-contact-form-messages.php:110
575
+ #: include/pages/class-bulk-delete-pages.php:88
576
+ #: include/posts/class-bulk-delete-posts.php:97
577
+ #: include/posts/class-bulk-delete-posts.php:382
578
+ #: include/posts/class-bulk-delete-posts.php:605
579
+ #: include/posts/class-bulk-delete-posts.php:882
580
+ #: include/posts/class-bulk-delete-posts.php:1138
581
+ #: include/users/class-bulk-delete-users.php:57
582
  #: tmp_addon/bulk-delete-attachments.php:275
583
  #: tmp_addon/bulk-delete-from-trash.php:348
584
  #: tmp_addon/bulk-delete-posts-by-attachment.php:177
586
  #: tmp_addon/bulk-delete-posts-by-custom-field.php:205
587
  #: tmp_addon/bulk-delete-posts-by-title.php:151
588
  #: tmp_addon/bulk-delete-posts-by-user-role.php:137
589
+ #: tmp_addon/bulk-delete-posts-by-user.php:181
590
  msgid "days"
591
  msgstr ""
592
 
593
+ #: include/meta/class-bulk-delete-comment-meta.php:141
594
+ msgid "Only delete comment meta field from first "
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
595
  msgstr ""
596
 
597
+ #: include/meta/class-bulk-delete-comment-meta.php:142
598
+ msgid "comments."
599
  msgstr ""
600
 
601
+ #: include/meta/class-bulk-delete-comment-meta.php:143
602
+ #: include/meta/class-bulk-delete-post-meta.php:143
603
+ #: include/misc/class-bulk-delete-jetpack-contact-form-messages.php:121
604
+ #: include/posts/class-bulk-delete-posts.php:113
605
+ #: include/posts/class-bulk-delete-posts.php:407
606
+ #: include/posts/class-bulk-delete-posts.php:630
607
+ #: include/posts/class-bulk-delete-posts.php:907
608
+ #: include/posts/class-bulk-delete-posts.php:1156
609
+ #: tmp_addon/bulk-delete-posts-by-attachment.php:202
610
+ #: tmp_addon/bulk-delete-posts-by-content.php:220
611
+ #: tmp_addon/bulk-delete-posts-by-custom-field.php:230
612
+ #: tmp_addon/bulk-delete-posts-by-duplicate-title.php:172
613
+ #: tmp_addon/bulk-delete-posts-by-title.php:176
614
  msgid ""
615
+ "Use this option if there are more than 1000 posts and the script timesout."
616
  msgstr ""
617
 
618
+ #: include/meta/class-bulk-delete-comment-meta.php:149
619
+ #: include/meta/class-bulk-delete-post-meta.php:149
620
+ #: include/meta/class-bulk-delete-user-meta.php:129
621
+ #: include/misc/class-bulk-delete-jetpack-contact-form-messages.php:140
622
+ #: include/pages/class-bulk-delete-pages.php:110
623
+ #: include/posts/class-bulk-delete-posts.php:119
624
+ #: include/posts/class-bulk-delete-posts.php:413
625
+ #: include/posts/class-bulk-delete-posts.php:636
626
+ #: include/posts/class-bulk-delete-posts.php:913
627
+ #: include/posts/class-bulk-delete-posts.php:1162
628
+ #: include/users/class-bulk-delete-users.php:89
629
  #: tmp_addon/bulk-delete-attachments.php:299
630
  #: tmp_addon/bulk-delete-posts-by-attachment.php:208
631
  #: tmp_addon/bulk-delete-posts-by-content.php:226
633
  #: tmp_addon/bulk-delete-posts-by-duplicate-title.php:178
634
  #: tmp_addon/bulk-delete-posts-by-title.php:182
635
  #: tmp_addon/bulk-delete-posts-by-user-role.php:160
636
+ #: tmp_addon/bulk-delete-posts-by-user.php:204
637
  msgid "Delete now"
638
  msgstr ""
639
 
640
+ #: include/meta/class-bulk-delete-comment-meta.php:151
641
+ #: include/meta/class-bulk-delete-post-meta.php:151
642
+ #: include/meta/class-bulk-delete-user-meta.php:131
643
+ #: include/misc/class-bulk-delete-jetpack-contact-form-messages.php:142
644
+ #: include/pages/class-bulk-delete-pages.php:112
645
+ #: include/posts/class-bulk-delete-posts.php:121
646
+ #: include/posts/class-bulk-delete-posts.php:415
647
+ #: include/posts/class-bulk-delete-posts.php:638
648
+ #: include/posts/class-bulk-delete-posts.php:915
649
+ #: include/posts/class-bulk-delete-posts.php:1164
650
+ #: include/users/class-bulk-delete-users.php:91
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
651
  #: tmp_addon/bulk-delete-attachments.php:301
652
  #: tmp_addon/bulk-delete-posts-by-attachment.php:210
653
  #: tmp_addon/bulk-delete-posts-by-content.php:228
655
  #: tmp_addon/bulk-delete-posts-by-duplicate-title.php:180
656
  #: tmp_addon/bulk-delete-posts-by-title.php:184
657
  #: tmp_addon/bulk-delete-posts-by-user-role.php:162
658
+ #: tmp_addon/bulk-delete-posts-by-user.php:206
659
  msgid "repeat "
660
  msgstr ""
661
 
662
+ #: include/meta/class-bulk-delete-comment-meta.php:153
663
+ #: include/meta/class-bulk-delete-post-meta.php:153
664
+ #: include/meta/class-bulk-delete-user-meta.php:133
665
+ #: include/misc/class-bulk-delete-jetpack-contact-form-messages.php:144
666
+ #: include/pages/class-bulk-delete-pages.php:114
667
+ #: include/posts/class-bulk-delete-posts.php:123
668
+ #: include/posts/class-bulk-delete-posts.php:417
669
+ #: include/posts/class-bulk-delete-posts.php:640
670
+ #: include/posts/class-bulk-delete-posts.php:917
671
+ #: include/posts/class-bulk-delete-posts.php:1166
672
+ #: include/users/class-bulk-delete-users.php:93
673
  #: tmp_addon/bulk-delete-attachments.php:303
674
  #: tmp_addon/bulk-delete-posts-by-attachment.php:212
675
  #: tmp_addon/bulk-delete-posts-by-content.php:230
677
  #: tmp_addon/bulk-delete-posts-by-duplicate-title.php:182
678
  #: tmp_addon/bulk-delete-posts-by-title.php:186
679
  #: tmp_addon/bulk-delete-posts-by-user-role.php:164
680
+ #: tmp_addon/bulk-delete-posts-by-user.php:208
681
  msgid "Don't repeat"
682
  msgstr ""
683
 
684
+ #: include/meta/class-bulk-delete-comment-meta.php:171
685
+ #: include/meta/class-bulk-delete-post-meta.php:171
686
+ #: include/meta/class-bulk-delete-user-meta.php:151
687
+ #: include/posts/class-bulk-delete-posts.php:433
688
+ #: include/users/class-bulk-delete-users.php:109
689
+ #: tmp_addon/bulk-delete-attachments.php:319
690
+ #: tmp_addon/bulk-delete-posts-by-attachment.php:228
691
+ #: tmp_addon/bulk-delete-posts-by-content.php:246
692
+ #: tmp_addon/bulk-delete-posts-by-custom-field.php:256
693
+ #: tmp_addon/bulk-delete-posts-by-duplicate-title.php:198
694
+ #: tmp_addon/bulk-delete-posts-by-title.php:202
695
+ #: tmp_addon/bulk-delete-posts-by-user-role.php:180
696
+ #: tmp_addon/bulk-delete-posts-by-user.php:224
697
+ msgid "Enter time in Y-m-d H:i:s format or enter now to use current time"
 
 
 
 
 
 
 
 
 
698
  msgstr ""
699
 
700
+ #: include/meta/class-bulk-delete-comment-meta.php:179
701
+ #: include/meta/class-bulk-delete-post-meta.php:179
702
+ #: include/meta/class-bulk-delete-user-meta.php:159
703
+ #: include/misc/class-bulk-delete-jetpack-contact-form-messages.php:161
704
+ #: include/pages/class-bulk-delete-pages.php:131
705
+ #: include/posts/class-bulk-delete-posts.php:140
706
+ #: include/posts/class-bulk-delete-posts.php:441
707
+ #: include/posts/class-bulk-delete-posts.php:657
708
+ #: include/posts/class-bulk-delete-posts.php:934
709
+ #: include/posts/class-bulk-delete-posts.php:1183
710
+ #: include/posts/class-bulk-delete-posts.php:1345
711
+ #: include/posts/class-bulk-delete-posts.php:1419
712
+ #: include/users/class-bulk-delete-users.php:117
713
  #: tmp_addon/bulk-delete-attachments.php:326
714
  #: tmp_addon/bulk-delete-from-trash.php:162
715
  #: tmp_addon/bulk-delete-from-trash.php:270
719
  #: tmp_addon/bulk-delete-posts-by-duplicate-title.php:206
720
  #: tmp_addon/bulk-delete-posts-by-title.php:210
721
  #: tmp_addon/bulk-delete-posts-by-user-role.php:188
722
+ #: tmp_addon/bulk-delete-posts-by-user.php:232
723
  msgid "Bulk Delete "
724
  msgstr ""
725
 
726
+ #: include/meta/class-bulk-delete-comment-meta.php:198
727
+ msgid ""
728
+ "Are you sure you want to delete all the comment meta fields that match the "
729
+ "selected filters?"
730
  msgstr ""
731
 
732
+ #: include/meta/class-bulk-delete-comment-meta.php:239
733
+ msgid ""
734
+ "Comment meta fields from the comments with the selected criteria are "
735
+ "scheduled for deletion."
736
+ msgstr ""
737
+
738
+ #: include/meta/class-bulk-delete-comment-meta.php:240
739
+ #: include/meta/class-bulk-delete-post-meta.php:240
740
+ #: include/meta/class-bulk-delete-user-meta.php:216
741
+ #: include/misc/class-bulk-delete-jetpack-contact-form-messages.php:221
742
+ #: include/pages/class-bulk-delete-pages.php:167
743
+ #: include/posts/class-bulk-delete-posts.php:178
744
+ #: include/posts/class-bulk-delete-posts.php:477
745
+ #: include/posts/class-bulk-delete-posts.php:696
746
+ #: include/posts/class-bulk-delete-posts.php:975
747
+ #: include/posts/class-bulk-delete-posts.php:1223
748
+ #: include/users/class-bulk-delete-users.php:150
749
  #: tmp_addon/bulk-delete-attachments.php:375
750
  #: tmp_addon/bulk-delete-posts-by-attachment.php:288
751
  #: tmp_addon/bulk-delete-posts-by-content.php:292
753
  #: tmp_addon/bulk-delete-posts-by-duplicate-title.php:249
754
  #: tmp_addon/bulk-delete-posts-by-title.php:247
755
  #: tmp_addon/bulk-delete-posts-by-user-role.php:222
756
+ #: tmp_addon/bulk-delete-posts-by-user.php:265
757
  msgid "See the full list of <a href = \"%s\">scheduled tasks</a>"
758
  msgstr ""
759
 
760
+ #: include/meta/class-bulk-delete-comment-meta.php:243
761
+ msgid "Deleted comment meta field from %d comment"
762
+ msgid_plural "Deleted comment meta field from %d comments"
763
  msgstr[0] ""
764
  msgstr[1] ""
765
 
766
+ #: include/meta/class-bulk-delete-meta.php:38
767
+ #: include/meta/class-bulk-delete-meta.php:39
768
+ #: include/meta/class-bulk-delete-meta.php:102
769
+ msgid "Bulk Delete Meta Fields"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
770
  msgstr ""
771
 
772
+ #: include/meta/class-bulk-delete-meta.php:117
773
+ #: tmp_addon/bulk-delete-attachments.php:193
774
+ msgid "WARNING: Items deleted once cannot be retrieved back. Use with caution."
775
  msgstr ""
776
 
777
+ #: include/meta/class-bulk-delete-post-meta.php:38
778
+ msgid "Bulk Delete Post Meta"
779
  msgstr ""
780
 
781
+ #: include/meta/class-bulk-delete-post-meta.php:68
782
+ msgid "Select the post type whose post meta fields you want to delete"
783
  msgstr ""
784
 
785
+ #: include/meta/class-bulk-delete-post-meta.php:84
786
+ msgid "Choose your post meta field settings"
787
  msgstr ""
788
 
789
+ #: include/meta/class-bulk-delete-post-meta.php:89
790
+ msgid "Delete based on post meta key name only"
791
  msgstr ""
792
 
793
+ #: include/meta/class-bulk-delete-post-meta.php:96
794
+ msgid "Delete based on post meta key name and value"
795
  msgstr ""
796
 
797
+ #: include/meta/class-bulk-delete-post-meta.php:105
798
+ msgid "Post Meta Key "
799
  msgstr ""
800
 
801
+ #: include/meta/class-bulk-delete-post-meta.php:129
802
+ #: include/misc/class-bulk-delete-jetpack-contact-form-messages.php:105
803
+ #: include/posts/class-bulk-delete-posts.php:92
804
+ #: include/posts/class-bulk-delete-posts.php:377
805
+ #: include/posts/class-bulk-delete-posts.php:600
806
+ #: include/posts/class-bulk-delete-posts.php:877
807
+ #: include/posts/class-bulk-delete-posts.php:1133
808
  #: tmp_addon/bulk-delete-posts-by-attachment.php:172
809
  #: tmp_addon/bulk-delete-posts-by-content.php:192
810
  #: tmp_addon/bulk-delete-posts-by-custom-field.php:200
811
  #: tmp_addon/bulk-delete-posts-by-title.php:146
812
  #: tmp_addon/bulk-delete-posts-by-user-role.php:132
813
+ #: tmp_addon/bulk-delete-posts-by-user.php:176
814
  msgid "Only restrict to posts which are "
815
  msgstr ""
816
 
817
+ #: include/meta/class-bulk-delete-post-meta.php:132
818
+ #: include/misc/class-bulk-delete-jetpack-contact-form-messages.php:108
819
+ #: include/pages/class-bulk-delete-pages.php:86
820
+ #: include/posts/class-bulk-delete-posts.php:95
821
+ #: include/posts/class-bulk-delete-posts.php:380
822
+ #: include/posts/class-bulk-delete-posts.php:603
823
+ #: include/posts/class-bulk-delete-posts.php:880
824
+ #: include/posts/class-bulk-delete-posts.php:1136
825
+ #: tmp_addon/bulk-delete-attachments.php:273
826
+ #: tmp_addon/bulk-delete-posts-by-attachment.php:175
827
+ #: tmp_addon/bulk-delete-posts-by-content.php:195
828
+ #: tmp_addon/bulk-delete-posts-by-custom-field.php:203
829
+ #: tmp_addon/bulk-delete-posts-by-title.php:149
830
+ #: tmp_addon/bulk-delete-posts-by-user-role.php:135
831
+ #: tmp_addon/bulk-delete-posts-by-user.php:179
832
+ msgid "posted within last"
833
+ msgstr ""
834
+
835
+ #: include/meta/class-bulk-delete-post-meta.php:141
836
+ msgid "Only delete post meta field from first "
837
+ msgstr ""
838
+
839
+ #: include/meta/class-bulk-delete-post-meta.php:142
840
+ #: include/misc/class-bulk-delete-jetpack-contact-form-messages.php:120
841
+ #: include/posts/class-bulk-delete-posts.php:112
842
+ #: include/posts/class-bulk-delete-posts.php:406
843
+ #: include/posts/class-bulk-delete-posts.php:629
844
+ #: include/posts/class-bulk-delete-posts.php:906
845
+ #: include/posts/class-bulk-delete-posts.php:1155
846
  #: tmp_addon/bulk-delete-posts-by-attachment.php:201
847
  #: tmp_addon/bulk-delete-posts-by-content.php:219
848
  #: tmp_addon/bulk-delete-posts-by-custom-field.php:229
849
  #: tmp_addon/bulk-delete-posts-by-title.php:175
850
  #: tmp_addon/bulk-delete-posts-by-user-role.php:153
851
+ #: tmp_addon/bulk-delete-posts-by-user.php:197
852
  msgid "posts."
853
  msgstr ""
854
 
855
+ #: include/meta/class-bulk-delete-post-meta.php:198
 
 
 
 
 
 
 
 
 
 
 
 
856
  msgid ""
857
+ "Are you sure you want to delete all the post meta fields that match the "
858
+ "selected filters?"
859
  msgstr ""
860
 
861
+ #: include/meta/class-bulk-delete-post-meta.php:239
862
+ msgid ""
863
+ "Post meta fields from the posts with the selected criteria are scheduled for "
864
+ "deletion."
865
  msgstr ""
866
 
867
+ #: include/meta/class-bulk-delete-post-meta.php:243
868
+ msgid "Deleted post meta field from %d post"
869
+ msgid_plural "Deleted post meta field from %d posts"
870
  msgstr[0] ""
871
  msgstr[1] ""
872
 
873
+ #: include/meta/class-bulk-delete-user-meta.php:38
874
+ msgid "Bulk Delete User Meta"
875
  msgstr ""
876
 
877
+ #: include/meta/class-bulk-delete-user-meta.php:59
878
+ msgid "Select the user role whose user meta fields you want to delete"
879
  msgstr ""
880
 
881
+ #: include/meta/class-bulk-delete-user-meta.php:68
882
+ #: include/users/class-bulk-delete-users.php:34
883
+ #: tmp_addon/bulk-delete-posts-by-user-role.php:96
884
+ msgid "Users"
885
  msgstr ""
886
 
887
+ #: include/meta/class-bulk-delete-user-meta.php:76
888
+ msgid "Choose your user meta field settings"
889
  msgstr ""
890
 
891
+ #: include/meta/class-bulk-delete-user-meta.php:81
892
+ msgid "Delete based on user meta key name only"
 
 
 
 
 
 
893
  msgstr ""
894
 
895
+ #: include/meta/class-bulk-delete-user-meta.php:88
896
+ msgid "Delete based on user meta key name and value"
 
 
 
 
 
 
897
  msgstr ""
898
 
899
+ #: include/meta/class-bulk-delete-user-meta.php:97
900
+ msgid "User Meta Key "
 
 
 
 
 
 
 
 
 
 
 
901
  msgstr ""
902
 
903
+ #: include/meta/class-bulk-delete-user-meta.php:121
904
+ msgid "Only delete user meta field from first "
905
  msgstr ""
906
 
907
+ #: include/meta/class-bulk-delete-user-meta.php:122
908
+ #: include/users/class-bulk-delete-users.php:82
909
+ msgid "users."
 
 
 
 
 
910
  msgstr ""
911
 
912
+ #: include/meta/class-bulk-delete-user-meta.php:123
913
+ msgid ""
914
+ "Use this option if there are more than 1000 users and the script timesout."
915
  msgstr ""
916
 
917
+ #: include/meta/class-bulk-delete-user-meta.php:178
918
+ msgid ""
919
+ "Are you sure you want to delete all the user meta fields that match the "
920
+ "selected filters?"
921
  msgstr ""
922
 
923
+ #: include/meta/class-bulk-delete-user-meta.php:215
924
+ msgid ""
925
+ "User meta fields from the users with the selected criteria are scheduled for "
926
+ "deletion."
927
  msgstr ""
928
 
929
+ #: include/meta/class-bulk-delete-user-meta.php:219
930
+ msgid "Deleted user meta field from %d user"
931
+ msgid_plural "Deleted user meta field from %d users"
932
  msgstr[0] ""
933
  msgstr[1] ""
934
 
935
+ #: include/misc/class-bulk-delete-jetpack-contact-form-messages.php:30
936
+ msgid "Bulk Delete Jetpack Contact Form Messages"
937
  msgstr ""
938
 
939
+ #: include/misc/class-bulk-delete-jetpack-contact-form-messages.php:54
940
+ msgid "Jetpack contact form is not enabled."
941
  msgstr ""
942
 
943
+ #: include/misc/class-bulk-delete-jetpack-contact-form-messages.php:70
944
+ msgid "Delete all Contact Form Messages"
 
 
945
  msgstr ""
946
 
947
+ #: include/misc/class-bulk-delete-jetpack-contact-form-messages.php:70
948
+ msgid "in total"
 
 
949
  msgstr ""
950
 
951
+ #: include/misc/class-bulk-delete-jetpack-contact-form-messages.php:79
952
+ msgid "Delete Messages based on filters"
953
  msgstr ""
954
 
955
+ #: include/misc/class-bulk-delete-jetpack-contact-form-messages.php:96
956
+ msgid "Choose your date options"
957
  msgstr ""
958
 
959
+ #: include/misc/class-bulk-delete-jetpack-contact-form-messages.php:119
960
+ #: include/pages/class-bulk-delete-pages.php:102
961
+ #: include/posts/class-bulk-delete-posts.php:111
962
+ #: include/posts/class-bulk-delete-posts.php:405
963
+ #: include/posts/class-bulk-delete-posts.php:628
964
+ #: include/posts/class-bulk-delete-posts.php:905
965
+ #: include/posts/class-bulk-delete-posts.php:1154
966
+ #: include/users/class-bulk-delete-users.php:80
967
+ #: tmp_addon/bulk-delete-attachments.php:291
968
+ #: tmp_addon/bulk-delete-posts-by-attachment.php:200
969
+ #: tmp_addon/bulk-delete-posts-by-content.php:218
970
+ #: tmp_addon/bulk-delete-posts-by-custom-field.php:228
971
+ #: tmp_addon/bulk-delete-posts-by-duplicate-title.php:170
972
+ #: tmp_addon/bulk-delete-posts-by-title.php:174
973
+ #: tmp_addon/bulk-delete-posts-by-user-role.php:151
974
+ #: tmp_addon/bulk-delete-posts-by-user.php:195
975
+ msgid "Only delete first "
976
  msgstr ""
977
 
978
+ #: include/misc/class-bulk-delete-jetpack-contact-form-messages.php:133
979
+ #: include/pages/class-bulk-delete-pages.php:94
980
+ #: include/posts/class-bulk-delete-posts.php:103
981
+ #: include/posts/class-bulk-delete-posts.php:388
982
+ #: include/posts/class-bulk-delete-posts.php:611
983
+ #: include/posts/class-bulk-delete-posts.php:888
984
+ #: include/posts/class-bulk-delete-posts.php:1144
985
+ #: include/posts/class-bulk-delete-posts.php:1336
986
+ #: tmp_addon/bulk-delete-attachments.php:281
987
+ #: tmp_addon/bulk-delete-posts-by-attachment.php:183
988
+ #: tmp_addon/bulk-delete-posts-by-content.php:203
989
+ #: tmp_addon/bulk-delete-posts-by-custom-field.php:211
990
+ #: tmp_addon/bulk-delete-posts-by-duplicate-title.php:162
991
+ #: tmp_addon/bulk-delete-posts-by-title.php:157
992
+ #: tmp_addon/bulk-delete-posts-by-user-role.php:143
993
+ #: tmp_addon/bulk-delete-posts-by-user.php:187
994
+ msgid "Move to Trash"
995
  msgstr ""
996
 
997
+ #: include/misc/class-bulk-delete-jetpack-contact-form-messages.php:134
998
+ #: include/pages/class-bulk-delete-pages.php:95
999
+ #: include/posts/class-bulk-delete-posts.php:104
1000
+ #: include/posts/class-bulk-delete-posts.php:389
1001
+ #: include/posts/class-bulk-delete-posts.php:612
1002
+ #: include/posts/class-bulk-delete-posts.php:889
1003
+ #: include/posts/class-bulk-delete-posts.php:1145
1004
+ #: include/posts/class-bulk-delete-posts.php:1337
1005
+ #: tmp_addon/bulk-delete-attachments.php:282
1006
+ #: tmp_addon/bulk-delete-posts-by-attachment.php:184
1007
+ #: tmp_addon/bulk-delete-posts-by-content.php:204
1008
+ #: tmp_addon/bulk-delete-posts-by-custom-field.php:212
1009
+ #: tmp_addon/bulk-delete-posts-by-duplicate-title.php:163
1010
+ #: tmp_addon/bulk-delete-posts-by-title.php:158
1011
+ #: tmp_addon/bulk-delete-posts-by-user-role.php:144
1012
+ #: tmp_addon/bulk-delete-posts-by-user.php:188
1013
+ msgid "Delete permanently"
1014
  msgstr ""
1015
 
1016
+ #: include/misc/class-bulk-delete-jetpack-contact-form-messages.php:181
1017
+ msgid ""
1018
+ "Are you sure you want to delete all the Jetpack contact form messages based "
1019
+ "on the selected filters?"
 
 
 
 
1020
  msgstr ""
1021
 
1022
+ #: include/misc/class-bulk-delete-jetpack-contact-form-messages.php:220
1023
+ msgid ""
1024
+ "Jetpack contact form messages with the selected criteria are scheduled for "
1025
+ "deletion."
1026
  msgstr ""
1027
 
1028
+ #: include/misc/class-bulk-delete-jetpack-contact-form-messages.php:224
1029
+ msgid "Deleted %d Jetpack contact form message"
1030
+ msgid_plural "Deleted %d Jetpack contact form messages"
1031
  msgstr[0] ""
1032
  msgstr[1] ""
1033
 
1034
+ #: include/misc/class-bulk-delete-misc.php:33
1035
+ #: include/misc/class-bulk-delete-misc.php:97
1036
+ msgid "Bulk Delete Miscellaneous Items"
 
 
 
1037
  msgstr ""
1038
 
1039
+ #: include/misc/class-bulk-delete-misc.php:34
1040
+ msgid "Bulk Delete Misc"
 
 
 
 
 
 
 
 
1041
  msgstr ""
1042
 
1043
+ #: include/pages/class-bulk-delete-pages.php:35
1044
+ msgid "Select the pages which you want to delete"
1045
  msgstr ""
1046
 
1047
+ #: include/pages/class-bulk-delete-pages.php:42
1048
+ msgid "All Published Pages"
 
 
1049
  msgstr ""
1050
 
1051
+ #: include/pages/class-bulk-delete-pages.php:42
1052
+ #: include/pages/class-bulk-delete-pages.php:49
1053
+ #: include/pages/class-bulk-delete-pages.php:56
1054
+ #: include/pages/class-bulk-delete-pages.php:63
1055
+ #: include/pages/class-bulk-delete-pages.php:70
1056
+ msgid "Pages"
1057
  msgstr ""
1058
 
1059
+ #: include/pages/class-bulk-delete-pages.php:49
1060
+ msgid "All Draft Pages"
1061
  msgstr ""
1062
 
1063
+ #: include/pages/class-bulk-delete-pages.php:56
1064
+ msgid "All Scheduled Pages"
 
1065
  msgstr ""
1066
 
1067
+ #: include/pages/class-bulk-delete-pages.php:63
1068
+ msgid "All Pending Pages"
1069
  msgstr ""
1070
 
1071
+ #: include/pages/class-bulk-delete-pages.php:70
1072
+ msgid "All Private Pages"
1073
  msgstr ""
1074
 
1075
+ #: include/pages/class-bulk-delete-pages.php:76
1076
+ #: include/posts/class-bulk-delete-posts.php:79
1077
+ #: include/posts/class-bulk-delete-posts.php:368
1078
+ #: include/posts/class-bulk-delete-posts.php:591
1079
+ #: include/posts/class-bulk-delete-posts.php:868
1080
+ #: include/posts/class-bulk-delete-posts.php:1124
1081
+ #: include/posts/class-bulk-delete-posts.php:1330
1082
+ #: include/users/class-bulk-delete-users.php:42
1083
+ #: tmp_addon/bulk-delete-attachments.php:261
1084
+ #: tmp_addon/bulk-delete-jetpack-contact-form-messages.php:123
1085
+ #: tmp_addon/bulk-delete-posts-by-attachment.php:163
1086
+ #: tmp_addon/bulk-delete-posts-by-content.php:186
1087
+ #: tmp_addon/bulk-delete-posts-by-custom-field.php:191
1088
+ #: tmp_addon/bulk-delete-posts-by-duplicate-title.php:156
1089
+ #: tmp_addon/bulk-delete-posts-by-title.php:137
1090
+ #: tmp_addon/bulk-delete-posts-by-user-role.php:127
1091
+ #: tmp_addon/bulk-delete-posts-by-user.php:171
1092
+ msgid "Choose your filtering options"
1093
  msgstr ""
1094
 
1095
+ #: include/pages/class-bulk-delete-pages.php:83
1096
+ msgid "Only restrict to pages which are "
1097
  msgstr ""
1098
 
1099
+ #: include/pages/class-bulk-delete-pages.php:103
1100
+ msgid "pages."
1101
  msgstr ""
1102
 
1103
+ #: include/pages/class-bulk-delete-pages.php:104
1104
  msgid ""
1105
+ "Use this option if there are more than 1000 pages and the script timesout."
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1106
  msgstr ""
1107
 
1108
+ #: include/pages/class-bulk-delete-pages.php:166
1109
+ msgid "The selected pages are scheduled for deletion."
1110
  msgstr ""
1111
 
1112
+ #: include/pages/class-bulk-delete-pages.php:170
1113
+ msgid "Deleted %d page"
1114
+ msgid_plural "Deleted %d pages"
1115
+ msgstr[0] ""
1116
+ msgstr[1] ""
1117
 
1118
+ #: include/pages/class-bulk-delete-pages.php:273
1119
+ msgid "You need \"Bulk Delete From Trash\" Addon, to delete pages in Trash."
 
1120
  msgstr ""
1121
 
1122
+ #: include/posts/class-bulk-delete-posts.php:31
1123
+ #: include/posts/class-bulk-delete-posts.php:1404
1124
+ msgid "Select the posts which you want to delete"
1125
  msgstr ""
1126
 
1127
+ #: include/posts/class-bulk-delete-posts.php:38
1128
+ msgid "All publish posts"
1129
  msgstr ""
1130
 
1131
+ #: include/posts/class-bulk-delete-posts.php:38
1132
+ #: include/posts/class-bulk-delete-posts.php:52
1133
+ #: include/posts/class-bulk-delete-posts.php:59
1134
+ #: include/posts/class-bulk-delete-posts.php:66
1135
+ #: include/posts/class-bulk-delete-posts.php:73
1136
+ #: include/posts/class-bulk-delete-posts.php:349
1137
+ #: include/posts/class-bulk-delete-posts.php:574
1138
+ #: include/posts/class-bulk-delete-posts.php:855
1139
+ msgid "Posts"
1140
  msgstr ""
1141
 
1142
+ #: include/posts/class-bulk-delete-posts.php:45
1143
+ msgid "All Draft Posts"
1144
  msgstr ""
1145
 
1146
+ #: include/posts/class-bulk-delete-posts.php:45
1147
+ msgid "Drafts"
 
1148
  msgstr ""
1149
+
1150
+ #: include/posts/class-bulk-delete-posts.php:52
1151
+ msgid "All Pending posts"
 
 
1152
  msgstr ""
1153
 
1154
+ #: include/posts/class-bulk-delete-posts.php:59
1155
+ msgid "All scheduled posts"
1156
  msgstr ""
1157
 
1158
+ #: include/posts/class-bulk-delete-posts.php:66
1159
+ msgid "All private posts"
 
 
1160
  msgstr ""
1161
 
1162
+ #: include/posts/class-bulk-delete-posts.php:73
1163
+ msgid "All Sticky posts"
1164
  msgstr ""
1165
 
1166
+ #: include/posts/class-bulk-delete-posts.php:85
1167
+ msgid "Note: The date filter will not work for sticky posts"
1168
  msgstr ""
1169
 
1170
+ #: include/posts/class-bulk-delete-posts.php:177
1171
+ msgid "Posts with the selected status are scheduled for deletion."
1172
  msgstr ""
1173
 
1174
+ #: include/posts/class-bulk-delete-posts.php:181
1175
+ msgid "Deleted %d post with the selected post status"
1176
+ msgid_plural "Deleted %d posts with the selected post status"
1177
+ msgstr[0] ""
1178
+ msgstr[1] ""
1179
+
1180
+ #: include/posts/class-bulk-delete-posts.php:313
1181
+ msgid "Select the post type whose category posts you want to delete"
1182
  msgstr ""
1183
 
1184
+ #: include/posts/class-bulk-delete-posts.php:332
1185
+ msgid "Select the categories whose post you want to delete"
1186
  msgstr ""
1187
 
1188
+ #: include/posts/class-bulk-delete-posts.php:333
1189
  msgid ""
1190
+ "Note: The post count below for each category is the total number of posts in "
1191
+ "that category, irrespective of post type"
1192
  msgstr ""
1193
 
1194
+ #: include/posts/class-bulk-delete-posts.php:360
1195
+ msgid "All Categories"
1196
  msgstr ""
1197
 
1198
+ #: include/posts/class-bulk-delete-posts.php:395
1199
+ #: include/posts/class-bulk-delete-posts.php:618
1200
+ #: include/posts/class-bulk-delete-posts.php:895
1201
+ #: tmp_addon/bulk-delete-posts-by-attachment.php:190
1202
+ #: tmp_addon/bulk-delete-posts-by-content.php:210
1203
+ #: tmp_addon/bulk-delete-posts-by-custom-field.php:218
1204
+ #: tmp_addon/bulk-delete-posts-by-title.php:164
1205
+ msgid "Public posts"
1206
  msgstr ""
1207
 
1208
+ #: include/posts/class-bulk-delete-posts.php:396
1209
+ #: include/posts/class-bulk-delete-posts.php:619
1210
+ #: include/posts/class-bulk-delete-posts.php:896
1211
+ #: tmp_addon/bulk-delete-posts-by-attachment.php:191
1212
+ #: tmp_addon/bulk-delete-posts-by-content.php:211
1213
+ #: tmp_addon/bulk-delete-posts-by-custom-field.php:219
1214
+ #: tmp_addon/bulk-delete-posts-by-title.php:165
1215
+ msgid "Private Posts"
1216
  msgstr ""
1217
 
1218
+ #: include/posts/class-bulk-delete-posts.php:476
1219
+ msgid "Posts from the selected categories are scheduled for deletion."
1220
  msgstr ""
1221
 
1222
+ #: include/posts/class-bulk-delete-posts.php:480
1223
+ msgid "Deleted %d post from the selected categories"
1224
+ msgid_plural "Deleted %d posts from the selected categories"
1225
+ msgstr[0] ""
1226
+ msgstr[1] ""
1227
+
1228
+ #: include/posts/class-bulk-delete-posts.php:561
1229
+ msgid "Select the tags whose post you want to delete"
1230
  msgstr ""
1231
 
1232
+ #: include/posts/class-bulk-delete-posts.php:585
1233
+ msgid "All Tags"
1234
  msgstr ""
1235
 
1236
+ #: include/posts/class-bulk-delete-posts.php:663
1237
+ msgid "You don't have any posts assigned to tags in this blog."
1238
  msgstr ""
1239
 
1240
+ #: include/posts/class-bulk-delete-posts.php:695
1241
+ msgid "Posts from the selected tags are scheduled for deletion."
1242
  msgstr ""
1243
 
1244
+ #: include/posts/class-bulk-delete-posts.php:699
1245
+ msgid "Deleted %d post from the selected tags"
1246
+ msgid_plural "Deleted %d posts from the selected tags"
1247
+ msgstr[0] ""
1248
+ msgstr[1] ""
1249
+
1250
+ #: include/posts/class-bulk-delete-posts.php:802
1251
+ msgid "Select the post type whose taxonomy posts you want to delete"
1252
  msgstr ""
1253
 
1254
+ #: include/posts/class-bulk-delete-posts.php:822
1255
+ msgid "Select the taxonomies whose post you want to delete"
1256
  msgstr ""
1257
 
1258
+ #: include/posts/class-bulk-delete-posts.php:841
1259
+ msgid ""
1260
+ "The selected taxonomy has the following terms. Select the terms whose post "
1261
+ "you want to delete"
1262
  msgstr ""
1263
 
1264
+ #: include/posts/class-bulk-delete-posts.php:842
1265
+ msgid ""
1266
+ "Note: The post count below for each term is the total number of posts in "
1267
+ "that term, irrespective of post type"
1268
  msgstr ""
1269
 
1270
+ #: include/posts/class-bulk-delete-posts.php:940
1271
+ msgid "You don't have any posts assigned to custom taxonomies in this blog."
1272
  msgstr ""
1273
 
1274
+ #: include/posts/class-bulk-delete-posts.php:974
1275
+ msgid "Posts from the selected custom taxonomies are scheduled for deletion."
 
 
1276
  msgstr ""
1277
 
1278
+ #: include/posts/class-bulk-delete-posts.php:978
1279
+ msgid "Deleted %d post from the selected custom taxonomies"
1280
+ msgid_plural "Deleted %d posts from the selected custom taxonomies"
1281
+ msgstr[0] ""
1282
+ msgstr[1] ""
1283
+
1284
+ #: include/posts/class-bulk-delete-posts.php:1104
1285
+ msgid "Select the custom post type whose post you want to delete"
1286
  msgstr ""
1287
 
1288
+ #: include/posts/class-bulk-delete-posts.php:1189
1289
+ msgid "You don't have any posts assigned to custom post types in this blog."
1290
  msgstr ""
1291
 
1292
+ #: include/posts/class-bulk-delete-posts.php:1222
1293
+ msgid "Posts from the selected custom post type are scheduled for deletion."
1294
  msgstr ""
1295
 
1296
+ #: include/posts/class-bulk-delete-posts.php:1226
1297
+ msgid "Deleted %d post from the selected custom post type"
1298
+ msgid_plural "Deleted %d posts from the selected custom post type"
1299
+ msgstr[0] ""
1300
+ msgstr[1] ""
1301
+
1302
+ #: include/posts/class-bulk-delete-posts.php:1316
1303
+ msgid "Delete posts and pages that have the following Permalink"
1304
  msgstr ""
1305
 
1306
+ #: include/posts/class-bulk-delete-posts.php:1322
1307
+ msgid "Enter one post url (not post ids) per line"
1308
  msgstr ""
1309
 
1310
+ #: include/posts/class-bulk-delete-posts.php:1377
1311
+ msgid "Deleted %d post with the specified urls"
1312
+ msgid_plural "Deleted %d posts with the specified urls"
1313
+ msgstr[0] ""
1314
+ msgstr[1] ""
1315
+
1316
+ #: include/posts/class-bulk-delete-posts.php:1411
1317
+ msgid "All Revisions"
1318
  msgstr ""
1319
 
1320
+ #: include/posts/class-bulk-delete-posts.php:1411
1321
+ msgid "Revisions"
 
 
1322
  msgstr ""
1323
 
1324
+ #: include/posts/class-bulk-delete-posts.php:1435
1325
+ msgid "Deleted %d post revision"
1326
+ msgid_plural "Deleted %d post revisions"
1327
  msgstr[0] ""
1328
  msgstr[1] ""
1329
 
1330
+ #: include/posts/class-bulk-delete-posts.php:1487
1331
+ msgid ""
1332
+ "You need \"Bulk Delete Posts by Custom Field\" Addon, to delete post by "
1333
+ "custom field."
1334
  msgstr ""
1335
 
1336
+ #: include/posts/class-bulk-delete-posts.php:1516
1337
+ msgid "You need \"Bulk Delete Posts by Title\" Addon, to delete post by title."
 
1338
  msgstr ""
1339
 
1340
+ #: include/posts/class-bulk-delete-posts.php:1546
1341
+ msgid ""
1342
+ "You need \"Bulk Delete Posts by Duplicate Title\" Addon, to delete post by "
1343
+ "duplicate title."
1344
  msgstr ""
1345
 
1346
+ #: include/posts/class-bulk-delete-posts.php:1574
1347
+ msgid ""
1348
+ "You need \"Bulk Delete Posts by User Role\" Addon, to delete post based on "
1349
+ "User Role"
1350
  msgstr ""
1351
 
1352
+ #: include/posts/class-bulk-delete-posts.php:1602
1353
+ msgid "You need \"Bulk Delete From Trash\" Addon, to delete post in Trash."
1354
  msgstr ""
1355
 
1356
+ #: include/posts/class-bulk-delete-posts.php:1628
1357
+ msgid ""
1358
+ "Are you sure you want to delete all the posts based on the selected option?"
1359
  msgstr ""
1360
 
1361
+ #: include/posts/class-bulk-delete-posts.php:1629
1362
+ msgid "Please select posts from at least one option"
1363
  msgstr ""
1364
 
1365
+ #: include/posts/class-bulk-delete-posts.php:1633
1366
+ msgid "Please enter at least one post url"
1367
  msgstr ""
1368
 
1369
+ #: include/posts/class-bulk-delete-posts.php:1657
1370
+ msgid "The selected scheduled job was successfully deleted "
1371
  msgstr ""
1372
 
1373
+ #: include/settings/class-bd-settings-page.php:45
1374
+ #: include/settings/class-bd-settings-page.php:93
1375
+ msgid "Bulk Delete Settings"
 
1376
  msgstr ""
1377
 
1378
+ #: include/settings/class-bd-settings-page.php:46
1379
+ msgid "Settings"
 
 
1380
  msgstr ""
1381
 
1382
+ #: include/settings/class-bd-settings.php:28
1383
+ msgid "Add Addon License"
1384
+ msgstr ""
 
 
1385
 
1386
+ #: include/ui/admin-ui.php:19
1387
+ msgid ""
1388
+ "Thank you for using <a href = \"%1$s\">Bulk Delete</a> plugin! Kindly <a "
1389
+ "href = \"%2$s\">rate us</a> at <a href = \"%2$s\">WordPress.org</a>"
1390
  msgstr ""
1391
 
1392
+ #: include/ui/admin-ui.php:72
1393
+ msgid "Buy Addons"
1394
  msgstr ""
1395
 
1396
+ #: include/ui/class-bulk-delete-help-screen.php:32
1397
+ msgid "More information"
1398
  msgstr ""
1399
 
1400
+ #: include/ui/class-bulk-delete-help-screen.php:33
1401
+ msgid "Support Forums"
1402
  msgstr ""
1403
 
1404
+ #: include/ui/class-bulk-delete-help-screen.php:34
1405
+ msgid "Buy pro addons"
1406
  msgstr ""
1407
 
1408
+ #: include/ui/class-bulk-delete-help-screen.php:35
1409
+ msgid "Plugin author's blog"
1410
  msgstr ""
1411
 
1412
+ #: include/ui/class-bulk-delete-help-screen.php:36
1413
+ msgid "Other Plugin's by Author"
1414
+ msgstr ""
1415
+
1416
+ #: include/ui/class-bulk-delete-help-screen.php:57
1417
+ #: include/ui/class-bulk-delete-help-screen.php:69
1418
+ #: include/ui/class-bulk-delete-help-screen.php:81
1419
+ msgid "Overview"
1420
  msgstr ""
1421
 
1422
+ #: include/ui/class-bulk-delete-help-screen.php:59
1423
  msgid ""
1424
+ "This screen contains different modules that allows you to delete posts or "
1425
+ "schedule them for deletion."
1426
  msgstr ""
1427
 
1428
+ #: include/ui/class-bulk-delete-help-screen.php:71
1429
  msgid ""
1430
+ "This screen contains different modules that allows you to delete pages or "
1431
+ "schedule them for deletion."
1432
  msgstr ""
1433
 
1434
+ #: include/ui/class-bulk-delete-help-screen.php:83
1435
  msgid ""
1436
+ "This screen contains different modules that allows you to delete users or "
1437
+ "schedule them for deletion."
1438
  msgstr ""
1439
 
1440
+ #: include/ui/class-bulk-delete-help-screen.php:93
1441
+ msgid "About Plugin"
1442
+ msgstr ""
 
 
1443
 
1444
+ #: include/ui/class-bulk-delete-help-screen.php:116
1445
+ msgid "This plugin allows you to perform bulk operations in WordPress easily."
1446
  msgstr ""
1447
 
1448
+ #: include/ui/class-bulk-delete-help-screen.php:117
1449
+ msgid ""
1450
+ "This plugin can be used to delete the posts, pages or users using various "
1451
+ "filters and conditions."
1452
  msgstr ""
1453
 
1454
+ #: include/ui/class-bulk-delete-system-info.php:55
1455
+ msgid "System Information"
1456
  msgstr ""
1457
 
1458
+ #: include/ui/class-bulk-delete-system-info.php:63
1459
+ msgid "Please include this information when posting support requests."
1460
  msgstr ""
1461
 
1462
+ #: include/ui/class-bulk-delete-system-info.php:72
1463
+ msgid ""
1464
+ "To copy the system info, click below then press Ctrl + C (PC) or Cmd + C "
1465
+ "(Mac)."
1466
  msgstr ""
1467
 
1468
+ #: include/users/class-bulk-delete-users.php:23
1469
+ msgid "Select the user roles from which you want to delete users"
1470
+ msgstr ""
1471
+
1472
+ #: include/users/class-bulk-delete-users.php:56
1473
+ msgid "Only restrict to users who have not logged in the last "
1474
+ msgstr ""
1475
+
1476
+ #: include/users/class-bulk-delete-users.php:62
1477
+ msgid "Need Simple Login Log Plugin"
1478
  msgstr ""
1479
 
1480
+ #: include/users/class-bulk-delete-users.php:73
1481
  msgid ""
1482
+ "Only if user doesn't have any post. Only posts from 'post' post type would "
1483
+ "be considered."
1484
  msgstr ""
1485
 
1486
+ #: include/users/class-bulk-delete-users.php:83
1487
  msgid ""
1488
+ "Use this option if there are more than 1000 users or the script timesout."
 
1489
  msgstr ""
1490
 
1491
+ #: include/users/class-bulk-delete-users.php:149
1492
+ msgid "Users from the selected userrole are scheduled for deletion."
1493
+ msgstr ""
1494
+
1495
+ #: include/users/class-bulk-delete-users.php:153
1496
+ msgid "Deleted %d user from the selected roles"
1497
+ msgid_plural "Deleted %d users from the selected role"
1498
  msgstr[0] ""
1499
  msgstr[1] ""
1500
 
1501
+ #: include/users/class-bulk-delete-users.php:227
1502
+ msgid ""
1503
+ "Are you sure you want to delete all the users from the selected user role?"
 
 
 
 
1504
  msgstr ""
1505
 
1506
+ #: include/users/class-bulk-delete-users.php:230
1507
+ msgid "Select at least one user role from which users should be deleted"
 
1508
  msgstr ""
1509
 
1510
+ #: include/util/class-bd-util.php:131
1511
+ msgctxt "Cron table date format"
1512
+ msgid "M j, Y @ G:i"
1513
  msgstr ""
1514
 
1515
  #: tmp_addon/bulk-delete-attachments.php:118
1569
  #: tmp_addon/bulk-delete-posts-by-custom-field.php:501
1570
  #: tmp_addon/bulk-delete-posts-by-duplicate-title.php:354
1571
  #: tmp_addon/bulk-delete-posts-by-title.php:410
1572
+ #: tmp_addon/bulk-delete-posts-by-user-role.php:322
1573
+ #: tmp_addon/bulk-delete-posts-by-user.php:335
1574
  #: tmp_addon/bulk-delete-scheduler-email.php:335
1575
  #: tmp_addon/bulk-delete-scheduler-for-deleting-attachments.php:112
1576
  #: tmp_addon/bulk-delete-scheduler-for-deleting-pages-by-status.php:108
1584
  #: tmp_addon/bulk-delete-scheduler-for-deleting-posts-by-tag.php:108
1585
  #: tmp_addon/bulk-delete-scheduler-for-deleting-posts-by-taxonomy.php:103
1586
  #: tmp_addon/bulk-delete-scheduler-for-deleting-posts-by-user-role.php:108
1587
+ #: tmp_addon/bulk-delete-scheduler-for-deleting-posts-by-user.php:129
1588
  #: tmp_addon/bulk-delete-scheduler-for-deleting-users-by-role.php:108
1589
  #: tmp_addon/bulk-delete-user-meta.php:213
1590
  msgid ""
2092
  msgstr ""
2093
 
2094
  #: tmp_addon/bulk-delete-posts-by-user-role.php:104
2095
+ #: tmp_addon/bulk-delete-posts-by-user.php:148
2096
  msgid "Select the post types from which you want to delete posts"
2097
  msgstr ""
2098
 
2099
  #: tmp_addon/bulk-delete-posts-by-user-role.php:154
2100
+ #: tmp_addon/bulk-delete-posts-by-user.php:198
2101
  msgid ""
2102
  "Use this option if there are more than 1000 posts or the script timesout."
2103
  msgstr ""
2112
  msgstr[0] ""
2113
  msgstr[1] ""
2114
 
2115
+ #: tmp_addon/bulk-delete-posts-by-user-role.php:302
2116
  msgid ""
2117
  "Are you sure you want to delete all the posts that belong to the selected "
2118
  "user role?"
2119
  msgstr ""
2120
 
2121
+ #: tmp_addon/bulk-delete-posts-by-user-role.php:305
2122
  msgid "Please select the user role from which you want to delete posts"
2123
  msgstr ""
2124
 
2125
+ #: tmp_addon/bulk-delete-posts-by-user.php:109
2126
+ msgid "By User"
2127
+ msgstr ""
2128
+
2129
+ #: tmp_addon/bulk-delete-posts-by-user.php:127
2130
+ msgid "Select the user whose posts you want to delete"
2131
+ msgstr ""
2132
+
2133
+ #: tmp_addon/bulk-delete-posts-by-user.php:264
2134
+ msgid "Posts belonging to the selected user are scheduled for deletion."
2135
+ msgstr ""
2136
+
2137
+ #: tmp_addon/bulk-delete-posts-by-user.php:268
2138
+ msgid "Deleted %d post belonging to the selected user"
2139
+ msgid_plural "Deleted %d posts belonging to the selected user"
2140
+ msgstr[0] ""
2141
+ msgstr[1] ""
2142
+
2143
+ #: tmp_addon/bulk-delete-posts-by-user.php:316
2144
+ msgid ""
2145
+ "Are you sure you want to delete all the posts belonging to the selected user?"
2146
+ msgstr ""
2147
+
2148
  #: tmp_addon/bulk-delete-scheduler-email.php:91
2149
  msgid "Scheduler Email Settings"
2150
  msgstr ""
readme.txt CHANGED
@@ -1,10 +1,12 @@
1
  === Bulk Delete ===
2
  Contributors: sudar
3
- Tags: post, comment, delete, bulk, mass, draft, revision, page, meta fields
4
  Requires at least: 3.9
5
- Tested up to: 4.1
6
  Donate Link: http://sudarmuthu.com/if-you-wanna-thank-me
7
- Stable tag: 5.4.1
 
 
8
 
9
  Bulk delete posts, pages, users and meta fields in bulk based on different conditions and filters.
10
 
@@ -28,7 +30,6 @@ This Plugin supports the following bulk delete options for deleting posts
28
  - Delete posts by custom field (Available as a [Pro addon](http://bulkwp.com/addons/bulk-delete-posts-by-custom-field/?utm_source=wprepo&utm_campaign=BulkDelete&utm_medium=readme&utm_content=bd-cf))
29
  - Delete posts by title (Available as a [Pro addon](http://bulkwp.com/addons/bulk-delete-posts-by-title/?utm_source=wprepo&utm_campaign=BulkDelete&utm_medium=readme&utm_content=bd-ti))
30
  - Delete posts by duplicate title (Available as a [Pro addon](http://bulkwp.com/addons/bulk-delete-posts-by-duplicate-title/?utm_source=wprepo&utm_campaign=BulkDelete&utm_medium=readme&utm_content=bd-dti))
31
- - Delete posts by user role (Available as a [Pro addon](http://bulkwp.com/addons/bulk-delete-posts-by-user-role/?utm_source=wprepo&utm_campaign=BulkDelete&utm_medium=readme&utm_content=bd-ti))
32
  - Delete all draft posts
33
  - Delete all pending posts
34
  - Delete all private posts
@@ -47,9 +48,15 @@ All the above options support the following filters
47
 
48
  #### Deleting posts by content
49
 
 
50
  - Delete duplicate posts by title (Available as a [Pro addon](http://bulkwp.com/addons/bulk-delete-posts-by-duplicate-title/?utm_source=wprepo&utm_campaign=BulkDelete&utm_medium=readme&utm_content=bd-dti))
51
  - Delete posts based on whether it contains attachment or not (Available as a [Pro addon](http://bulkwp.com/addons/bulk-delete-posts-by-attachment/?utm_source=wprepo&utm_campaign=BulkDelete&utm_medium=readme&utm_content=bd-p-at))
52
 
 
 
 
 
 
53
  #### Deleting pages
54
 
55
  - Delete all published pages
@@ -76,6 +83,7 @@ Like posts, all the above options support the following filters as well
76
  #### Deleting users
77
 
78
  - Delete users based on user role
 
79
  - Delete users who have not logged in in the last X days
80
 
81
  #### Deleting Meta Fields
@@ -83,6 +91,10 @@ Like posts, all the above options support the following filters as well
83
  - Delete Comment meta fields
84
  - Delete User meta fields
85
 
 
 
 
 
86
  #### Deleting other items
87
  - Delete Jetpack Contact Form Messages
88
 
@@ -97,9 +109,12 @@ If you looking for just moving posts, instead of deleting, then use [Bulk Move P
97
  The following are the popular pro addons that are available for purchase. The full list of [pro addons](http://bulkwp.com/addons/?utm_source=wprepo&utm_campaign=BulkDelete&utm_medium=readme&utm_content=pro) is available at the plugin site.
98
 
99
  - **Delete posts by custom field** - Adds the ability to delete posts based on custom field. [More details](http://bulkwp.com/addons/bulk-delete-posts-by-custom-field/?utm_source=wprepo&utm_campaign=BulkDelete&utm_medium=readme&utm_content=bd-cf).
 
 
100
  - **Delete posts by title** - Adds the ability to delete posts based on title. [More details](http://bulkwp.com/addons/bulk-delete-posts-by-title/?utm_source=wprepo&utm_campaign=BulkDelete&utm_medium=readme&utm_content=bd-ti).
101
  - **Delete posts by duplicate title** - Adds the ability to delete posts based on duplicate title. [More details](http://bulkwp.com/addons/bulk-delete-posts-by-duplicate-title/?utm_source=wprepo&utm_campaign=BulkDelete&utm_medium=readme&utm_content=bd-dti).
102
  - **Delete posts by user role** - Adds the ability to delete posts based on user role. [More details](http://bulkwp.com/addons/bulk-delete-posts-by-user-role/?utm_source=wprepo&utm_campaign=BulkDelete&utm_medium=readme&utm_content=bd-ur).
 
103
  - **Delete from trash** - Adds the ability to delete posts and pages from trash. [More details](http://bulkwp.com/addons/bulk-delete-from-trash/?utm_source=wprepo&utm_campaign=BulkDelete&utm_medium=readme&utm_content=bd-dh).
104
  - **Scheduler Email** - Sends email whenever a Bulk WP Scheduler runs. [More details](http://bulkwp.com/addons/scheduler-email/?utm_source=wprepo&utm_campaign=BulkDelete&utm_medium=readme&utm_content=bd-se).
105
  - **Scheduler for deleting posts Category** - Adds the ability to schedule auto delete of posts based on category. [More details](http://bulkwp.com/addons/scheduler-for-deleting-posts-by-category/?utm_source=wprepo&utm_campaign=BulkDelete&utm_medium=readme&utm_content=bd-sc).
@@ -109,9 +124,11 @@ The following are the popular pro addons that are available for purchase. The fu
109
  - **Scheduler for deleting posts by Post Status** - Adds the ability to schedule auto delete of posts based on post status like drafts, pending posts, scheduled posts etc. [More details](http://bulkwp.com/addons/scheduler-for-deleting-posts-by-status/?utm_source=wprepo&utm_campaign=BulkDelete&utm_medium=readme&utm_content=bd-sps).
110
  - **Scheduler for deleting pages by status** - Adds the ability to schedule auto delete of pages based on status. [More details](http://bulkwp.com/addons/scheduler-for-deleting-pages-by-status/?utm_source=wprepo&utm_campaign=BulkDelete&utm_medium=readme&utm_content=bd-sp).
111
  - **Scheduler for deleting users by User Role** - Adds the ability to schedule auto delete of users based on user role. [More details](http://bulkwp.com/addons/scheduler-for-deleting-users-by-role/?utm_source=wprepo&utm_campaign=BulkDelete&utm_medium=readme&utm_content=bd-u-ur).
 
112
  - **Delete Post Meta Fields Pro** - Adds the ability to delete post meta fields based on value and to schedule automatic deletion. [More details](http://bulkwp.com/addons/bulk-delete-post-meta/?utm_source=wprepo&utm_campaign=BulkDelete&utm_medium=readme&utm_content=bd-m-p).
113
  - **Delete Comment Meta Fields Pro** - Adds the ability to delete comment meta fields based on value and to schedule automatic deletion. [More details](http://bulkwp.com/addons/bulk-delete-comment-meta/?utm_source=wprepo&utm_campaign=BulkDelete&utm_medium=readme&utm_content=bd-m-c).
114
  - **Delete User Meta Fields Pro** - Adds the ability to delete user meta fields based on value and to schedule automatic deletion. [More details](http://bulkwp.com/addons/bulk-delete-user-meta/?utm_source=wprepo&utm_campaign=BulkDelete&utm_medium=readme&utm_content=bd-m-u).
 
115
  - **Delete Jetpack Contact Form Messages Pro** - Adds the ability to delete Jetpack Contact Form Messages based on filters and to schedule automatic deletion. [More details](http://bulkwp.com/addons/bulk-delete-jetpack-contact-form-messages/?utm_source=wprepo&utm_campaign=BulkDelete&utm_medium=readme&utm_content=bd-jcm).
116
 
117
  ### Development
@@ -247,6 +264,24 @@ You can contact us by posting about it in our [support forum](http://bulkwp.com/
247
  This Readme file was generated using <a href = 'http://sudarmuthu.com/wordpress/wp-readme'>wp-readme</a>, which generates readme files for WordPress Plugins.
248
  == Changelog ==
249
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
250
  = 2015-02-14 - v5.4.1 - (Dev time: 0.5 hours) =
251
  - Tweak: Use Google CDN for jQuery UI CSS, instead of ASP.NET
252
 
@@ -255,7 +290,7 @@ This Readme file was generated using <a href = 'http://sudarmuthu.com/wordpress/
255
  - New: Added the ability to delete comment meta fields (Issue #70)
256
  - New: Added the ability to delete user meta fields (Issue #87)
257
  - New: (Addon) Added the ability to delete posts based on attachment
258
- - New: Added the ability to hook into JavaScript message, date picker and validation (Issue ===82, ===83, #84)
259
  - New: Prevent PHP from timing out while performing bulk operations(Issue #81)
260
 
261
  - Tweak: Group memory related info together in system info output
@@ -483,6 +518,9 @@ This Readme file was generated using <a href = 'http://sudarmuthu.com/wordpress/
483
 
484
  == Upgrade Notice ==
485
 
 
 
 
486
  = 5.4.1 =
487
  Changed jQuery UI CSS CDN to Google CDN from ASP.NET, which seems to be discontinued
488
 
1
  === Bulk Delete ===
2
  Contributors: sudar
3
+ Tags: mass, bulk, delete, post, comment, draft, revision, page, user, meta fields
4
  Requires at least: 3.9
5
+ Tested up to: 4.2.3
6
  Donate Link: http://sudarmuthu.com/if-you-wanna-thank-me
7
+ Stable tag: 5.5
8
+
9
+ [![Build Status](https://scrutinizer-ci.com/g/sudar/bulk-delete/badges/build.png?b=master)](https://scrutinizer-ci.com/g/sudar/bulk-delete/build-status/master) [![Scrutinizer Code Quality](https://scrutinizer-ci.com/g/sudar/bulk-delete/badges/quality-score.png?b=master)](https://scrutinizer-ci.com/g/sudar/bulk-delete/?branch=master)
10
 
11
  Bulk delete posts, pages, users and meta fields in bulk based on different conditions and filters.
12
 
30
  - Delete posts by custom field (Available as a [Pro addon](http://bulkwp.com/addons/bulk-delete-posts-by-custom-field/?utm_source=wprepo&utm_campaign=BulkDelete&utm_medium=readme&utm_content=bd-cf))
31
  - Delete posts by title (Available as a [Pro addon](http://bulkwp.com/addons/bulk-delete-posts-by-title/?utm_source=wprepo&utm_campaign=BulkDelete&utm_medium=readme&utm_content=bd-ti))
32
  - Delete posts by duplicate title (Available as a [Pro addon](http://bulkwp.com/addons/bulk-delete-posts-by-duplicate-title/?utm_source=wprepo&utm_campaign=BulkDelete&utm_medium=readme&utm_content=bd-dti))
 
33
  - Delete all draft posts
34
  - Delete all pending posts
35
  - Delete all private posts
48
 
49
  #### Deleting posts by content
50
 
51
+ - Delete posts by content (Available as a [Pro addon](http://bulkwp.com/addons/bulk-delete-posts-by-content/?utm_source=wprepo&utm_campaign=BulkDelete&utm_medium=readme&utm_content=bd-p-co))
52
  - Delete duplicate posts by title (Available as a [Pro addon](http://bulkwp.com/addons/bulk-delete-posts-by-duplicate-title/?utm_source=wprepo&utm_campaign=BulkDelete&utm_medium=readme&utm_content=bd-dti))
53
  - Delete posts based on whether it contains attachment or not (Available as a [Pro addon](http://bulkwp.com/addons/bulk-delete-posts-by-attachment/?utm_source=wprepo&utm_campaign=BulkDelete&utm_medium=readme&utm_content=bd-p-at))
54
 
55
+ #### Deleting posts by user
56
+
57
+ - Delete posts by user role (Available as a [Pro addon](http://bulkwp.com/addons/bulk-delete-posts-by-user-role/?utm_source=wprepo&utm_campaign=BulkDelete&utm_medium=readme&utm_content=bd-ur))
58
+ - Delete posts by user (Available as a [Pro addon](http://bulkwp.com/addons/bulk-delete-posts-by-user/?utm_source=wprepo&utm_campaign=BulkDelete&utm_medium=readme&utm_content=bd-p-u))
59
+
60
  #### Deleting pages
61
 
62
  - Delete all published pages
83
  #### Deleting users
84
 
85
  - Delete users based on user role
86
+ - Delete users based on user meta fields
87
  - Delete users who have not logged in in the last X days
88
 
89
  #### Deleting Meta Fields
91
  - Delete Comment meta fields
92
  - Delete User meta fields
93
 
94
+ #### Deleting Meta Fields
95
+
96
+ - Delete Attachments (Available as a [Pro addon](http://bulkwp.com/addons/bulk-delete-attachments/?utm_source=wprepo&utm_campaign=BulkDelete&utm_medium=readme&utm_content=bd-at))
97
+
98
  #### Deleting other items
99
  - Delete Jetpack Contact Form Messages
100
 
109
  The following are the popular pro addons that are available for purchase. The full list of [pro addons](http://bulkwp.com/addons/?utm_source=wprepo&utm_campaign=BulkDelete&utm_medium=readme&utm_content=pro) is available at the plugin site.
110
 
111
  - **Delete posts by custom field** - Adds the ability to delete posts based on custom field. [More details](http://bulkwp.com/addons/bulk-delete-posts-by-custom-field/?utm_source=wprepo&utm_campaign=BulkDelete&utm_medium=readme&utm_content=bd-cf).
112
+ - **Delete posts by content** - Adds the ability to delete posts based on content. [More details](http://bulkwp.com/addons/bulk-delete-posts-by-content/?utm_source=wprepo&utm_campaign=BulkDelete&utm_medium=readme&utm_content=bd-p-co).
113
+ - **Delete posts by attachment** - Adds the ability to delete posts based on attachment [More details](http://bulkwp.com/addons/bulk-delete-posts-by-attachment/?utm_source=wprepo&utm_campaign=BulkDelete&utm_medium=readme&utm_content=bd-p-at).
114
  - **Delete posts by title** - Adds the ability to delete posts based on title. [More details](http://bulkwp.com/addons/bulk-delete-posts-by-title/?utm_source=wprepo&utm_campaign=BulkDelete&utm_medium=readme&utm_content=bd-ti).
115
  - **Delete posts by duplicate title** - Adds the ability to delete posts based on duplicate title. [More details](http://bulkwp.com/addons/bulk-delete-posts-by-duplicate-title/?utm_source=wprepo&utm_campaign=BulkDelete&utm_medium=readme&utm_content=bd-dti).
116
  - **Delete posts by user role** - Adds the ability to delete posts based on user role. [More details](http://bulkwp.com/addons/bulk-delete-posts-by-user-role/?utm_source=wprepo&utm_campaign=BulkDelete&utm_medium=readme&utm_content=bd-ur).
117
+ - **Delete posts by user** - Adds the ability to delete posts based on user. [More details](http://bulkwp.com/addons/bulk-delete-posts-by-user/?utm_source=wprepo&utm_campaign=BulkDelete&utm_medium=readme&utm_content=bd-p-u).
118
  - **Delete from trash** - Adds the ability to delete posts and pages from trash. [More details](http://bulkwp.com/addons/bulk-delete-from-trash/?utm_source=wprepo&utm_campaign=BulkDelete&utm_medium=readme&utm_content=bd-dh).
119
  - **Scheduler Email** - Sends email whenever a Bulk WP Scheduler runs. [More details](http://bulkwp.com/addons/scheduler-email/?utm_source=wprepo&utm_campaign=BulkDelete&utm_medium=readme&utm_content=bd-se).
120
  - **Scheduler for deleting posts Category** - Adds the ability to schedule auto delete of posts based on category. [More details](http://bulkwp.com/addons/scheduler-for-deleting-posts-by-category/?utm_source=wprepo&utm_campaign=BulkDelete&utm_medium=readme&utm_content=bd-sc).
124
  - **Scheduler for deleting posts by Post Status** - Adds the ability to schedule auto delete of posts based on post status like drafts, pending posts, scheduled posts etc. [More details](http://bulkwp.com/addons/scheduler-for-deleting-posts-by-status/?utm_source=wprepo&utm_campaign=BulkDelete&utm_medium=readme&utm_content=bd-sps).
125
  - **Scheduler for deleting pages by status** - Adds the ability to schedule auto delete of pages based on status. [More details](http://bulkwp.com/addons/scheduler-for-deleting-pages-by-status/?utm_source=wprepo&utm_campaign=BulkDelete&utm_medium=readme&utm_content=bd-sp).
126
  - **Scheduler for deleting users by User Role** - Adds the ability to schedule auto delete of users based on user role. [More details](http://bulkwp.com/addons/scheduler-for-deleting-users-by-role/?utm_source=wprepo&utm_campaign=BulkDelete&utm_medium=readme&utm_content=bd-u-ur).
127
+ - **Scheduler for deleting users by User Meta** - Adds the ability to schedule auto delete of users based on user meta. [More details](http://bulkwp.com/addons/scheduler-for-deleting-users-by-meta/?utm_source=wprepo&utm_campaign=BulkDelete&utm_medium=readme&utm_content=bds-u-ma).
128
  - **Delete Post Meta Fields Pro** - Adds the ability to delete post meta fields based on value and to schedule automatic deletion. [More details](http://bulkwp.com/addons/bulk-delete-post-meta/?utm_source=wprepo&utm_campaign=BulkDelete&utm_medium=readme&utm_content=bd-m-p).
129
  - **Delete Comment Meta Fields Pro** - Adds the ability to delete comment meta fields based on value and to schedule automatic deletion. [More details](http://bulkwp.com/addons/bulk-delete-comment-meta/?utm_source=wprepo&utm_campaign=BulkDelete&utm_medium=readme&utm_content=bd-m-c).
130
  - **Delete User Meta Fields Pro** - Adds the ability to delete user meta fields based on value and to schedule automatic deletion. [More details](http://bulkwp.com/addons/bulk-delete-user-meta/?utm_source=wprepo&utm_campaign=BulkDelete&utm_medium=readme&utm_content=bd-m-u).
131
+ - **Delete attachment** - Adds the ability to delete attachments [More details](http://bulkwp.com/addons/bulk-delete-attachments/?utm_source=wprepo&utm_campaign=BulkDelete&utm_medium=readme&utm_content=bd-at).
132
  - **Delete Jetpack Contact Form Messages Pro** - Adds the ability to delete Jetpack Contact Form Messages based on filters and to schedule automatic deletion. [More details](http://bulkwp.com/addons/bulk-delete-jetpack-contact-form-messages/?utm_source=wprepo&utm_campaign=BulkDelete&utm_medium=readme&utm_content=bd-jcm).
133
 
134
  ### Development
264
  This Readme file was generated using <a href = 'http://sudarmuthu.com/wordpress/wp-readme'>wp-readme</a>, which generates readme files for WordPress Plugins.
265
  == Changelog ==
266
 
267
+ = 2015-07-21 - v5.5 (Dev time: 50 hours) =
268
+ - New Features
269
+ - Added the ability to delete users based on user meta. (Issue #79)
270
+ - Improved the UI of dropdowns. (Issue #101)
271
+ - (Addon) Added the ability to delete attachments. (Issue #98)
272
+
273
+ - Enhancements
274
+ - Tweaked the code that generates the UI and lot of hidden improvements.
275
+ - Tweaked the code that retrieves Mysql version. (Issue #102)
276
+ - Tweaked the license handling code. (Issue #92)
277
+ - Tweaked the build process
278
+ - Use compressed JS and CSS files for better performance. (Issue #62)
279
+
280
+ = 2015-03-03 - v5.4.2 (Dev time: 5.0 hours) =
281
+ - Tweak: Improve performance of DB queries to prevent timeouts. (Issue #93)
282
+ - Tweak: Add details about different post types in system info. (Issue #100)
283
+ - Tweak: Add details about timezone settings in system info. (Issue #100)
284
+
285
  = 2015-02-14 - v5.4.1 - (Dev time: 0.5 hours) =
286
  - Tweak: Use Google CDN for jQuery UI CSS, instead of ASP.NET
287
 
290
  - New: Added the ability to delete comment meta fields (Issue #70)
291
  - New: Added the ability to delete user meta fields (Issue #87)
292
  - New: (Addon) Added the ability to delete posts based on attachment
293
+ - New: Added the ability to hook into JavaScript message, date picker and validation (Issue 82, 83, 84)
294
  - New: Prevent PHP from timing out while performing bulk operations(Issue #81)
295
 
296
  - Tweak: Group memory related info together in system info output
518
 
519
  == Upgrade Notice ==
520
 
521
+ = 5.5 =
522
+ Added the ability to delete users based on user meta and lot of UI improvement
523
+
524
  = 5.4.1 =
525
  Changed jQuery UI CSS CDN to Google CDN from ASP.NET, which seems to be discontinued
526
 
style/jquery-ui-timepicker.css DELETED
@@ -1,10 +0,0 @@
1
- .ui-timepicker-div .ui-widget-header { margin-bottom: 8px; }
2
- .ui-timepicker-div dl { text-align: left; }
3
- .ui-timepicker-div dl dt { height: 25px; margin-bottom: -25px; }
4
- .ui-timepicker-div dl dd { margin: 0 10px 10px 65px; }
5
- .ui-timepicker-div td { font-size: 90%; }
6
- .ui-tpicker-grid-label { background: none; border: none; margin: 0; padding: 0; }
7
-
8
- .ui-timepicker-rtl{ direction: rtl; }
9
- .ui-timepicker-rtl dl { text-align: right; }
10
- .ui-timepicker-rtl dl dd { margin: 0 65px 10px 10px; }