Health Check - Version 1.1.0

Version Description

Download this release

Release Info

Developer Clorith
Plugin Icon 128x128 Health Check
Version 1.1.0
Comparing to
See all releases

Code changes from version 1.0.1 to 1.1.0

assets/css/health-check.css CHANGED
@@ -1,149 +1,259 @@
1
- body.dashboard_page_health-check .health-check-table tbody td {
2
- width: 80%;
3
- }
4
-
5
- body.dashboard_page_health-check .health-check-table tbody td ul,
6
- body.dashboard_page_health-check .health-check-table tbody td ol {
7
- margin: 0;
8
- }
9
-
10
- body.dashboard_page_health-check .health-check-table thead th:first-child,
11
- body.dashboard_page_health-check .health-check-table tbody td:first-child {
12
- width: 20%;
13
- }
14
-
15
- body.dashboard_page_health-check .file-integrity-table thead th:first-child,
16
- body.dashboard_page_health-check .file-integrity-table tbody td:first-child,
17
- body.dashboard_page_health-check .file-integrity-table tfoot td:first-child {
18
- text-align: center;
19
- width: 80px;
20
- }
21
-
22
- body.dashboard_page_health-check #health-check-mail-check,
23
- body.dashboard_page_health-check #health-check-file-integrity {
24
- margin-bottom: 15px;
25
- }
26
-
27
- body.dashboard_page_health-check .pass:before,
28
- body.dashboard_page_health-check .good:before {
29
- content: "\f147";
30
- display: inline-block;
31
- color: #46b450;
32
- font-family: dashicons;
33
- }
34
-
35
- body.dashboard_page_health-check .warning:before {
36
- content: "\f460";
37
- display: inline-block;
38
- color: #ffb900;
39
- font-family: dashicons;
40
- }
41
-
42
- body.dashboard_page_health-check .info:before {
43
- content: "\f348";
44
- display: inline-block;
45
- color: #00a0d2;
46
- font-family: dashicons;
47
- }
48
-
49
- body.dashboard_page_health-check .fail:before,
50
- body.dashboard_page_health-check .error:before {
51
- content: "\f335";
52
- display: inline-block;
53
- color: #dc3232;
54
- font-family: dashicons;
55
- }
56
-
57
- .health-check-modal {
58
- display: none;
59
- position: fixed;
60
- z-index: 1000;
61
- padding-top: 100px;
62
- left: 0;
63
- top: 0;
64
- width: 100%;
65
- height: 100%;
66
- overflow: auto;
67
- background-color: rgb(0,0,0);
68
- background-color: rgba(0,0,0,0.4);
69
- }
70
- .health-check-modal.show {
71
- display: block;
72
- }
73
-
74
- .health-check-modal .modal-content {
75
- background-color: #fefefe;
76
- margin: auto;
77
- padding: 20px;
78
- border: 1px solid #888;
79
- width: 30%;
80
- }
81
-
82
- .health-check-modal .modal-content .modal-close {
83
- color: #aaaaaa;
84
- float: right;
85
- font-size: 28px;
86
- font-weight: bold;
87
- cursor: pointer;
88
- }
89
-
90
- .health-check-modal .modal-content #dynamic-content {
91
- display: block;
92
- width: 100%;
93
- }
94
-
95
- .health-check-modal .modal-close:hover,
96
- .health-check-modal .modal-close:focus {
97
- color: #aaaaaa;
98
- float: right;
99
- font-size: 28px;
100
- font-weight: bold;
101
- }
102
-
103
- body.dashboard_page_health-check #health-check-diff-modal {
104
- width: 100vw;
105
- height: 100%;
106
- position: fixed;
107
- display: block;
108
- top: 0;
109
- left: 0;
110
- background: rgba(0,0,0,0.7);
111
- display: none;
112
- z-index: 99999;
113
- }
114
-
115
- body.dashboard_page_health-check #health-check-diff-modal #health-check-diff-modal-content {
116
- background: #fff;
117
- height: calc( 100% - 120px );
118
- width: calc( 100% - 120px );
119
- margin-top: 40px;
120
- margin-left: 40px;
121
- padding: 20px;
122
- display: block;
123
- }
124
-
125
- body.dashboard_page_health-check #health-check-diff-modal #health-check-diff-modal-diff {
126
- width: 100%;
127
- height: calc( 100% - 80px );
128
- overflow-y: auto;
129
- display: block;
130
- position: relative;
131
- }
132
-
133
- body.dashboard_page_health-check #health-check-diff-modal #health-check-diff-modal-diff table.diff td:nth-child(2) {
134
- background: #f3f3f3;
135
- }
136
-
137
-
138
- body.dashboard_page_health-check #health-check-diff-modal-close-ref {
139
- position: relative;
140
- display: block;
141
- float: right;
142
- color: #000;
143
- text-decoration: none;
144
- }
145
-
146
- body.dashboard_page_health-check #health-check-diff-modal #health-check-diff-modal-content .spinner,
147
- body.dashboard_page_health-check #tools-response-holder .spinner {
148
- float: none;
149
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ body.dashboard_page_health-check {
2
+ /* Tools screen styles */
3
+ /* Diff viewer styles */
4
+ }
5
+
6
+ body.dashboard_page_health-check .health-check-table thead th:first-child,
7
+ body.dashboard_page_health-check .health-check-table thead td:first-child {
8
+ width: 20%;
9
+ }
10
+
11
+ body.dashboard_page_health-check .health-check-table tbody td {
12
+ width: 80%;
13
+ }
14
+
15
+ body.dashboard_page_health-check .health-check-table tbody td:first-child {
16
+ width: 20%;
17
+ }
18
+
19
+ body.dashboard_page_health-check .health-check-table tbody td ul,
20
+ body.dashboard_page_health-check .health-check-table tbody td ol {
21
+ margin: 0;
22
+ }
23
+
24
+ body.dashboard_page_health-check .pass:before,
25
+ body.dashboard_page_health-check .good:before {
26
+ content: "\f147";
27
+ display: inline-block;
28
+ color: #46b450;
29
+ font-family: dashicons;
30
+ }
31
+
32
+ body.dashboard_page_health-check .warning:before {
33
+ content: "\f460";
34
+ display: inline-block;
35
+ color: #ffb900;
36
+ font-family: dashicons;
37
+ }
38
+
39
+ body.dashboard_page_health-check .info:before {
40
+ content: "\f348";
41
+ display: inline-block;
42
+ color: #00a0d2;
43
+ font-family: dashicons;
44
+ }
45
+
46
+ body.dashboard_page_health-check .fail:before,
47
+ body.dashboard_page_health-check .error:before {
48
+ content: "\f335";
49
+ display: inline-block;
50
+ color: #dc3232;
51
+ font-family: dashicons;
52
+ }
53
+
54
+ body.dashboard_page_health-check .spinner {
55
+ float: none;
56
+ }
57
+
58
+ body.dashboard_page_health-check .file-integrity-table thead th:first-child,
59
+ body.dashboard_page_health-check .file-integrity-table thead td:first-child,
60
+ body.dashboard_page_health-check .file-integrity-table tbody th:first-child,
61
+ body.dashboard_page_health-check .file-integrity-table tbody td:first-child,
62
+ body.dashboard_page_health-check .file-integrity-table tfoot th:first-child,
63
+ body.dashboard_page_health-check .file-integrity-table tfoot td:first-child {
64
+ text-align: center;
65
+ width: 60px;
66
+ }
67
+
68
+ body.dashboard_page_health-check .tools-email-table {
69
+ border: 0;
70
+ box-shadow: none;
71
+ }
72
+
73
+ body.dashboard_page_health-check .tools-email-table td:first-child {
74
+ width: 280px;
75
+ }
76
+
77
+ @media (max-width: 768px) {
78
+ body.dashboard_page_health-check .tools-email-table td {
79
+ display: block;
80
+ }
81
+ }
82
+
83
+ body.dashboard_page_health-check .tools-email-table input {
84
+ width: 100%;
85
+ }
86
+
87
+ body.dashboard_page_health-check .tools-email-table label {
88
+ display: block;
89
+ clear: both;
90
+ }
91
+
92
+ body.dashboard_page_health-check #health-check-mail-check,
93
+ body.dashboard_page_health-check #health-check-file-integrity {
94
+ margin-bottom: 15px;
95
+ }
96
+
97
+ body.dashboard_page_health-check #health-check-diff-modal {
98
+ width: 100vw;
99
+ height: 100%;
100
+ position: fixed;
101
+ top: 0;
102
+ left: 0;
103
+ background: rgba(0, 0, 0, 0.7);
104
+ display: none;
105
+ z-index: 99999;
106
+ }
107
+
108
+ body.dashboard_page_health-check #health-check-diff-modal #health-check-diff-modal-content {
109
+ background: #fff;
110
+ height: calc(100% - 120px);
111
+ width: calc(100% - 120px);
112
+ margin-top: 40px;
113
+ margin-left: 40px;
114
+ padding: 20px;
115
+ display: block;
116
+ }
117
+
118
+ body.dashboard_page_health-check #health-check-diff-modal #health-check-diff-modal-diff {
119
+ width: 100%;
120
+ height: calc(100% - 80px);
121
+ overflow-y: auto;
122
+ display: block;
123
+ position: relative;
124
+ }
125
+
126
+ body.dashboard_page_health-check #health-check-diff-modal #health-check-diff-modal-diff table.diff td:nth-child(2) {
127
+ background: #f3f3f3;
128
+ }
129
+
130
+ body.dashboard_page_health-check #health-check-diff-modal-close-ref {
131
+ position: relative;
132
+ display: block;
133
+ float: right;
134
+ color: #000;
135
+ text-decoration: none;
136
+ }
137
+
138
+ /* Accordion styles */
139
+ .health-check-accordion {
140
+ border: 1px solid #d1d1d1;
141
+ border-radius: 0.3em;
142
+ box-shadow: 0 1px 2px #d1d1d1;
143
+ }
144
+
145
+ .health-check-accordion > * + * {
146
+ border-top: 1px solid #d1d1d1;
147
+ }
148
+
149
+ .health-check-accordion dt {
150
+ font-weight: 600;
151
+ }
152
+
153
+ .health-check-accordion dt:first-child {
154
+ border-radius: 0.3em 0.3em 0 0;
155
+ }
156
+
157
+ .health-check-accordion .health-check-accordion-trigger {
158
+ background: #fff;
159
+ border: 0;
160
+ color: #212121;
161
+ display: block;
162
+ font-size: 1rem;
163
+ font-weight: 400;
164
+ margin: 0;
165
+ padding: 1em 1.5em;
166
+ position: relative;
167
+ text-align: left;
168
+ width: 100%;
169
+ }
170
+
171
+ .health-check-accordion .health-check-accordion-trigger:hover, .health-check-accordion .health-check-accordion-trigger:focus, .health-check-accordion .health-check-accordion-trigger:active {
172
+ background: #dedede;
173
+ }
174
+
175
+ .health-check-accordion .health-check-accordion-trigger .title {
176
+ display: block;
177
+ pointer-events: none;
178
+ }
179
+
180
+ .health-check-accordion .health-check-accordion-trigger .icon {
181
+ border: solid #9e9e9e;
182
+ border-width: 0 2px 2px 0;
183
+ height: 0.5rem;
184
+ pointer-events: none;
185
+ position: absolute;
186
+ right: 1.5em;
187
+ top: 50%;
188
+ transform: translateY(-60%) rotate(45deg);
189
+ width: 0.5rem;
190
+ }
191
+
192
+ .health-check-accordion .health-check-accordion-trigger[aria-expanded="true"] .icon {
193
+ transform: translateY(-50%) rotate(-135deg);
194
+ }
195
+
196
+ .health-check-accordion .health-check-accordion-panel {
197
+ margin: 0;
198
+ padding: 1em 1.5em;
199
+ background: #fff;
200
+ }
201
+
202
+ .health-check-accordion .health-check-accordion-panel > div {
203
+ display: block;
204
+ }
205
+
206
+ .health-check-accordion .health-check-accordion-panel[hidden] {
207
+ display: none;
208
+ }
209
+
210
+ .health-check-accordion dl dd {
211
+ margin: 0 0 0.5em 2em;
212
+ }
213
+
214
+ /* Modal styles */
215
+ .health-check-modal {
216
+ display: none;
217
+ position: fixed;
218
+ z-index: 1000;
219
+ padding-top: 100px;
220
+ left: 0;
221
+ top: 0;
222
+ width: 100%;
223
+ height: 100%;
224
+ overflow: auto;
225
+ background-color: black;
226
+ background-color: rgba(0, 0, 0, 0.4);
227
+ }
228
+
229
+ .health-check-modal.show {
230
+ display: block;
231
+ }
232
+
233
+ .health-check-modal .modal-content {
234
+ background-color: #fefefe;
235
+ margin: auto;
236
+ padding: 20px;
237
+ border: 1px solid #888;
238
+ width: 30%;
239
+ }
240
+
241
+ .health-check-modal .modal-content .modal-close {
242
+ color: #aaa;
243
+ float: right;
244
+ font-size: 28px;
245
+ font-weight: 600;
246
+ cursor: pointer;
247
+ }
248
+
249
+ .health-check-modal .modal-content #dynamic-content {
250
+ display: block;
251
+ width: 100%;
252
+ }
253
+
254
+ .health-check-modal .modal-close:hover, .health-check-modal .modal-close:focus {
255
+ color: #aaa;
256
+ float: right;
257
+ font-size: 28px;
258
+ font-weight: 600;
259
+ }
assets/javascript/health-check.js CHANGED
@@ -1,165 +1,185 @@
1
- jQuery(document).ready(function ($) {
2
- function health_check_failure_modal( markup, action, parent ) {
3
- $("#dynamic-content").html( markup );
4
- $(".health-check-modal").data( 'modal-action', action ).data( 'parent-field', parent ).show();
5
- }
 
 
 
 
 
 
 
6
 
7
- function health_check_failure_modal_close( modal ) {
8
- modal.hide();
9
- }
 
 
 
 
 
 
 
 
 
 
 
 
10
 
11
- $(".modal-close").click(function (e) {
12
  e.preventDefault();
13
- health_check_failure_modal_close( $(this).closest('.health-check-modal') );
 
 
 
 
 
 
14
  });
 
15
 
16
- $(".health-check-toc").click(function (e) {
17
- e.preventDefault();
18
 
19
  // Remove the height of the admin bar, and an extra 10px for better positioning.
20
- var offset = $( $(this).attr('href') ).offset().top - $("#wpadminbar").height() - 10;
 
 
21
 
22
- $('html, body').animate({
23
  scrollTop: offset
24
- }, 1200);
25
  });
 
26
 
27
- $("#loopback-no-plugins").click(function (e) {
28
- var $trigger = $(this),
29
- $parent = $(this).closest('td');
 
 
 
30
 
31
- $(this).html( '<span class="spinner" style="visibility: visible;"></span> ' + health_check.string.please_wait );
 
 
32
 
 
33
  e.preventDefault();
 
 
34
 
35
- var data = {
36
- action: 'health-check-loopback-no-plugins'
37
- };
 
 
38
 
39
  $.post(
40
  ajaxurl,
41
  data,
42
- function (response) {
43
- $trigger.remove();
44
  if ( true === response.success ) {
45
- $parent.append(response.data.message);
46
  } else {
47
- health_check_failure_modal( response.data, data.action, $parent );
48
  }
49
- },
50
- 'json'
51
- )
52
- });
53
 
54
- $(".dashboard_page_health-check").on('click', '#loopback-individual-plugins', function (e) {
55
- var $trigger = $(this),
56
- $parent = $(this).closest('td');
57
 
58
- $(this).html( '<span class="spinner" style="visibility: visible;"></span> ' + health_check.string.please_wait );
 
 
 
 
 
 
 
59
 
60
  e.preventDefault();
61
 
62
- var data = {
63
- action: 'health-check-loopback-individual-plugins'
64
- };
65
 
66
  $.post(
67
  ajaxurl,
68
  data,
69
- function (response) {
70
  $trigger.remove();
71
  if ( true === response.success ) {
72
- $parent.append(response.data.message);
73
  } else {
74
- health_check_failure_modal( response.data, data.action, $parent );
75
  }
76
  },
77
  'json'
78
- )
79
  });
80
 
81
- $(".health-check-modal").on('submit', 'form', function (e) {
82
- var data = $(this).serializeArray(),
83
- modal = $(this).closest('.health-check-modal');
 
 
 
84
 
85
  e.preventDefault();
86
 
 
 
87
  $.post(
88
  ajaxurl,
89
  data,
90
- function (response) {
 
91
  if ( true === response.success ) {
92
- $( modal.data('parent-field') ).append(response.data.message);
93
  } else {
94
- health_check_failure_modal( response.data.message, data.action, modal.data('parent-field') );
95
  }
96
- }
 
97
  );
98
-
99
- health_check_failure_modal_close( modal );
100
- });
101
-
102
- $(".health-check-copy-field").click(function (e) {
103
- e.preventDefault();
104
-
105
- var $textarea = $( 'textarea', $(this).closest('div') ),
106
- $button = $(this);
107
-
108
- $textarea.select();
109
-
110
- var copied = document.execCommand( 'copy' );
111
- if ( copied ) {
112
- $button.text( health_check.string.copied );
113
- }
114
  });
 
115
 
 
 
116
  $( '#health-check-file-integrity' ).submit( function( e ) {
117
- e.preventDefault();
118
- $( '#tools-response-holder' ).html( '<span class="spinner"></span>' );
119
- $( '#tools-response-holder .spinner' ).addClass( 'is-active' );
120
-
121
  var data = {
122
  'action': 'health-check-files-integrity-check'
123
  };
124
 
125
- $.post(
126
- ajaxurl,
127
- data,
128
- function( response ) {
129
- $( '#tools-response-holder .spinner' ).removeClass( 'is-active' );
130
- $( '#tools-response-holder').html( response.data.message );
131
- });
132
- });
133
-
134
- $( '#health-check-mail-check' ).submit( function( e ) {
135
  e.preventDefault();
136
- var email = $('#health-check-mail-check #email').val();
137
- $( '#tools-response-holder' ).html( '<span class="spinner"></span>' );
138
- $( '#tools-response-holder .spinner' ).addClass( 'is-active' );
139
 
140
- var data = {
141
- 'action': 'health-check-mail-check',
142
- 'email' : email
143
- };
144
 
145
  $.post(
146
  ajaxurl,
147
  data,
148
  function( response ) {
149
- $( '#tools-response-holder .spinner' ).removeClass( 'is-active' );
150
- $( '#tools-response-holder').html( response.data.message );
151
- });
 
 
152
  });
153
 
154
- $( '#tools-response-holder' ).on( 'click', 'a[href="#health-check-diff"]', function( e ) {
 
 
 
155
  e.preventDefault();
156
- var file = $( this ).data('file');
157
  $( '#health-check-diff-modal' ).toggle();
158
  $( '#health-check-diff-modal #health-check-diff-modal-content .spinner' ).addClass( 'is-active' );
159
 
160
- var data = {
161
  'action': 'health-check-view-file-diff',
162
- 'file' : file
163
  };
164
 
165
  $.post(
@@ -169,12 +189,54 @@ jQuery(document).ready(function ($) {
169
  $( '#health-check-diff-modal #health-check-diff-modal-diff' ).html( response.data.message );
170
  $( '#health-check-diff-modal #health-check-diff-modal-content h3' ).html( file );
171
  $( '#health-check-diff-modal #health-check-diff-modal-content .spinner' ).removeClass( 'is-active' );
172
- });
 
173
  });
 
174
 
 
175
  $( '#health-check-diff-modal' ).on( 'click', 'a[href="#health-check-diff-modal-close"]', function( e ) {
176
  e.preventDefault();
177
  $( '#health-check-diff-modal' ).toggle();
 
 
 
 
 
 
 
 
 
 
178
  });
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
179
 
 
 
 
 
 
 
 
 
 
 
180
  });
1
+ jQuery( document ).ready(function( $ ) {
2
+ $( '.health-check-accordion-trigger' ).click(function() {
3
+ var isExpanded = ( 'true' === $( this ).attr( 'aria-expanded' ) );
4
+
5
+ if ( isExpanded ) {
6
+ $( this ).attr( 'aria-expanded', 'false' );
7
+ $( '#' + $( this ).attr( 'aria-controls' ) ).attr( 'hidden', true );
8
+ } else {
9
+ $( this ).attr( 'aria-expanded', 'true' );
10
+ $( '#' + $( this ).attr( 'aria-controls' ) ).attr( 'hidden', false );
11
+ }
12
+ });
13
 
14
+ $( '.health-check-accordion' ).on( 'keyup', '.health-check-accordion-trigger', function( e ) {
15
+ if ( '38' === e.keyCode.toString() ) {
16
+ $( '.health-check-accordion-trigger', $( this ).closest( 'dt' ).prevAll( 'dt' ) ).focus();
17
+ } else if ( '40' === e.keyCode.toString() ) {
18
+ $( '.health-check-accordion-trigger', $( this ).closest( 'dt' ).nextAll( 'dt' ) ).focus();
19
+ }
20
+ });
21
+ });
22
+
23
+ /* global HealthCheck */
24
+ jQuery( document ).ready(function( $ ) {
25
+ $( '.health-check-copy-field' ).click(function( e ) {
26
+ var $textarea = $( 'textarea', $( this ).closest( 'div' ) ),
27
+ $button = $( this ),
28
+ copied = false;
29
 
 
30
  e.preventDefault();
31
+
32
+ $textarea.select();
33
+
34
+ copied = document.execCommand( 'copy' );
35
+ if ( copied ) {
36
+ $button.text( HealthCheck.string.copied );
37
+ }
38
  });
39
+ });
40
 
41
+ jQuery( document ).ready(function( $ ) {
42
+ $( '.health-check-toc' ).click(function( e ) {
43
 
44
  // Remove the height of the admin bar, and an extra 10px for better positioning.
45
+ var offset = $( $( this ).attr( 'href' ) ).offset().top - $( '#wpadminbar' ).height() - 10;
46
+
47
+ e.preventDefault();
48
 
49
+ $( 'html, body' ).animate({
50
  scrollTop: offset
51
+ }, 1200 );
52
  });
53
+ });
54
 
55
+ /* global ajaxurl */
56
+ jQuery( document ).ready(function( $ ) {
57
+ function healthCheckFailureModal( markup, action, parent ) {
58
+ $( '#dynamic-content' ).html( markup );
59
+ $( '.health-check-modal' ).data( 'modal-action', action ).data( 'parent-field', parent ).show();
60
+ }
61
 
62
+ function healthCheckFailureModalClose( modal ) {
63
+ modal.hide();
64
+ }
65
 
66
+ $( '.modal-close' ).click(function( e ) {
67
  e.preventDefault();
68
+ healthCheckFailureModalClose( $( this ).closest( '.health-check-modal' ) );
69
+ });
70
 
71
+ $( '.health-check-modal' ).on( 'submit', 'form', function( e ) {
72
+ var data = $( this ).serializeArray(),
73
+ modal = $( this ).closest( '.health-check-modal' );
74
+
75
+ e.preventDefault();
76
 
77
  $.post(
78
  ajaxurl,
79
  data,
80
+ function( response ) {
 
81
  if ( true === response.success ) {
82
+ $( modal.data( 'parent-field' ) ).append( response.data.message );
83
  } else {
84
+ healthCheckFailureModal( response.data.message, data.action, modal.data( 'parent-field' ) );
85
  }
86
+ }
87
+ );
 
 
88
 
89
+ healthCheckFailureModalClose( modal );
90
+ });
91
+ });
92
 
93
+ /* global HealthCheck, ajaxurl, healthCheckFailureModal */
94
+ jQuery( document ).ready(function( $ ) {
95
+ $( '#loopback-no-plugins' ).click(function( e ) {
96
+ var $trigger = $( this ),
97
+ $parent = $( this ).closest( 'td' ),
98
+ data = {
99
+ action: 'health-check-loopback-no-plugins'
100
+ };
101
 
102
  e.preventDefault();
103
 
104
+ $( this ).html( '<span class="spinner" style="visibility: visible;"></span> ' + HealthCheck.string.please_wait );
 
 
105
 
106
  $.post(
107
  ajaxurl,
108
  data,
109
+ function( response ) {
110
  $trigger.remove();
111
  if ( true === response.success ) {
112
+ $parent.append( response.data.message );
113
  } else {
114
+ healthCheckFailureModal( response.data, data.action, $parent );
115
  }
116
  },
117
  'json'
118
+ );
119
  });
120
 
121
+ $( '.dashboard_page_health-check' ).on( 'click', '#loopback-individual-plugins', function( e ) {
122
+ var $trigger = $( this ),
123
+ $parent = $( this ).closest( 'td' ),
124
+ data = {
125
+ action: 'health-check-loopback-individual-plugins'
126
+ };
127
 
128
  e.preventDefault();
129
 
130
+ $( this ).html( '<span class="spinner" style="visibility: visible;"></span> ' + HealthCheck.string.please_wait );
131
+
132
  $.post(
133
  ajaxurl,
134
  data,
135
+ function( response ) {
136
+ $trigger.remove();
137
  if ( true === response.success ) {
138
+ $parent.append( response.data.message );
139
  } else {
140
+ healthCheckFailureModal( response.data, data.action, $parent );
141
  }
142
+ },
143
+ 'json'
144
  );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
145
  });
146
+ });
147
 
148
+ /* global ajaxurl */
149
+ jQuery( document ).ready(function( $ ) {
150
  $( '#health-check-file-integrity' ).submit( function( e ) {
 
 
 
 
151
  var data = {
152
  'action': 'health-check-files-integrity-check'
153
  };
154
 
 
 
 
 
 
 
 
 
 
 
155
  e.preventDefault();
 
 
 
156
 
157
+ $( '#tools-file-integrity-response-holder' ).html( '<span class="spinner"></span>' );
158
+ $( '#tools-file-integrity-response-holder .spinner' ).addClass( 'is-active' );
 
 
159
 
160
  $.post(
161
  ajaxurl,
162
  data,
163
  function( response ) {
164
+ $( '#tools-file-integrity-response-holder .spinner' ).removeClass( 'is-active' );
165
+ $( '#tools-file-integrity-response-holder' ).parent().css( 'height', 'auto' );
166
+ $( '#tools-file-integrity-response-holder' ).html( response.data.message );
167
+ }
168
+ );
169
  });
170
 
171
+ $( '#tools-file-integrity-response-holder' ).on( 'click', 'a[href="#health-check-diff"]', function( e ) {
172
+ var file = $( this ).data( 'file' ),
173
+ data;
174
+
175
  e.preventDefault();
176
+
177
  $( '#health-check-diff-modal' ).toggle();
178
  $( '#health-check-diff-modal #health-check-diff-modal-content .spinner' ).addClass( 'is-active' );
179
 
180
+ data = {
181
  'action': 'health-check-view-file-diff',
182
+ 'file': file
183
  };
184
 
185
  $.post(
189
  $( '#health-check-diff-modal #health-check-diff-modal-diff' ).html( response.data.message );
190
  $( '#health-check-diff-modal #health-check-diff-modal-content h3' ).html( file );
191
  $( '#health-check-diff-modal #health-check-diff-modal-content .spinner' ).removeClass( 'is-active' );
192
+ }
193
+ );
194
  });
195
+ });
196
 
197
+ jQuery( document ).ready(function( $ ) {
198
  $( '#health-check-diff-modal' ).on( 'click', 'a[href="#health-check-diff-modal-close"]', function( e ) {
199
  e.preventDefault();
200
  $( '#health-check-diff-modal' ).toggle();
201
+ $( '#health-check-diff-modal #health-check-diff-modal-diff' ).html( '' );
202
+ $( '#health-check-diff-modal #health-check-diff-modal-content h3' ).html( '' );
203
+ });
204
+
205
+ $( document ).keyup(function( e ) {
206
+ if ( 27 === e.which ) {
207
+ $( '#health-check-diff-modal' ).css( 'display', 'none' );
208
+ $( '#health-check-diff-modal #health-check-diff-modal-diff' ).html( '' );
209
+ $( '#health-check-diff-modal #health-check-diff-modal-content h3' ).html( '' );
210
+ }
211
  });
212
+ });
213
+
214
+ /* global ajaxurl */
215
+ jQuery( document ).ready(function( $ ) {
216
+ $( '#health-check-mail-check' ).submit( function( e ) {
217
+ var email = $( '#health-check-mail-check #email' ).val(),
218
+ emailMessage = $( '#health-check-mail-check #email_message' ).val(),
219
+ data;
220
+
221
+ e.preventDefault();
222
+
223
+ $( '#tools-mail-check-response-holder' ).html( '<span class="spinner"></span>' );
224
+ $( '#tools-mail-check-response-holder .spinner' ).addClass( 'is-active' );
225
+
226
+ data = {
227
+ 'action': 'health-check-mail-check',
228
+ 'email': email,
229
+ 'email_message': emailMessage
230
+ };
231
 
232
+ $.post(
233
+ ajaxurl,
234
+ data,
235
+ function( response ) {
236
+ $( '#tools-mail-check-response-holder .spinner' ).removeClass( 'is-active' );
237
+ $( '#tools-mail-check-response-holder' ).parent().css( 'height', 'auto' );
238
+ $( '#tools-mail-check-response-holder' ).html( response.data.message );
239
+ }
240
+ );
241
+ });
242
  });
assets/mu-plugin/health-check-troubleshooting-mode.php ADDED
@@ -0,0 +1,621 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /*
3
+ Plugin Name: Health Check Troubleshooting Mode
4
+ Description: Conditionally disabled themes or plugins on your site for a given session, used to rule out conflicts during troubleshooting.
5
+ Version: 1.4
6
+ */
7
+
8
+ if ( ! defined( 'ABSPATH' ) ) {
9
+ die( 'We\'re sorry, but you can not directly access this file.' );
10
+ }
11
+
12
+ class Health_Check_Troubleshooting_MU {
13
+ private $override_active = true;
14
+ private $default_theme = true;
15
+ private $active_plugins = array();
16
+ private $current_theme;
17
+
18
+ private $available_query_args = array(
19
+ 'health-check-disable-plugins',
20
+ 'health-check-disable-plugins-hash',
21
+ 'health-check-disable-troubleshooting',
22
+ 'health-check-change-active-theme',
23
+ 'health-check-troubleshoot-enable-plugin',
24
+ 'health-check-troubleshoot-disable-plugin',
25
+ );
26
+
27
+ private $default_themes = array(
28
+ 'twentyseventeen',
29
+ 'twentysixteen',
30
+ 'twentyfifteen',
31
+ 'twentyfourteen',
32
+ 'twentythirteen',
33
+ 'twentytwelve',
34
+ 'twentyeleven',
35
+ 'twentyten',
36
+ );
37
+
38
+ /**
39
+ * Health_Check_Troubleshooting_MU constructor.
40
+ */
41
+ public function __construct() {
42
+ $this->init();
43
+ }
44
+
45
+ /**
46
+ * Actually initiation of the plugin.
47
+ *
48
+ * @return void
49
+ */
50
+ public function init() {
51
+ add_action( 'admin_bar_menu', array( $this, 'health_check_troubleshoot_menu_bar' ), 999 );
52
+
53
+ add_filter( 'option_active_plugins', array( $this, 'health_check_loopback_test_disable_plugins' ) );
54
+ add_filter( 'option_active_sitewide_plugins', array( $this, 'health_check_loopback_test_disable_plugins' ) );
55
+
56
+ add_filter( 'stylesheet', array( $this, 'health_check_troubleshoot_theme' ) );
57
+ add_filter( 'template', array( $this, 'health_check_troubleshoot_theme' ) );
58
+
59
+ add_action( 'admin_notices', array( $this, 'plugin_list_admin_notice' ) );
60
+ add_action( 'admin_notices', array( $this, 'prompt_install_default_theme' ) );
61
+ add_filter( 'user_has_cap', array( $this, 'remove_plugin_theme_install' ) );
62
+
63
+ add_action( 'plugin_action_links', array( $this, 'plugin_actions' ), 50, 4 );
64
+
65
+ add_action( 'wp_logout', array( $this, 'health_check_troubleshooter_mode_logout' ) );
66
+ add_action( 'init', array( $this, 'health_check_troubleshoot_get_captures' ) );
67
+
68
+ /*
69
+ * Plugin activations can be forced by other tools in things like themes, so let's
70
+ * attempt to work around that by forcing plugin lists back and forth.
71
+ *
72
+ * This is not an ideal scenario, but one we must accept as reality.
73
+ */
74
+ add_action( 'activated_plugin', array( $this, 'plugin_activated' ) );
75
+
76
+ $this->default_theme = ( 'yes' === get_option( 'health-check-default-theme', 'yes' ) ? true : false );
77
+ $this->active_plugins = $this->get_unfiltered_plugin_list();
78
+ $this->current_theme = get_option( 'health-check-current-theme', false );
79
+ }
80
+
81
+ /**
82
+ * Add a prompt to install a default theme.
83
+ *
84
+ * If no default theme exists, we can't reliably assert if an issue is
85
+ * caused by the theme. In these cases we should provide an easy step
86
+ * to get to, and install, one of the default themes.
87
+ *
88
+ * @return void
89
+ */
90
+ public function prompt_install_default_theme() {
91
+ if ( ! $this->is_troubleshooting() || $this->has_default_theme() ) {
92
+ return;
93
+ }
94
+
95
+ printf(
96
+ '<div class="notice notice-warning dismissable"><p>%s</p><p><a href="%s" class="button button-primary">%s</a></p></div>',
97
+ esc_html__( 'You don\'t have any of the default themes installed. A default theme helps you determine if your current theme is causing conflicts.', 'health-check' ),
98
+ esc_url( admin_url( sprintf(
99
+ 'theme-install.php?theme=%s',
100
+ $this->default_themes[0]
101
+ ) ) ),
102
+ esc_html__( 'Install a default theme', 'health-check' )
103
+ );
104
+ }
105
+
106
+ /**
107
+ * Remove the `Add` option for plugins and themes.
108
+ *
109
+ * When troubleshooting, adding or changing themes and plugins can
110
+ * lead to unexpected results. Remove these menu items to make it less
111
+ * likely that a user breaks their site through these.
112
+ *
113
+ * @param array $caps Array containing the current users capabilities.
114
+ *
115
+ * @return array
116
+ */
117
+ public function remove_plugin_theme_install( $caps ) {
118
+ if ( ! $this->is_troubleshooting() ) {
119
+ return $caps;
120
+ }
121
+
122
+ $caps['switch_themes'] = false;
123
+
124
+ /*
125
+ * This is to early for `get_current_screen()`, so we have to do it the
126
+ * old fashioned way with `$_SERVER`.
127
+ */
128
+ if ( 'plugin-install.php' === substr( $_SERVER['REQUEST_URI'], -18 ) ) {
129
+ $caps['activate_plugins'] = false;
130
+ }
131
+
132
+ return $caps;
133
+ }
134
+
135
+ /**
136
+ * Fire on plugin activation.
137
+ *
138
+ * When in Troubleshooting Mode, plugin activations
139
+ * will clear out the DB entry for `active_plugins`, this is bad.
140
+ *
141
+ * We fix this by re-setting the DB entry if anything tries
142
+ * to modify it during troubleshooting.
143
+ *
144
+ * @return void
145
+ */
146
+ public function plugin_activated() {
147
+ if ( ! $this->is_troubleshooting() ) {
148
+ return;
149
+ }
150
+
151
+ // Force the database entry for active plugins if someone tried changing plugins while in Troubleshooting Mode.
152
+ update_option( 'active_plugins', $this->active_plugins );
153
+ }
154
+
155
+ /**
156
+ * Add a notice to the plugins screen.
157
+ *
158
+ * Make sure users are informed that all plugin actions are
159
+ * stripped away when they are troubleshooting.
160
+ *
161
+ * @return void
162
+ */
163
+ public function plugin_list_admin_notice() {
164
+ if ( ! $this->is_troubleshooting() ) {
165
+ return;
166
+ }
167
+ global $current_screen;
168
+
169
+ // Only output our notice on the plugins screen.
170
+ if ( 'plugins' !== $current_screen->base ) {
171
+ return;
172
+ }
173
+
174
+ printf(
175
+ '<div class="notice notice-warning"><p>%s</p></div>',
176
+ esc_html__( 'Plugin actions are not available while in Troubleshooting Mode.', 'health-check' )
177
+ );
178
+ }
179
+
180
+ /**
181
+ * Modify plugin actions.
182
+ *
183
+ * While in Troubleshooting Mode, weird things will happen if you start
184
+ * modifying your plugin list. Prevent this, but also add in the ability
185
+ * to enable or disable a plugin during troubleshooting from this screen.
186
+ *
187
+ * @param $actions
188
+ * @param $plugin_file
189
+ * @param $plugin_data
190
+ * @param $context
191
+ *
192
+ * @return array
193
+ */
194
+ public function plugin_actions( $actions, $plugin_file, $plugin_data, $context ) {
195
+ if ( ! $this->is_troubleshooting() ) {
196
+ return $actions;
197
+ }
198
+
199
+ if ( 'mustuse' === $context ) {
200
+ return $actions;
201
+ }
202
+
203
+ /*
204
+ * Disable all plugin actions when in Troubleshooting Mode.
205
+ *
206
+ * We intentionally remove all plugin actions to avoid accidental clicking, activating or deactivating plugins
207
+ * while our plugin is altering plugin data may lead to unexpected behaviors, so to keep things sane we do
208
+ * not allow users to perform any actions during this time.
209
+ */
210
+ $actions = array();
211
+
212
+ // This isn't an active plugin, so does not apply to our troubleshooting scenarios.
213
+ if ( ! in_array( $plugin_file, $this->active_plugins ) ) {
214
+ return $actions;
215
+ }
216
+
217
+ // Set a slug if the plugin lives in the plugins directory root.
218
+ if ( ! stristr( $plugin_file, '/' ) ) {
219
+ $plugin_data['slug'] = $plugin_file;
220
+ }
221
+
222
+ $allowed_plugins = get_option( 'health-check-allowed-plugins', array() );
223
+
224
+ $plugin_slug = ( isset( $plugin_data['slug'] ) ? $plugin_data['slug'] : sanitize_title( $plugin_data['Name'] ) );
225
+
226
+ if ( in_array( $plugin_slug, $allowed_plugins ) ) {
227
+ $actions['troubleshoot-disable'] = sprintf(
228
+ '<a href="%s">%s</a>',
229
+ esc_url( add_query_arg( array(
230
+ 'health-check-troubleshoot-disable-plugin' => $plugin_slug,
231
+ ), admin_url( 'plugins.php' ) ) ),
232
+ esc_html__( 'Disable while troubleshooting', 'health-check' )
233
+ );
234
+ } else {
235
+ $actions['troubleshoot-disable'] = sprintf(
236
+ '<a href="%s">%s</a>',
237
+ esc_url( add_query_arg( array(
238
+ 'health-check-troubleshoot-enable-plugin' => $plugin_slug,
239
+ ), admin_url( 'plugins.php' ) ) ),
240
+ esc_html__( 'Enable while troubleshooting', 'health-check' )
241
+ );
242
+ }
243
+
244
+ return $actions;
245
+ }
246
+
247
+ /**
248
+ * Get the actual list of active plugins.
249
+ *
250
+ * When in Troubleshooting Mode we override the list of plugins,
251
+ * this function lets us grab the active plugins list without
252
+ * any interference.
253
+ *
254
+ * @return array Array of active plugins.
255
+ */
256
+ public function get_unfiltered_plugin_list() {
257
+ $this->override_active = false;
258
+ $all_plugins = get_option( 'active_plugins' );
259
+ $this->override_active = true;
260
+
261
+ return $all_plugins;
262
+ }
263
+
264
+ /**
265
+ * Check if the user is currently in Troubleshooting Mode or not.
266
+ *
267
+ * @return bool
268
+ */
269
+ public static function is_troubleshooting() {
270
+ // Check if a session cookie to disable plugins has been set.
271
+ if ( isset( $_COOKIE['health-check-disable-plugins'] ) ) {
272
+ $_GET['health-check-disable-plugin-hash'] = $_COOKIE['health-check-disable-plugins'];
273
+ }
274
+
275
+ // If the disable hash isn't set, no need to interact with things.
276
+ if ( ! isset( $_GET['health-check-disable-plugin-hash'] ) ) {
277
+ return false;
278
+ }
279
+
280
+ // If the plugin hash is not valid, we also break out
281
+ $disable_hash = get_option( 'health-check-disable-plugin-hash', '' );
282
+ if ( $disable_hash !== $_GET['health-check-disable-plugin-hash'] ) {
283
+ return false;
284
+ }
285
+
286
+ return true;
287
+ }
288
+
289
+ /**
290
+ * Filter the plugins that are activated in WordPress.
291
+ *
292
+ * @param array $plugins An array of plugins marked as active.
293
+ *
294
+ * @return array
295
+ */
296
+ function health_check_loopback_test_disable_plugins( $plugins ) {
297
+ if ( ! $this->is_troubleshooting() || ! $this->override_active ) {
298
+ return $plugins;
299
+ }
300
+
301
+ $allowed_plugins = get_option( 'health-check-allowed-plugins', array() );
302
+
303
+ // If we've received a comma-separated list of allowed plugins, we'll add them to the array of allowed plugins.
304
+ if ( isset( $_GET['health-check-allowed-plugins'] ) ) {
305
+ $allowed_plugins = explode( ',', $_GET['health-check-allowed-plugins'] );
306
+ }
307
+
308
+ foreach ( $plugins as $plugin_no => $plugin_path ) {
309
+ // Split up the plugin path, [0] is the slug and [1] holds the primary plugin file.
310
+ $plugin_parts = explode( '/', $plugin_path );
311
+
312
+ // We may want to allow individual, or groups of plugins, so introduce a skip-mechanic for those scenarios.
313
+ if ( in_array( $plugin_parts[0], $allowed_plugins ) ) {
314
+ continue;
315
+ }
316
+
317
+ // Remove the reference to this plugin.
318
+ unset( $plugins[ $plugin_no ] );
319
+ }
320
+
321
+ // Return a possibly modified list of activated plugins.
322
+ return $plugins;
323
+ }
324
+
325
+ /**
326
+ * Check if a default theme exists.
327
+ *
328
+ * If a default theme exists, return the most recent one, if not return `false`.
329
+ *
330
+ * @return bool|string
331
+ */
332
+ function has_default_theme() {
333
+ foreach ( $this->default_themes as $default_theme ) {
334
+ if ( $this->theme_exists( $default_theme ) ) {
335
+ return $default_theme;
336
+ }
337
+ }
338
+
339
+ return false;
340
+ }
341
+
342
+ /**
343
+ * Check if a theme exists by looking for the slug.
344
+ *
345
+ * @param string $theme_slug
346
+ *
347
+ * @return bool
348
+ */
349
+ function theme_exists( $theme_slug ) {
350
+ return is_dir( WP_CONTENT_DIR . '/themes/' . $theme_slug );
351
+ }
352
+
353
+ /**
354
+ * Check if theme overrides are active.
355
+ *
356
+ * @return bool
357
+ */
358
+ function override_theme() {
359
+ if ( ! $this->is_troubleshooting() ) {
360
+ return false;
361
+ }
362
+
363
+ return true;
364
+ }
365
+
366
+ /**
367
+ * Use a default theme.
368
+ *
369
+ * Attempt to set one of the default themes as the active one
370
+ * during Troubleshooting Mode, if one exists, if not fall
371
+ * back to always showing the active theme.
372
+ *
373
+ * @param string $theme The users active theme slug.
374
+ *
375
+ * @return string Theme slug to be perceived as the active theme.
376
+ */
377
+ function health_check_troubleshoot_theme( $theme ) {
378
+ // Check if overrides are triggered if not break out.
379
+ if ( ! $this->override_theme() ) {
380
+ return $theme;
381
+ }
382
+
383
+ // Check if a default theme exists, and if so use it as a default.
384
+ $default_theme = $this->has_default_theme();
385
+ if ( $default_theme ) {
386
+ $theme = $default_theme;
387
+ }
388
+
389
+ // If a specific theme has been chosen, use it.
390
+ if ( false !== $this->current_theme ) {
391
+ $theme = $this->current_theme;
392
+ }
393
+
394
+ return $theme;
395
+ }
396
+
397
+ /**
398
+ * Disable Troubleshooting Mode on logout.
399
+ *
400
+ * If logged in, disable the Troubleshooting Mode when the logout
401
+ * event is fired, this ensures we start with a clean slate on
402
+ * the next login.
403
+ *
404
+ * @return void
405
+ */
406
+ function health_check_troubleshooter_mode_logout() {
407
+ if ( ! $this->is_troubleshooting() ) {
408
+ return;
409
+ }
410
+
411
+ if ( isset( $_COOKIE['health-check-disable-plugins'] ) ) {
412
+ $this->disable_troubleshooting_mode();
413
+ }
414
+ }
415
+
416
+ function disable_troubleshooting_mode() {
417
+ unset( $_COOKIE['health-check-disable-plugins'] );
418
+ setcookie( 'health-check-disable-plugins', null, 0, COOKIEPATH, COOKIE_DOMAIN );
419
+ delete_option( 'health-check-allowed-plugins' );
420
+ delete_option( 'health-check-default-theme' );
421
+ delete_option( 'health-check-current-theme' );
422
+
423
+ delete_option( 'health-check-backup-plugin-list' );
424
+ }
425
+
426
+ /**
427
+ * Catch query arguments.
428
+ *
429
+ * When in Troubleshooting Mode, look for various GET variables that trigger
430
+ * various plugin actions.
431
+ *
432
+ * @return void
433
+ */
434
+ function health_check_troubleshoot_get_captures() {
435
+ if ( ! $this->is_troubleshooting() ) {
436
+ return;
437
+ }
438
+
439
+ // Disable Troubleshooting Mode.
440
+ if ( isset( $_GET['health-check-disable-troubleshooting'] ) ) {
441
+ $this->disable_troubleshooting_mode();
442
+
443
+ wp_redirect( remove_query_arg( $this->available_query_args ) );
444
+ die();
445
+ }
446
+
447
+ // Enable an individual plugin.
448
+ if ( isset( $_GET['health-check-troubleshoot-enable-plugin'] ) ) {
449
+ $allowed_plugins = get_option( 'health-check-allowed-plugins', array() );
450
+ $allowed_plugins[ $_GET['health-check-troubleshoot-enable-plugin'] ] = $_GET['health-check-troubleshoot-enable-plugin'];
451
+
452
+ update_option( 'health-check-allowed-plugins', $allowed_plugins );
453
+
454
+ wp_redirect( remove_query_arg( $this->available_query_args ) );
455
+ die();
456
+ }
457
+
458
+ // Disable an individual plugin.
459
+ if ( isset( $_GET['health-check-troubleshoot-disable-plugin'] ) ) {
460
+ $allowed_plugins = get_option( 'health-check-allowed-plugins', array() );
461
+ unset( $allowed_plugins[ $_GET['health-check-troubleshoot-disable-plugin'] ] );
462
+
463
+ update_option( 'health-check-allowed-plugins', $allowed_plugins );
464
+
465
+ wp_redirect( remove_query_arg( $this->available_query_args ) );
466
+ die();
467
+ }
468
+
469
+ // Change the active theme for this session.
470
+ if ( isset( $_GET['health-check-change-active-theme'] ) ) {
471
+ update_option( 'health-check-current-theme', $_GET['health-check-change-active-theme'] );
472
+
473
+ wp_redirect( remove_query_arg( $this->available_query_args ) );
474
+ die();
475
+ }
476
+ }
477
+
478
+ /**
479
+ * Extend the admin bar.
480
+ *
481
+ * When in Troubleshooting Mode, introduce a new element to the admin bar to show
482
+ * enabled and disabled plugins (if conditions are met), switch between themes
483
+ * and disable Troubleshooting Mode altogether.
484
+ *
485
+ * @param WP_Admin_Bar $wp_menu
486
+ *
487
+ * @return void
488
+ */
489
+ function health_check_troubleshoot_menu_bar( $wp_menu ) {
490
+ if ( ! $this->is_troubleshooting() ) {
491
+ return;
492
+ }
493
+
494
+ // Ensure the theme functions are available to us on every page.
495
+ include_once( trailingslashit( ABSPATH ) . 'wp-admin/includes/theme.php' );
496
+
497
+ // Add top-level menu item.
498
+ $wp_menu->add_menu( array(
499
+ 'id' => 'health-check',
500
+ 'title' => esc_html__( 'Troubleshooting Mode', 'health-check' ),
501
+ ) );
502
+
503
+ $allowed_plugins = get_option( 'health-check-allowed-plugins', array() );
504
+
505
+ // Add a link to manage plugins if there are more than 20 set to be active.
506
+ if ( count( $allowed_plugins ) > 20 ) {
507
+ $wp_menu->add_node( array(
508
+ 'id' => 'health-check-plugins',
509
+ 'title' => esc_html__( 'Manage active plugins', 'health-check' ),
510
+ 'parent' => 'health-check',
511
+ 'href' => admin_url( 'plugins.php' ),
512
+ ) );
513
+ } else {
514
+ $wp_menu->add_node( array(
515
+ 'id' => 'health-check-plugins',
516
+ 'title' => esc_html__( 'Plugins', 'health-check' ),
517
+ 'parent' => 'health-check',
518
+ ) );
519
+
520
+ $wp_menu->add_group( array(
521
+ 'id' => 'health-check-plugins-enabled',
522
+ 'parent' => 'health-check-plugins',
523
+ ) );
524
+ $wp_menu->add_group( array(
525
+ 'id' => 'health-check-plugins-disabled',
526
+ 'parent' => 'health-check-plugins',
527
+ ) );
528
+
529
+ foreach ( $this->active_plugins as $single_plugin ) {
530
+ $plugin_slug = explode( '/', $single_plugin );
531
+ $plugin_slug = $plugin_slug[0];
532
+
533
+ $plugin_data = get_plugin_data( trailingslashit( WP_PLUGIN_DIR ) . $single_plugin );
534
+
535
+ $enabled = true;
536
+
537
+ if ( in_array( $plugin_slug, $allowed_plugins ) ) {
538
+ $label = sprintf(
539
+ // Translators: %s: Plugin slug.
540
+ esc_html__( 'Disable %s', 'health-check' ),
541
+ sprintf(
542
+ '<strong>%s</strong>',
543
+ $plugin_data['Name']
544
+ )
545
+ );
546
+ $url = add_query_arg( array(
547
+ 'health-check-troubleshoot-disable-plugin' => $plugin_slug,
548
+ ) );
549
+ } else {
550
+ $enabled = false;
551
+ $label = sprintf(
552
+ // Translators: %s: Plugin slug.
553
+ esc_html__( 'Enable %s', 'health-check' ),
554
+ sprintf(
555
+ '<strong>%s</strong>',
556
+ $plugin_data['Name']
557
+ )
558
+ );
559
+ $url = add_query_arg( array(
560
+ 'health-check-troubleshoot-enable-plugin' => $plugin_slug,
561
+ ) );
562
+ }
563
+
564
+ $wp_menu->add_node( array(
565
+ 'id' => sprintf(
566
+ 'health-check-plugin-%s',
567
+ $plugin_slug
568
+ ),
569
+ 'title' => $label,
570
+ 'parent' => ( $enabled ? 'health-check-plugins-enabled' : 'health-check-plugins-disabled' ),
571
+ 'href' => $url,
572
+ ) );
573
+ }
574
+ }
575
+
576
+ $wp_menu->add_node( array(
577
+ 'id' => 'health-check-theme',
578
+ 'title' => esc_html__( 'Themes', 'health-check' ),
579
+ 'parent' => 'health-check',
580
+ ) );
581
+
582
+ $themes = wp_prepare_themes_for_js();
583
+
584
+ foreach ( $themes as $theme ) {
585
+ $node = array(
586
+ 'id' => sprintf(
587
+ 'health-check-theme-%s',
588
+ sanitize_title( $theme['id'] )
589
+ ),
590
+ 'title' => sprintf(
591
+ '%s %s',
592
+ // translators: Prefix for the active theme in a listing.
593
+ ( $theme['active'] ? esc_html__( 'Active:', 'health-check' ) : '' ),
594
+ $theme['name']
595
+ ),
596
+ 'parent' => 'health-check-theme',
597
+ );
598
+
599
+ if ( ! $theme['active'] ) {
600
+ $node['href'] = add_query_arg( array(
601
+ 'health-check-change-active-theme' => $theme['id'],
602
+ ) );
603
+ }
604
+
605
+ $wp_menu->add_node( $node );
606
+ }
607
+
608
+ // Add a link to disable Troubleshooting Mode.
609
+ $wp_menu->add_node( array(
610
+ 'id' => 'health-check-disable',
611
+ 'title' => esc_html__( 'Disable Troubleshooting Mode', 'health-check' ),
612
+ 'parent' => 'health-check',
613
+ 'href' => add_query_arg( array(
614
+ 'health-check-disable-troubleshooting' => true,
615
+ ) ),
616
+ ) );
617
+ }
618
+
619
+ }
620
+
621
+ new Health_Check_Troubleshooting_MU();
changelog.txt CHANGED
@@ -1,57 +1,96 @@
1
- = v 0.7.0 =
2
- * Troubleshooting mode now also switches to a default theme.
3
- * Introduced a method for toggling default or active theme use when in troubleshooting mode.
4
- * Introduced a method for enabling/disabling plugins while in troubleshooting mode.
5
- * Introduced a method for disabling troubleshooting mode without needing to log out and back in again.
6
-
7
- = v 0.6.0 =
8
- * Improved loopback tests
9
- * Check if loopbacks can be completed without plugins activated
10
- * Test individual plugins to identify loopback blockers
11
- * Add troubleshooting mode, test your website without any plugins for your session without disabling functionality for visitors.
12
-
13
- = v 0.5.1 =
14
- * Introduced loopback check to the health checker status.
15
-
16
- = v 0.5.0 =
17
- * Added clarity to many text strings.
18
- * Avoid listing MU directories if it's not being used.
19
- * Add a Table of Contents heading and make navigating the debug page from it smoother.
20
- * Only enqueue our CSS and JavaScript if we are on the health check pages.
21
- * Add some missing version numbers nor being included in text strings.
22
- * Avoid fatal errors if accessing files directly, caused by translation functions being used when they don't exist.
23
- * Avoid "empty" strings when author or version is missing from plugins or themes.
24
- * Make the health checker test background updates.
25
- * Make the health checker look for missed scheduled events.
26
- * If using a localized version of WordPress, also display the copy and paste field in English if using an international support resource.
27
- * Indicate if 64bit values are supported by PHP in the debug section.
28
- * Improved MariaDB version detection/comparison.
29
-
30
- = v 0.4.1 =
31
- * Better SQL version detection to account for MariaDB versions
32
- * Added translation support
33
- * Removed unintentional indentations in the debug copying field
34
-
35
- = v 0.4 =
36
- * Added debug section
37
- * Added PHP info section
38
- * Cleaned up the health check
39
- * Added WordPress.org connectivity check
40
- * Added HTTPS check
41
-
42
- = v 0.3.1 =
43
- * Fixed a few typos
44
-
45
- = v 0.3 =
46
- * Added recommended PHP and MySQL versions
47
- * Check for utf8mb4 support
48
- * Fixed a bunch of PHP warnings
49
-
50
- = v 0.2.1 =
51
- * Fixed version comparision bug - When the server had the exact required versions we reported it as out of date.
52
-
53
- = v 0.2 =
54
- * Updated with actual PHP and MySQL version requirements for WordPress 3.2
55
-
56
- = v 0.1 =
57
- * Initial release with checks for the PHP and MySQL versions we will likely target for WordPress 3.2
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ = v 1.0.1 =
2
+ * Fixed email tester having the wrong class reference, preventing it from running.
3
+ * Add some missing text domains preventing full translations.
4
+
5
+ = v 1.0.0 =
6
+ * Added minimum PHP version checks with documentation links.
7
+ * Added testing with a default theme to the loopback checker.
8
+ * Added cURL version checker to the health check tab.
9
+ * Added simple e-mail tester.
10
+ * Added core file integrity checker.
11
+ * Added capability checks, to avoid installing things that may modify the database while troubleshooting.
12
+ * Added a prompt to install a default theme if none exist.
13
+ * Added a warning encouraging users to maintain up to date backups when troubleshooting.
14
+ * Fixed MU plugin not always updating (if available) when a user tries to troubleshoot.
15
+ * Fixed fatal error when trying to troubleshoot "too early".
16
+ * Updated troubleshooting drop down, it no longer shows theme switching if no default theme exists.
17
+ * Removed the checkbox requirement from the Troubleshooting tab, it wasn't needed any more, and added pointless complexity now.
18
+
19
+ = v 0.9.0 =
20
+ * Various string changes, typo fixes and translation enhancements.
21
+ * Added conditional hiding of the plugins list from the admin bar, if there's too many plugins it becomes a bad experience. (Hidden if there are more than 20 active plugins)
22
+ * Added ability to enable/disable plugins in Troubleshooting Mode from the plugins list.
23
+ * Added filter to remove actions from the plugin list in Troubleshooting Mode.
24
+ * Fixed notices on the plugin screen when plugin data may be inconsistent.
25
+ * Fixed jumping directly to troubleshooting mode for single file plugins placed directly in the plugin directory root.
26
+ * Fixed issue where troubleshooting a plugin directly made it impossible to disable it while in Troubleshooting Mode.
27
+ * Fixed so that the original language is returned when translating the debug data for copying.
28
+ * Fixed issue where the Debug screen would turn to half-English when using a non-English language.
29
+ * Fixed an issue where plugins could become truly disabled on a site when in Troubleshooting Mode.
30
+ * Fixed so that enabled/disabled plugins don't carry over between troubleshooting sessions.
31
+
32
+ = v 0.8.0 =
33
+ * Updated recommended PHP version to mirror WordPress.org.
34
+ * Updated texts for troubleshooting mode.
35
+ * Re-labeled database terms to be more user friendly.
36
+ * Added media information to the debug tab.
37
+ * Added individual `Troubleshoot` links for the list of active plugins.
38
+ * Added automatic copy to clipboard with supported browsers in the debug tab.
39
+
40
+ = v 0.7.0 =
41
+ * Troubleshooting mode now also switches to a default theme.
42
+ * Introduced a method for toggling default or active theme use when in troubleshooting mode.
43
+ * Introduced a method for enabling/disabling plugins while in troubleshooting mode.
44
+ * Introduced a method for disabling troubleshooting mode without needing to log out and back in again.
45
+
46
+ = v 0.6.0 =
47
+ * Improved loopback tests
48
+ * Check if loopbacks can be completed without plugins activated
49
+ * Test individual plugins to identify loopback blockers
50
+ * Add troubleshooting mode, test your website without any plugins for your session without disabling functionality for visitors.
51
+
52
+ = v 0.5.1 =
53
+ * Introduced loopback check to the health checker status.
54
+
55
+ = v 0.5.0 =
56
+ * Added clarity to many text strings.
57
+ * Avoid listing MU directories if it's not being used.
58
+ * Add a Table of Contents heading and make navigating the debug page from it smoother.
59
+ * Only enqueue our CSS and JavaScript if we are on the health check pages.
60
+ * Add some missing version numbers nor being included in text strings.
61
+ * Avoid fatal errors if accessing files directly, caused by translation functions being used when they don't exist.
62
+ * Avoid "empty" strings when author or version is missing from plugins or themes.
63
+ * Make the health checker test background updates.
64
+ * Make the health checker look for missed scheduled events.
65
+ * If using a localized version of WordPress, also display the copy and paste field in English if using an international support resource.
66
+ * Indicate if 64bit values are supported by PHP in the debug section.
67
+ * Improved MariaDB version detection/comparison.
68
+
69
+ = v 0.4.1 =
70
+ * Better SQL version detection to account for MariaDB versions
71
+ * Added translation support
72
+ * Removed unintentional indentations in the debug copying field
73
+
74
+ = v 0.4 =
75
+ * Added debug section
76
+ * Added PHP info section
77
+ * Cleaned up the health check
78
+ * Added WordPress.org connectivity check
79
+ * Added HTTPS check
80
+
81
+ = v 0.3.1 =
82
+ * Fixed a few typos
83
+
84
+ = v 0.3 =
85
+ * Added recommended PHP and MySQL versions
86
+ * Check for utf8mb4 support
87
+ * Fixed a bunch of PHP warnings
88
+
89
+ = v 0.2.1 =
90
+ * Fixed version comparision bug - When the server had the exact required versions we reported it as out of date.
91
+
92
+ = v 0.2 =
93
+ * Updated with actual PHP and MySQL version requirements for WordPress 3.2
94
+
95
+ = v 0.1 =
96
+ * Initial release with checks for the PHP and MySQL versions we will likely target for WordPress 3.2
health-check.php CHANGED
@@ -8,7 +8,7 @@
8
  * Plugin URI: http://wordpress.org/plugins/health-check/
9
  * Description: Checks the health of your WordPress install.
10
  * Author: The WordPress.org community
11
- * Version: 1.0.1
12
  * Author URI: http://wordpress.org/plugins/health-check/
13
  * Text Domain: health-check
14
  */
@@ -34,431 +34,22 @@ define( 'HEALTH_CHECK_MYSQL_MIN_VERSION', '5.0' );
34
  define( 'HEALTH_CHECK_MYSQL_REC_VERSION', '5.6' );
35
 
36
  // Set the plugin version.
37
- define( 'HEALTH_CHECK_PLUGIN_VERSION', '1.0.1' );
38
 
39
  // Set the absolute path for the plugin.
40
  define( 'HEALTH_CHECK_PLUGIN_DIRECTORY', plugin_dir_path( __FILE__ ) );
41
 
 
 
 
42
  // Set the current cURL version.
43
  define( 'HEALTH_CHECK_CURL_VERSION', '7.58' );
44
 
45
  // Set the minimum cURL version that we've tested that core works with.
46
  define( 'HEALTH_CHECK_CURL_MIN_VERSION', '7.38' );
47
 
48
- /**
49
- * Class HealthCheck
50
- */
51
- class HealthCheck {
52
-
53
- /**
54
- * Notices to show at the head of the admin screen.
55
- *
56
- * @access public
57
- *
58
- * @var array
59
- */
60
- public $admin_notices = array();
61
-
62
- /**
63
- * HealthCheck constructor.
64
- *
65
- * @uses HealthCheck::init()
66
- *
67
- * @return void
68
- */
69
- public function __construct() {
70
- $this->init();
71
- }
72
-
73
- /**
74
- * Plugin initiation.
75
- *
76
- * A helper function, called by `HealthCheck::__construct()` to initiate actions, hooks and other features needed.
77
- *
78
- * @uses add_action()
79
- * @uses add_filter()
80
- *
81
- * @return void
82
- */
83
- public function init() {
84
- add_action( 'plugins_loaded', array( $this, 'load_i18n' ) );
85
-
86
- add_action( 'admin_menu', array( $this, 'action_admin_menu' ) );
87
- add_filter( 'plugin_row_meta', array( $this, 'settings_link' ), 10, 2 );
88
-
89
- add_filter( 'plugin_action_links', array( $this, 'troubeshoot_plugin_action' ), 20, 4 );
90
-
91
- add_action( 'admin_footer', array( $this, 'show_backup_warning' ) );
92
-
93
- add_action( 'admin_notices', array( $this, 'admin_notices' ) );
94
-
95
- add_action( 'admin_enqueue_scripts', array( $this, 'enqueues' ) );
96
-
97
- add_action( 'init', array( $this, 'start_troubleshoot_mode' ) );
98
- add_action( 'load-plugins.php', array( $this, 'start_troubleshoot_single_plugin_mode' ) );
99
-
100
- add_action( 'wp_ajax_health-check-loopback-no-plugins', array( 'Health_Check_Loopback', 'loopback_no_plugins' ) );
101
- add_action( 'wp_ajax_health-check-loopback-individual-plugins', array( 'Health_Check_Loopback', 'loopback_test_individual_plugins' ) );
102
- add_action( 'wp_ajax_health-check-files-integrity-check', array( 'Health_Check_Files_Integrity', 'run_files_integrity_check' ) );
103
- add_action( 'wp_ajax_health-check-view-file-diff', array( 'Health_Check_Files_Integrity', 'view_file_diff' ) );
104
- add_action( 'wp_ajax_health-check-mail-check', array( 'Health_Check_Mail_Check', 'run_mail_check' ) );
105
- add_action( 'wp_ajax_health-check-confirm-warning', array( 'Health_Check_Troubleshoot', 'confirm_warning' ) );
106
- }
107
-
108
- /**
109
- * Show a warning modal about keeping backups.
110
- *
111
- * @uses Health_Check_Troubleshoot::has_seen_warning()
112
- *
113
- * @return void
114
- */
115
- public function show_backup_warning() {
116
- if ( Health_Check_Troubleshoot::has_seen_warning() ) {
117
- return;
118
- }
119
-
120
- include_once( HEALTH_CHECK_PLUGIN_DIRECTORY . '/modals/backup-warning.php' );
121
- }
122
-
123
- /**
124
- * Initiate troubleshooting mode.
125
- *
126
- * Catch when the troubleshooting form has been submitted, and appropriately set required options and cookies.
127
- *
128
- * @uses current_user_can()
129
- * @uses md5()
130
- * @uses rand()
131
- * @uses update_option()
132
- * @uses setcookie()
133
- *
134
- * @return void
135
- */
136
- public function start_troubleshoot_mode() {
137
- if ( ! isset( $_POST['health-check-troubleshoot-mode'] ) || ! current_user_can( 'manage_options' ) ) {
138
- return;
139
- }
140
-
141
- $loopback_hash = md5( rand() );
142
- update_option( 'health-check-disable-plugin-hash', $loopback_hash );
143
-
144
- setcookie( 'health-check-disable-plugins', $loopback_hash, 0, COOKIEPATH, COOKIE_DOMAIN );
145
- }
146
-
147
- /**
148
- * Initiate troubleshooting mode for a specific plugin.
149
- *
150
- * Catch when the troubleshooting link on an individual plugin has been clicked, and appropriately sets the
151
- * required options and cookies.
152
- *
153
- * @uses current_user_can()
154
- * @uses md5()
155
- * @uses rand()
156
- * @uses update_option()
157
- * @uses setcookie()
158
- * @uses wp_redirect()
159
- * @uses admin_url()
160
- *
161
- * @return void
162
- */
163
- public function start_troubleshoot_single_plugin_mode() {
164
- if ( ! isset( $_GET['health-check-troubleshoot-plugin'] ) || ! current_user_can( 'manage_options' ) ) {
165
- return;
166
- }
167
-
168
- ob_start();
169
-
170
- $needs_credentials = false;
171
-
172
- if ( ! Health_Check_Troubleshoot::mu_plugin_exists() ) {
173
- if ( ! Health_Check_Troubleshoot::get_filesystem_credentials() ) {
174
- $needs_credentials = true;
175
- } else {
176
- $check_output = Health_Check_Troubleshoot::setup_must_use_plugin( false );
177
- if ( false === $check_output ) {
178
- $needs_credentials = true;
179
- }
180
- }
181
- } else {
182
- if ( ! Health_Check_Troubleshoot::maybe_update_must_use_plugin() ) {
183
- $needs_credentials = true;
184
- }
185
- }
186
-
187
- $result = ob_get_clean();
188
-
189
- if ( $needs_credentials ) {
190
- $this->admin_notices[] = (object) array(
191
- 'message' => $result,
192
- 'type' => 'warning',
193
- );
194
- return;
195
- }
196
-
197
- $loopback_hash = md5( rand() );
198
- update_option( 'health-check-disable-plugin-hash', $loopback_hash );
199
-
200
- update_option( 'health-check-allowed-plugins', array( $_GET['health-check-troubleshoot-plugin'] => $_GET['health-check-troubleshoot-plugin'] ) );
201
-
202
- setcookie( 'health-check-disable-plugins', $loopback_hash, 0, COOKIEPATH, COOKIE_DOMAIN );
203
-
204
- wp_redirect( admin_url( 'plugins.php' ) );
205
- }
206
-
207
- /**
208
- * Load translations.
209
- *
210
- * Loads the textdomain needed to get translations for our plugin.
211
- *
212
- * @uses load_plugin_textdomain()
213
- * @uses basename()
214
- * @uses dirname()
215
- *
216
- * @return void
217
- */
218
- public function load_i18n() {
219
- load_plugin_textdomain( 'health-check', false, basename( dirname( __FILE__ ) ) . '/languages/' );
220
- }
221
-
222
- /**
223
- * Enqueue assets.
224
- *
225
- * Conditionally enqueue our CSS and JavaScript when viewing plugin related pages in wp-admin.
226
- *
227
- * @uses wp_enqueue_style()
228
- * @uses plugins_url()
229
- * @uses wp_enqueue_script()
230
- * @uses wp_localize_script()
231
- * @uses esc_html__()
232
- *
233
- * @return void
234
- */
235
- public function enqueues() {
236
- // Don't enqueue anything unless we're on the health check page
237
- if ( ! isset( $_GET['page'] ) || 'health-check' !== $_GET['page'] ) {
238
-
239
- /*
240
- * Special consideration, if warnings are not dismissed we need to display
241
- * our modal, and thus require our styles, in other locations, before bailing.
242
- */
243
- if ( ! Health_Check_Troubleshoot::has_seen_warning() ) {
244
- wp_enqueue_style( 'health-check', plugins_url( '/assets/css/health-check.css', __FILE__ ), array(), HEALTH_CHECK_PLUGIN_VERSION );
245
- }
246
- return;
247
- }
248
-
249
- wp_enqueue_style( 'health-check', plugins_url( '/assets/css/health-check.css', __FILE__ ), array(), HEALTH_CHECK_PLUGIN_VERSION );
250
-
251
- wp_enqueue_script( 'health-check', plugins_url( '/assets/javascript/health-check.js', __FILE__ ), array( 'jquery' ), HEALTH_CHECK_PLUGIN_VERSION, true );
252
-
253
- wp_localize_script( 'health-check', 'health_check', array(
254
- 'string' => array(
255
- 'please_wait' => esc_html__( 'Please wait...', 'health-check' ),
256
- 'copied' => esc_html__( 'Copied', 'health-check' ),
257
- ),
258
- 'warning' => array(
259
- 'seen_backup' => Health_Check_Troubleshoot::has_seen_warning(),
260
- ),
261
- ) );
262
- }
263
-
264
- /**
265
- * Add item to the admin menu.
266
- *
267
- * @uses add_dashboard_page()
268
- * @uses __()
269
- *
270
- * @return void
271
- */
272
- public function action_admin_menu() {
273
- add_dashboard_page( _x( 'Health Check', 'Menu, Section and Page Title', 'health-check' ), _x( 'Health Check', 'Menu, Section and Page Title', 'health-check' ), 'manage_options', 'health-check', array( $this, 'dashboard_page' ) );
274
- }
275
-
276
- /**
277
- * Add a quick-access link under our plugin name on the plugins-list.
278
- *
279
- * @uses plugin_basename()
280
- * @uses sprintf()
281
- * @uses menu_page_url()
282
- *
283
- * @param array $meta An array containing meta links.
284
- * @param string $name The plugin slug that these metas relate to.
285
- *
286
- * @return array
287
- */
288
- public function settings_link( $meta, $name ) {
289
- if ( plugin_basename( __FILE__ ) === $name ) {
290
- $meta[] = sprintf( '<a href="%s">' . _x( 'Health Check', 'Menu, Section and Page Title', 'health-check' ) . '</a>', menu_page_url( 'health-check', false ) );
291
- }
292
-
293
- return $meta;
294
- }
295
-
296
- /**
297
- * Add a troubleshooting action link to plugins.
298
- *
299
- * @param $actions
300
- * @param $plugin_file
301
- * @param $plugin_data
302
- * @param $context
303
- *
304
- * @return array
305
- */
306
- public function troubeshoot_plugin_action( $actions, $plugin_file, $plugin_data, $context ) {
307
- // Don't add anything if this is a Must-Use plugin, we can't touch those.
308
- if ( 'mustuse' === $context ) {
309
- return $actions;
310
- }
311
-
312
- // Only add troubleshooting actions to active plugins.
313
- if ( ! is_plugin_active( $plugin_file ) ) {
314
- return $actions;
315
- }
316
-
317
- // Set a slug if the plugin lives in the plugins directory root.
318
- if ( ! stristr( $plugin_file, '/' ) ) {
319
- $plugin_data['slug'] = $plugin_file;
320
- }
321
-
322
- $actions['troubleshoot'] = sprintf(
323
- '<a href="%s">%s</a>',
324
- esc_url( add_query_arg( array(
325
- 'health-check-troubleshoot-plugin' => ( isset( $plugin_data['slug'] ) ? $plugin_data['slug'] : sanitize_title( $plugin_data['Name'] ) ),
326
- ), admin_url( 'plugins.php' ) ) ),
327
- esc_html__( 'Troubleshoot', 'health-check' )
328
- );
329
-
330
- return $actions;
331
- }
332
-
333
- /**
334
- * Render our admin page.
335
- *
336
- * @uses _e()
337
- * @uses esc_html__()
338
- * @uses printf()
339
- * @uses sprintf()
340
- * @uses menu_page_url()
341
- * @uses dirname()
342
- *
343
- * @return void
344
- */
345
- public function dashboard_page() {
346
- ?>
347
- <div class="wrap">
348
- <h1>
349
- <?php _ex( 'Health Check', 'Menu, Section and Page Title', 'health-check' ); ?>
350
- </h1>
351
-
352
- <?php
353
- $tabs = array(
354
- 'health-check' => esc_html_x( 'Health Check', 'Menu, Section and Page Title', 'health-check' ),
355
- 'debug' => esc_html__( 'Debug information', 'health-check' ),
356
- 'troubleshoot' => esc_html__( 'Troubleshooting', 'health-check' ),
357
- 'phpinfo' => esc_html__( 'PHP Information', 'health-check' ),
358
- 'tools' => esc_html__( 'Tools', 'health-check' ),
359
- );
360
-
361
- $current_tab = ( isset( $_GET['tab'] ) ? $_GET['tab'] : 'health-check' );
362
- ?>
363
-
364
- <h2 class="nav-tab-wrapper wp-clearfix">
365
- <?php
366
- foreach ( $tabs as $tab => $label ) {
367
- printf(
368
- '<a href="%s" class="nav-tab %s">%s</a>',
369
- sprintf(
370
- '%s&tab=%s',
371
- menu_page_url( 'health-check', false ),
372
- $tab
373
- ),
374
- ( $current_tab === $tab ? 'nav-tab-active' : '' ),
375
- $label
376
- );
377
- }
378
- ?>
379
- </h2>
380
-
381
- <?php
382
- switch ( $current_tab ) {
383
- case 'debug':
384
- include_once( dirname( __FILE__ ) . '/pages/debug-data.php' );
385
- break;
386
- case 'phpinfo':
387
- include_once( dirname( __FILE__ ) . '/pages/phpinfo.php' );
388
- break;
389
- case 'troubleshoot':
390
- include_once( dirname( __FILE__ ) . '/pages/troubleshoot.php' );
391
- break;
392
- case 'tools':
393
- include_once( dirname( __FILE__ ) . '/pages/tools.php' );
394
- break;
395
- case 'health-check':
396
- default:
397
- include_once( dirname( __FILE__ ) . '/pages/health-check.php' );
398
- }
399
- ?>
400
- </div>
401
- <?php
402
- }
403
-
404
- /**
405
- * Display styled admin notices.
406
- *
407
- * @uses printf()
408
- *
409
- * @param string $message A sanitized string containing our notice message.
410
- * @param string $status A string representing the status type.
411
- *
412
- * @return void
413
- */
414
- static function display_notice( $message, $status = 'success' ) {
415
- printf(
416
- '<div class="notice notice-%s inline">',
417
- $status
418
- );
419
-
420
- printf(
421
- '<p>%s</p>',
422
- $message
423
- );
424
-
425
- echo '</div>';
426
- }
427
-
428
- /**
429
- * Display admin notices if we have any queued.
430
- *
431
- * @return void
432
- */
433
- public function admin_notices() {
434
- foreach ( $this->admin_notices as $admin_notice ) {
435
- printf(
436
- '<div class="notice notice-%s"><p>%s</p></div>',
437
- esc_attr( $admin_notice->type ),
438
- $admin_notice->message
439
- );
440
- }
441
- }
442
-
443
- /**
444
- * Perform a check to see is JSON is enabled.
445
- *
446
- * @uses extension_loaded()
447
- * @uses function_Exists()
448
- * @uses son_encode()
449
- *
450
- * @return bool
451
- */
452
- static function json_check() {
453
- $extension_loaded = extension_loaded( 'json' );
454
- $functions_exist = function_exists( 'json_encode' ) && function_exists( 'json_decode' );
455
- $functions_work = function_exists( 'json_encode' ) && ( '' != json_encode( 'my test string' ) );
456
-
457
- return $extension_loaded && $functions_exist && $functions_work;
458
- }
459
- }
460
-
461
  // Include class-files used by our plugin.
 
462
  require_once( dirname( __FILE__ ) . '/includes/class-health-check-auto-updates.php' );
463
  require_once( dirname( __FILE__ ) . '/includes/class-health-check-wp-cron.php' );
464
  require_once( dirname( __FILE__ ) . '/includes/class-health-check-debug-data.php' );
8
  * Plugin URI: http://wordpress.org/plugins/health-check/
9
  * Description: Checks the health of your WordPress install.
10
  * Author: The WordPress.org community
11
+ * Version: 1.1.0
12
  * Author URI: http://wordpress.org/plugins/health-check/
13
  * Text Domain: health-check
14
  */
34
  define( 'HEALTH_CHECK_MYSQL_REC_VERSION', '5.6' );
35
 
36
  // Set the plugin version.
37
+ define( 'HEALTH_CHECK_PLUGIN_VERSION', '1.1.0' );
38
 
39
  // Set the absolute path for the plugin.
40
  define( 'HEALTH_CHECK_PLUGIN_DIRECTORY', plugin_dir_path( __FILE__ ) );
41
 
42
+ // Set the plugin URL root.
43
+ define( 'HEALTH_CHECK_PLUGIN_URL', plugins_url( '/', __FILE__ ) );
44
+
45
  // Set the current cURL version.
46
  define( 'HEALTH_CHECK_CURL_VERSION', '7.58' );
47
 
48
  // Set the minimum cURL version that we've tested that core works with.
49
  define( 'HEALTH_CHECK_CURL_MIN_VERSION', '7.38' );
50
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
51
  // Include class-files used by our plugin.
52
+ require_once( dirname( __FILE__ ) . '/includes/class-healthcheck.php' );
53
  require_once( dirname( __FILE__ ) . '/includes/class-health-check-auto-updates.php' );
54
  require_once( dirname( __FILE__ ) . '/includes/class-health-check-wp-cron.php' );
55
  require_once( dirname( __FILE__ ) . '/includes/class-health-check-debug-data.php' );
includes/class-health-check-auto-updates.php CHANGED
@@ -1,511 +1,512 @@
1
- <?php
2
- /**
3
- * Class for testing automatic updates in the WordPress code.
4
- *
5
- * @package Health Check
6
- */
7
-
8
- /**
9
- * Class Health_Check_Auto_Updates
10
- */
11
- class Health_Check_Auto_Updates {
12
- /**
13
- * Health_Check_Auto_Updates constructor.
14
- *
15
- * @uses HealthCheck::init()
16
- *
17
- * @return void
18
- */
19
- public function __construct() {
20
- $this->init();
21
- }
22
-
23
- /**
24
- * Initiate the plugin class.
25
- *
26
- * @return void
27
- */
28
- public function init() {
29
- include_once ABSPATH . 'wp-admin/includes/class-wp-upgrader.php';
30
- }
31
-
32
- /**
33
- * Run tests to determine if auto-updates can run.
34
- *
35
- * @uses get_class_methods()
36
- * @uses substr()
37
- * @uses call_user_func()
38
- *
39
- * @return array
40
- */
41
- public function run_tests() {
42
- $tests = array();
43
-
44
- foreach ( get_class_methods( $this ) as $method ) {
45
- if ( 'test_' !== substr( $method, 0, 5 ) ) {
46
- continue;
47
- }
48
-
49
- $result = call_user_func( array( $this, $method ) );
50
-
51
- if ( false === $result || null === $result ) {
52
- continue;
53
- }
54
-
55
- $result = (object) $result;
56
-
57
- if ( empty( $result->severity ) ) {
58
- $result->severity = 'warning';
59
- }
60
-
61
- $tests[ $method ] = $result;
62
- }
63
-
64
- return $tests;
65
- }
66
-
67
- /**
68
- * Test if file modifications are possible.
69
- *
70
- * @uses defined()
71
- * @uses sprintf()
72
- * @uses esc_html__()
73
- *
74
- * @return array
75
- */
76
- function test_constant_FILE_MODS() {
77
- if ( defined( 'DISALLOW_FILE_MODS' ) && DISALLOW_FILE_MODS ) {
78
- return array(
79
- 'desc' => sprintf(
80
- /* translators: %s: Name of the constant used. */
81
- esc_html__( 'The %s constant is defined and enabled.', 'health-check' ),
82
- '<code>DISALLOW_FILE_MODS</code>'
83
- ),
84
- 'severity' => 'fail',
85
- );
86
- }
87
- }
88
-
89
- /**
90
- * Check if automatic updates are disabled with a constant.
91
- *
92
- * @uses defined()
93
- * @uses sprintf()
94
- * @uses esc_html__()
95
- *
96
- * @return array
97
- */
98
- function test_constant_AUTOMATIC_UPDATER_DISABLED() {
99
- if ( defined( 'AUTOMATIC_UPDATER_DISABLED' ) && AUTOMATIC_UPDATER_DISABLED ) {
100
- return array(
101
- 'desc' => sprintf(
102
- /* translators: %s: Name of the constant used. */
103
- esc_html__( 'The %s constant is defined and enabled.', 'health-check' ),
104
- '<code>AUTOMATIC_UPDATER_DISABLED</code>'
105
- ),
106
- 'severity' => 'fail',
107
- );
108
- }
109
- }
110
-
111
- /**
112
- * Check if automatic core updates are disabled with a constant.
113
- *
114
- * @uses defined()
115
- * @uses sprintf()
116
- * @uses esc_html__()
117
- *
118
- * @return array
119
- */
120
- function test_constant_WP_AUTO_UPDATE_CORE() {
121
- if ( defined( 'WP_AUTO_UPDATE_CORE' ) && false === WP_AUTO_UPDATE_CORE ) {
122
- return array(
123
- 'desc' => sprintf(
124
- /* translators: %s: Name of the constant used. */
125
- esc_html__( 'The %s constant is defined and enabled.', 'health-check' ),
126
- '<code>WP_AUTO_UPDATE_CORE</code>'
127
- ),
128
- 'severity' => 'fail',
129
- );
130
- }
131
- }
132
-
133
- /**
134
- * Check if updates are intercepted by a filter.
135
- *
136
- * @uses has_filter()
137
- * @uses sprintf()
138
- * @uses esc_html__()
139
- *
140
- * @return array
141
- */
142
- function test_wp_version_check_attached() {
143
- if ( ! has_filter( 'wp_version_check', 'wp_version_check' ) ) {
144
- return array(
145
- 'desc' => sprintf(
146
- /* translators: %s: Name of the filter used. */
147
- esc_html__( 'A plugin has prevented updates by disabling %s.', 'health-check' ),
148
- '<code>wp_version_check()</code>'
149
- ),
150
- 'severity' => 'fail',
151
- );
152
- }
153
- }
154
-
155
- /**
156
- * Check if automatic updates are disabled by a filter.
157
- *
158
- * @uses apply_filters()
159
- * @uses sprintf()
160
- * @uses esc_html__()
161
- *
162
- * @return array
163
- */
164
- function test_filters_automatic_updater_disabled() {
165
- if ( apply_filters( 'automatic_updater_disabled', false ) ) {
166
- return array(
167
- 'desc' => sprintf(
168
- /* translators: %s: Name of the filter used. */
169
- esc_html__( 'The %s filter is enabled.', 'health-check' ),
170
- '<code>automatic_updater_disabled</code>'
171
- ),
172
- 'severity' => 'fail',
173
- );
174
- }
175
- }
176
-
177
- /**
178
- * Check if automatic updates have tried to run, but failed, previously.
179
- *
180
- * @uses get_site_option()
181
- * @uses esc_html__()
182
- * @uses sprintf()
183
- *
184
- * @return array|bool
185
- */
186
- function test_if_failed_update() {
187
- $failed = get_site_option( 'auto_core_update_failed' );
188
-
189
- if ( ! $failed ) {
190
- return false;
191
- }
192
-
193
- if ( ! empty( $failed['critical'] ) ) {
194
- $desc = esc_html__( 'A previous automatic background update ended with a critical failure, so updates are now disabled.', 'health-check' );
195
- $desc .= ' ' . esc_html__( 'You would have received an email because of this.', 'health-check' );
196
- $desc .= ' ' . esc_html__( "When you've been able to update using the \"Update Now\" button on Dashboard > Updates, we'll clear this error for future update attempts.", 'health-check' );
197
- $desc .= ' ' . sprintf(
198
- /* translators: %s: Code of error shown. */
199
- esc_html__( 'The error code was %s.', 'health-check' ),
200
- '<code>' . $failed['error_code'] . '</code>'
201
- );
202
- return array(
203
- 'desc' => $desc,
204
- 'severity' => 'warning',
205
- );
206
- }
207
-
208
- $desc = esc_html__( 'A previous automatic background update could not occur.', 'health-check' );
209
- if ( empty( $failed['retry'] ) ) {
210
- $desc .= ' ' . esc_html__( 'You would have received an email because of this.', 'health-check' );
211
- }
212
-
213
- $desc .= ' ' . esc_html__( "We'll try again with the next release.", 'health-check' );
214
- $desc .= ' ' . sprintf(
215
- /* translators: %s: Code of error shown. */
216
- esc_html__( 'The error code was %s.', 'health-check' ),
217
- '<code>' . $failed['error_code'] . '</code>'
218
- );
219
- return array(
220
- 'desc' => $desc,
221
- 'severity' => 'warning',
222
- );
223
- }
224
-
225
- /**
226
- * Check if WordPress is controlled by a VCS (Git, Subversion etc).
227
- *
228
- * @uses dirname()
229
- * @uses array_unique()
230
- * @uses is_dir()
231
- * @uses rtrim()
232
- * @uses apply_filters()
233
- * @uses sprintf()
234
- * @uses esc_html__()
235
- *
236
- * @param string $context The path to check from.
237
- *
238
- * @return array
239
- */
240
- function _test_is_vcs_checkout( $context ) {
241
- $context_dirs = array( ABSPATH );
242
- $vcs_dirs = array( '.svn', '.git', '.hg', '.bzr' );
243
- $check_dirs = array();
244
-
245
- foreach ( $context_dirs as $context_dir ) {
246
- // Walk up from $context_dir to the root.
247
- do {
248
- $check_dirs[] = $context_dir;
249
-
250
- // Once we've hit '/' or 'C:\', we need to stop. dirname will keep returning the input here.
251
- if ( dirname( $context_dir ) == $context_dir ) {
252
- break;
253
- }
254
-
255
- // Continue one level at a time.
256
- } while ( $context_dir = dirname( $context_dir ) );
257
- }
258
-
259
- $check_dirs = array_unique( $check_dirs );
260
-
261
- // Search all directories we've found for evidence of version control.
262
- foreach ( $vcs_dirs as $vcs_dir ) {
263
- foreach ( $check_dirs as $check_dir ) {
264
- if ( $checkout = @is_dir( rtrim( $check_dir, '\\/' ) . "/$vcs_dir" ) ) {
265
- break 2;
266
- }
267
- }
268
- }
269
-
270
- if ( $checkout && ! apply_filters( 'automatic_updates_is_vcs_checkout', true, $context ) ) {
271
- return array(
272
- 'desc' => sprintf(
273
- // translators: %1$s: Folder name. %2$s: Version control directory. %3$s: Filter name.
274
- esc_html__( 'The folder %1$s was detected as being under version control (%2$s), but the %3$s filter is allowing updates.', 'health-check' ),
275
- '<code>' . $check_dir . '</code>',
276
- "<code>$vcs_dir</code>",
277
- '<code>automatic_updates_is_vcs_checkout</code>'
278
- ),
279
- 'severity' => 'info',
280
- );
281
- }
282
-
283
- if ( $checkout ) {
284
- return array(
285
- 'desc' => sprintf(
286
- // translators: %1$s: Folder name. %2$s: Version control directory.
287
- esc_html__( 'The folder %1$s was detected as being under version control (%2$s).', 'health-check' ),
288
- '<code>' . $check_dir . '</code>',
289
- "<code>$vcs_dir</code>"
290
- ),
291
- 'severity' => 'fail',
292
- );
293
- }
294
-
295
- return array(
296
- 'desc' => esc_html__( 'No version control systems were detected.', 'health-check' ),
297
- 'severity' => 'pass',
298
- );
299
- }
300
-
301
- /**
302
- * Check if the absolute path is under Version Control.
303
- *
304
- * @uses Health_Check_Auto_Updates::_test_is_vcs_checkout()
305
- *
306
- * @return array
307
- */
308
- function test_vcs_ABSPATH() {
309
- $result = $this->_test_is_vcs_checkout( ABSPATH );
310
- return $result;
311
- }
312
-
313
- /**
314
- * Check if we can access files without providing credentials.
315
- *
316
- * @uses Automatic_Upgrader_Skin
317
- * @uses Automatic_Upgrader_Skin::request_filesystem_credentials()
318
- * @uses esc_html__()
319
- *
320
- * @return array
321
- */
322
- function test_check_wp_filesystem_method() {
323
- $skin = new Automatic_Upgrader_Skin;
324
- $success = $skin->request_filesystem_credentials( false, ABSPATH );
325
-
326
- if ( ! $success ) {
327
- $desc = esc_html__( 'Your installation of WordPress prompts for FTP credentials to perform updates.', 'health-check' );
328
- $desc .= ' ' . esc_html__( '(Your site is performing updates over FTP due to file ownership. Talk to your hosting company.)', 'health-check' );
329
-
330
- return array(
331
- 'desc' => $desc,
332
- 'severity' => 'fail',
333
- );
334
- }
335
-
336
- return array(
337
- 'desc' => esc_html__( "Your installation of WordPress doesn't require FTP credentials to perform updates.", 'health-check' ),
338
- 'severity' => 'pass',
339
- );
340
- }
341
-
342
- /**
343
- * Check if core files are writeable by the web user/group.
344
- *
345
- * @global $wp_filesystem
346
- *
347
- * @uses Automatic_Upgrader_Skin
348
- * @uses Automatic_Upgrader_Skin::request_filesystem_credentials()
349
- * @uses WP_Filesystem
350
- * @uses WP_Filesystem::method
351
- * @uses get_core_checksums()
352
- * @uses strpos()
353
- * @uses sprintf()
354
- * @uses esc_html__()
355
- * @uses array_keys()
356
- * @uses substr()
357
- * @uses file_exists()
358
- * @uses is_writable()
359
- * @uses count()
360
- * @uses array_slice()
361
- * @uses implode()
362
- *
363
- * @return array|bool
364
- */
365
- function test_all_files_writable() {
366
- global $wp_filesystem;
367
- include ABSPATH . WPINC . '/version.php'; // $wp_version; // x.y.z
368
-
369
- $skin = new Automatic_Upgrader_Skin;
370
- $success = $skin->request_filesystem_credentials( false, ABSPATH );
371
-
372
- if ( ! $success ) {
373
- return false;
374
- }
375
-
376
- WP_Filesystem();
377
-
378
- if ( 'direct' != $wp_filesystem->method ) {
379
- return false;
380
- }
381
-
382
- $checksums = get_core_checksums( $wp_version, 'en_US' );
383
- $dev = ( false !== strpos( $wp_version, '-' ) );
384
- // Get the last stable version's files and test against that
385
- if ( ! $checksums && $dev ) {
386
- $checksums = get_core_checksums( (float) $wp_version - 0.1, 'en_US' );
387
- }
388
-
389
- // There aren't always checksums for development releases, so just skip the test if we still can't find any
390
- if ( ! $checksums && $dev ) {
391
- return false;
392
- }
393
-
394
- if ( ! $checksums ) {
395
- $desc = sprintf(
396
- // translators: %s: WordPress version
397
- esc_html__( "Couldn't retrieve a list of the checksums for WordPress %s.", 'health-check' ),
398
- $wp_version
399
- );
400
- $desc .= ' ' . esc_html__( 'This could mean that connections are failing to WordPress.org.', 'health-check' );
401
- return array(
402
- 'desc' => $desc,
403
- 'severity' => 'warning',
404
- );
405
- }
406
-
407
- $unwritable_files = array();
408
- foreach ( array_keys( $checksums ) as $file ) {
409
- if ( 'wp-content' == substr( $file, 0, 10 ) ) {
410
- continue;
411
- }
412
- if ( ! file_exists( ABSPATH . '/' . $file ) ) {
413
- continue;
414
- }
415
- if ( ! is_writable( ABSPATH . '/' . $file ) ) {
416
- $unwritable_files[] = $file;
417
- }
418
- }
419
-
420
- if ( $unwritable_files ) {
421
- if ( count( $unwritable_files ) > 20 ) {
422
- $unwritable_files = array_slice( $unwritable_files, 0, 20 );
423
- $unwritable_files[] = '...';
424
- }
425
- return array(
426
- 'desc' => esc_html__( 'Some files are not writable by WordPress:', 'health-check' ) . ' <ul><li>' . implode( '</li><li>', $unwritable_files ) . '</li></ul>',
427
- 'severity' => 'fail',
428
- );
429
- } else {
430
- return array(
431
- 'desc' => esc_html__( 'All of your WordPress files are writable.', 'health-check' ),
432
- 'severity' => 'pass',
433
- );
434
- }
435
- }
436
-
437
- /**
438
- * Check if the install is using a development branch and can use nightly packages.
439
- *
440
- * @uses strpos()
441
- * @uses defined()
442
- * @uses sprintf()
443
- * @uses esc_html__()
444
- * @uses apply_filters()
445
- *
446
- * @return array|bool
447
- */
448
- function test_accepts_dev_updates() {
449
- include ABSPATH . WPINC . '/version.php'; // $wp_version; // x.y.z
450
- // Only for dev versions
451
- if ( false === strpos( $wp_version, '-' ) ) {
452
- return false;
453
- }
454
-
455
- if ( defined( 'WP_AUTO_UPDATE_CORE' ) && ( 'minor' === WP_AUTO_UPDATE_CORE || false === WP_AUTO_UPDATE_CORE ) ) {
456
- return array(
457
- 'desc' => sprintf(
458
- /* translators: %s: Name of the constant used. */
459
- esc_html__( 'WordPress development updates are blocked by the %s constant.', 'health-check' ),
460
- '<code>WP_AUTO_UPDATE_CORE</code>'
461
- ),
462
- 'severity' => 'fail',
463
- );
464
- }
465
-
466
- if ( ! apply_filters( 'allow_dev_auto_core_updates', $wp_version ) ) {
467
- return array(
468
- 'desc' => sprintf(
469
- /* translators: %s: Name of the filter used. */
470
- esc_html__( 'WordPress development updates are blocked by the %s filter.', 'health-check' ),
471
- '<code>allow_dev_auto_core_updates</code>'
472
- ),
473
- 'severity' => 'fail',
474
- );
475
- }
476
- }
477
-
478
- /**
479
- * Check if the site supports automatic minor updates.
480
- *
481
- * @uses defined()
482
- * @uses sprintf()
483
- * @uses esc_html__()
484
- * @uses apply_filters()
485
- *
486
- * @return array
487
- */
488
- function test_accepts_minor_updates() {
489
- if ( defined( 'WP_AUTO_UPDATE_CORE' ) && false === WP_AUTO_UPDATE_CORE ) {
490
- return array(
491
- 'desc' => sprintf(
492
- /* translators: %s: Name of the constant used. */
493
- esc_html__( 'WordPress security and maintenance releases are blocked by %s.', 'health-check' ),
494
- "<code>define( 'WP_AUTO_UPDATE_CORE', false );</code>"
495
- ),
496
- 'severity' => 'fail',
497
- );
498
- }
499
-
500
- if ( ! apply_filters( 'allow_minor_auto_core_updates', true ) ) {
501
- return array(
502
- 'desc' => sprintf(
503
- /* translators: %s: Name of the filter used. */
504
- esc_html__( 'WordPress security and maintenance releases are blocked by the %s filter.', 'health-check' ),
505
- '<code>allow_minor_auto_core_updates</code>'
506
- ),
507
- 'severity' => 'fail',
508
- );
509
- }
510
- }
511
- }
 
1
+ <?php
2
+ /**
3
+ * Class for testing automatic updates in the WordPress code.
4
+ *
5
+ * @package Health Check
6
+ */
7
+
8
+ /**
9
+ * Class Health_Check_Auto_Updates
10
+ */
11
+ class Health_Check_Auto_Updates {
12
+ /**
13
+ * Health_Check_Auto_Updates constructor.
14
+ *
15
+ * @uses HealthCheck::init()
16
+ *
17
+ * @return void
18
+ */
19
+ public function __construct() {
20
+ $this->init();
21
+ }
22
+
23
+ /**
24
+ * Initiate the plugin class.
25
+ *
26
+ * @return void
27
+ */
28
+ public function init() {
29
+ include_once ABSPATH . 'wp-admin/includes/class-wp-upgrader.php';
30
+ }
31
+
32
+ /**
33
+ * Run tests to determine if auto-updates can run.
34
+ *
35
+ * @uses get_class_methods()
36
+ * @uses substr()
37
+ * @uses call_user_func()
38
+ *
39
+ * @return array
40
+ */
41
+ public function run_tests() {
42
+ $tests = array();
43
+
44
+ foreach ( get_class_methods( $this ) as $method ) {
45
+ if ( 'test_' !== substr( $method, 0, 5 ) ) {
46
+ continue;
47
+ }
48
+
49
+ $result = call_user_func( array( $this, $method ) );
50
+
51
+ if ( false === $result || null === $result ) {
52
+ continue;
53
+ }
54
+
55
+ $result = (object) $result;
56
+
57
+ if ( empty( $result->severity ) ) {
58
+ $result->severity = 'warning';
59
+ }
60
+
61
+ $tests[ $method ] = $result;
62
+ }
63
+
64
+ return $tests;
65
+ }
66
+
67
+ /**
68
+ * Test if file modifications are possible.
69
+ *
70
+ * @uses defined()
71
+ * @uses sprintf()
72
+ * @uses esc_html__()
73
+ *
74
+ * @return array
75
+ */
76
+ function test_constant_FILE_MODS() {
77
+ if ( defined( 'DISALLOW_FILE_MODS' ) && DISALLOW_FILE_MODS ) {
78
+ return array(
79
+ 'desc' => sprintf(
80
+ /* translators: %s: Name of the constant used. */
81
+ esc_html__( 'The %s constant is defined and enabled.', 'health-check' ),
82
+ '<code>DISALLOW_FILE_MODS</code>'
83
+ ),
84
+ 'severity' => 'fail',
85
+ );
86
+ }
87
+ }
88
+
89
+ /**
90
+ * Check if automatic updates are disabled with a constant.
91
+ *
92
+ * @uses defined()
93
+ * @uses sprintf()
94
+ * @uses esc_html__()
95
+ *
96
+ * @return array
97
+ */
98
+ function test_constant_AUTOMATIC_UPDATER_DISABLED() {
99
+ if ( defined( 'AUTOMATIC_UPDATER_DISABLED' ) && AUTOMATIC_UPDATER_DISABLED ) {
100
+ return array(
101
+ 'desc' => sprintf(
102
+ /* translators: %s: Name of the constant used. */
103
+ esc_html__( 'The %s constant is defined and enabled.', 'health-check' ),
104
+ '<code>AUTOMATIC_UPDATER_DISABLED</code>'
105
+ ),
106
+ 'severity' => 'fail',
107
+ );
108
+ }
109
+ }
110
+
111
+ /**
112
+ * Check if automatic core updates are disabled with a constant.
113
+ *
114
+ * @uses defined()
115
+ * @uses sprintf()
116
+ * @uses esc_html__()
117
+ *
118
+ * @return array
119
+ */
120
+ function test_constant_WP_AUTO_UPDATE_CORE() {
121
+ if ( defined( 'WP_AUTO_UPDATE_CORE' ) && false === WP_AUTO_UPDATE_CORE ) {
122
+ return array(
123
+ 'desc' => sprintf(
124
+ /* translators: %s: Name of the constant used. */
125
+ esc_html__( 'The %s constant is defined and enabled.', 'health-check' ),
126
+ '<code>WP_AUTO_UPDATE_CORE</code>'
127
+ ),
128
+ 'severity' => 'fail',
129
+ );
130
+ }
131
+ }
132
+
133
+ /**
134
+ * Check if updates are intercepted by a filter.
135
+ *
136
+ * @uses has_filter()
137
+ * @uses sprintf()
138
+ * @uses esc_html__()
139
+ *
140
+ * @return array
141
+ */
142
+ function test_wp_version_check_attached() {
143
+ if ( ! has_filter( 'wp_version_check', 'wp_version_check' ) ) {
144
+ return array(
145
+ 'desc' => sprintf(
146
+ /* translators: %s: Name of the filter used. */
147
+ esc_html__( 'A plugin has prevented updates by disabling %s.', 'health-check' ),
148
+ '<code>wp_version_check()</code>'
149
+ ),
150
+ 'severity' => 'fail',
151
+ );
152
+ }
153
+ }
154
+
155
+ /**
156
+ * Check if automatic updates are disabled by a filter.
157
+ *
158
+ * @uses apply_filters()
159
+ * @uses sprintf()
160
+ * @uses esc_html__()
161
+ *
162
+ * @return array
163
+ */
164
+ function test_filters_automatic_updater_disabled() {
165
+ if ( apply_filters( 'automatic_updater_disabled', false ) ) {
166
+ return array(
167
+ 'desc' => sprintf(
168
+ /* translators: %s: Name of the filter used. */
169
+ esc_html__( 'The %s filter is enabled.', 'health-check' ),
170
+ '<code>automatic_updater_disabled</code>'
171
+ ),
172
+ 'severity' => 'fail',
173
+ );
174
+ }
175
+ }
176
+
177
+ /**
178
+ * Check if automatic updates have tried to run, but failed, previously.
179
+ *
180
+ * @uses get_site_option()
181
+ * @uses esc_html__()
182
+ * @uses sprintf()
183
+ *
184
+ * @return array|bool
185
+ */
186
+ function test_if_failed_update() {
187
+ $failed = get_site_option( 'auto_core_update_failed' );
188
+
189
+ if ( ! $failed ) {
190
+ return false;
191
+ }
192
+
193
+ if ( ! empty( $failed['critical'] ) ) {
194
+ $desc = esc_html__( 'A previous automatic background update ended with a critical failure, so updates are now disabled.', 'health-check' );
195
+ $desc .= ' ' . esc_html__( 'You would have received an email because of this.', 'health-check' );
196
+ $desc .= ' ' . esc_html__( "When you've been able to update using the \"Update Now\" button on Dashboard > Updates, we'll clear this error for future update attempts.", 'health-check' );
197
+ $desc .= ' ' . sprintf(
198
+ /* translators: %s: Code of error shown. */
199
+ esc_html__( 'The error code was %s.', 'health-check' ),
200
+ '<code>' . $failed['error_code'] . '</code>'
201
+ );
202
+ return array(
203
+ 'desc' => $desc,
204
+ 'severity' => 'warning',
205
+ );
206
+ }
207
+
208
+ $desc = esc_html__( 'A previous automatic background update could not occur.', 'health-check' );
209
+ if ( empty( $failed['retry'] ) ) {
210
+ $desc .= ' ' . esc_html__( 'You would have received an email because of this.', 'health-check' );
211
+ }
212
+
213
+ $desc .= ' ' . esc_html__( "We'll try again with the next release.", 'health-check' );
214
+ $desc .= ' ' . sprintf(
215
+ /* translators: %s: Code of error shown. */
216
+ esc_html__( 'The error code was %s.', 'health-check' ),
217
+ '<code>' . $failed['error_code'] . '</code>'
218
+ );
219
+ return array(
220
+ 'desc' => $desc,
221
+ 'severity' => 'warning',
222
+ );
223
+ }
224
+
225
+ /**
226
+ * Check if WordPress is controlled by a VCS (Git, Subversion etc).
227
+ *
228
+ * @uses dirname()
229
+ * @uses array_unique()
230
+ * @uses is_dir()
231
+ * @uses rtrim()
232
+ * @uses apply_filters()
233
+ * @uses sprintf()
234
+ * @uses esc_html__()
235
+ *
236
+ * @param string $context The path to check from.
237
+ *
238
+ * @return array
239
+ */
240
+ function _test_is_vcs_checkout( $context ) {
241
+ $context_dirs = array( ABSPATH );
242
+ $vcs_dirs = array( '.svn', '.git', '.hg', '.bzr' );
243
+ $check_dirs = array();
244
+
245
+ foreach ( $context_dirs as $context_dir ) {
246
+ // Walk up from $context_dir to the root.
247
+ do {
248
+ $check_dirs[] = $context_dir;
249
+
250
+ // Once we've hit '/' or 'C:\', we need to stop. dirname will keep returning the input here.
251
+ if ( dirname( $context_dir ) == $context_dir ) {
252
+ break;
253
+ }
254
+
255
+ // Continue one level at a time.
256
+ } while ( $context_dir = dirname( $context_dir ) );
257
+ }
258
+
259
+ $check_dirs = array_unique( $check_dirs );
260
+
261
+ // Search all directories we've found for evidence of version control.
262
+ foreach ( $vcs_dirs as $vcs_dir ) {
263
+ foreach ( $check_dirs as $check_dir ) {
264
+ // phpcs:ignore
265
+ if ( $checkout = @is_dir( rtrim( $check_dir, '\\/' ) . "/$vcs_dir" ) ) {
266
+ break 2;
267
+ }
268
+ }
269
+ }
270
+
271
+ if ( $checkout && ! apply_filters( 'automatic_updates_is_vcs_checkout', true, $context ) ) {
272
+ return array(
273
+ 'desc' => sprintf(
274
+ // translators: %1$s: Folder name. %2$s: Version control directory. %3$s: Filter name.
275
+ esc_html__( 'The folder %1$s was detected as being under version control (%2$s), but the %3$s filter is allowing updates.', 'health-check' ),
276
+ '<code>' . $check_dir . '</code>',
277
+ "<code>$vcs_dir</code>",
278
+ '<code>automatic_updates_is_vcs_checkout</code>'
279
+ ),
280
+ 'severity' => 'info',
281
+ );
282
+ }
283
+
284
+ if ( $checkout ) {
285
+ return array(
286
+ 'desc' => sprintf(
287
+ // translators: %1$s: Folder name. %2$s: Version control directory.
288
+ esc_html__( 'The folder %1$s was detected as being under version control (%2$s).', 'health-check' ),
289
+ '<code>' . $check_dir . '</code>',
290
+ "<code>$vcs_dir</code>"
291
+ ),
292
+ 'severity' => 'fail',
293
+ );
294
+ }
295
+
296
+ return array(
297
+ 'desc' => esc_html__( 'No version control systems were detected.', 'health-check' ),
298
+ 'severity' => 'pass',
299
+ );
300
+ }
301
+
302
+ /**
303
+ * Check if the absolute path is under Version Control.
304
+ *
305
+ * @uses Health_Check_Auto_Updates::_test_is_vcs_checkout()
306
+ *
307
+ * @return array
308
+ */
309
+ function test_vcs_ABSPATH() {
310
+ $result = $this->_test_is_vcs_checkout( ABSPATH );
311
+ return $result;
312
+ }
313
+
314
+ /**
315
+ * Check if we can access files without providing credentials.
316
+ *
317
+ * @uses Automatic_Upgrader_Skin
318
+ * @uses Automatic_Upgrader_Skin::request_filesystem_credentials()
319
+ * @uses esc_html__()
320
+ *
321
+ * @return array
322
+ */
323
+ function test_check_wp_filesystem_method() {
324
+ $skin = new Automatic_Upgrader_Skin;
325
+ $success = $skin->request_filesystem_credentials( false, ABSPATH );
326
+
327
+ if ( ! $success ) {
328
+ $desc = esc_html__( 'Your installation of WordPress prompts for FTP credentials to perform updates.', 'health-check' );
329
+ $desc .= ' ' . esc_html__( '(Your site is performing updates over FTP due to file ownership. Talk to your hosting company.)', 'health-check' );
330
+
331
+ return array(
332
+ 'desc' => $desc,
333
+ 'severity' => 'fail',
334
+ );
335
+ }
336
+
337
+ return array(
338
+ 'desc' => esc_html__( "Your installation of WordPress doesn't require FTP credentials to perform updates.", 'health-check' ),
339
+ 'severity' => 'pass',
340
+ );
341
+ }
342
+
343
+ /**
344
+ * Check if core files are writeable by the web user/group.
345
+ *
346
+ * @global $wp_filesystem
347
+ *
348
+ * @uses Automatic_Upgrader_Skin
349
+ * @uses Automatic_Upgrader_Skin::request_filesystem_credentials()
350
+ * @uses WP_Filesystem
351
+ * @uses WP_Filesystem::method
352
+ * @uses get_core_checksums()
353
+ * @uses strpos()
354
+ * @uses sprintf()
355
+ * @uses esc_html__()
356
+ * @uses array_keys()
357
+ * @uses substr()
358
+ * @uses file_exists()
359
+ * @uses is_writable()
360
+ * @uses count()
361
+ * @uses array_slice()
362
+ * @uses implode()
363
+ *
364
+ * @return array|bool
365
+ */
366
+ function test_all_files_writable() {
367
+ global $wp_filesystem;
368
+ include ABSPATH . WPINC . '/version.php'; // $wp_version; // x.y.z
369
+
370
+ $skin = new Automatic_Upgrader_Skin;
371
+ $success = $skin->request_filesystem_credentials( false, ABSPATH );
372
+
373
+ if ( ! $success ) {
374
+ return false;
375
+ }
376
+
377
+ WP_Filesystem();
378
+
379
+ if ( 'direct' != $wp_filesystem->method ) {
380
+ return false;
381
+ }
382
+
383
+ $checksums = get_core_checksums( $wp_version, 'en_US' );
384
+ $dev = ( false !== strpos( $wp_version, '-' ) );
385
+ // Get the last stable version's files and test against that
386
+ if ( ! $checksums && $dev ) {
387
+ $checksums = get_core_checksums( (float) $wp_version - 0.1, 'en_US' );
388
+ }
389
+
390
+ // There aren't always checksums for development releases, so just skip the test if we still can't find any
391
+ if ( ! $checksums && $dev ) {
392
+ return false;
393
+ }
394
+
395
+ if ( ! $checksums ) {
396
+ $desc = sprintf(
397
+ // translators: %s: WordPress version
398
+ esc_html__( "Couldn't retrieve a list of the checksums for WordPress %s.", 'health-check' ),
399
+ $wp_version
400
+ );
401
+ $desc .= ' ' . esc_html__( 'This could mean that connections are failing to WordPress.org.', 'health-check' );
402
+ return array(
403
+ 'desc' => $desc,
404
+ 'severity' => 'warning',
405
+ );
406
+ }
407
+
408
+ $unwritable_files = array();
409
+ foreach ( array_keys( $checksums ) as $file ) {
410
+ if ( 'wp-content' == substr( $file, 0, 10 ) ) {
411
+ continue;
412
+ }
413
+ if ( ! file_exists( ABSPATH . '/' . $file ) ) {
414
+ continue;
415
+ }
416
+ if ( ! is_writable( ABSPATH . '/' . $file ) ) {
417
+ $unwritable_files[] = $file;
418
+ }
419
+ }
420
+
421
+ if ( $unwritable_files ) {
422
+ if ( count( $unwritable_files ) > 20 ) {
423
+ $unwritable_files = array_slice( $unwritable_files, 0, 20 );
424
+ $unwritable_files[] = '...';
425
+ }
426
+ return array(
427
+ 'desc' => esc_html__( 'Some files are not writable by WordPress:', 'health-check' ) . ' <ul><li>' . implode( '</li><li>', $unwritable_files ) . '</li></ul>',
428
+ 'severity' => 'fail',
429
+ );
430
+ } else {
431
+ return array(
432
+ 'desc' => esc_html__( 'All of your WordPress files are writable.', 'health-check' ),
433
+ 'severity' => 'pass',
434
+ );
435
+ }
436
+ }
437
+
438
+ /**
439
+ * Check if the install is using a development branch and can use nightly packages.
440
+ *
441
+ * @uses strpos()
442
+ * @uses defined()
443
+ * @uses sprintf()
444
+ * @uses esc_html__()
445
+ * @uses apply_filters()
446
+ *
447
+ * @return array|bool
448
+ */
449
+ function test_accepts_dev_updates() {
450
+ include ABSPATH . WPINC . '/version.php'; // $wp_version; // x.y.z
451
+ // Only for dev versions
452
+ if ( false === strpos( $wp_version, '-' ) ) {
453
+ return false;
454
+ }
455
+
456
+ if ( defined( 'WP_AUTO_UPDATE_CORE' ) && ( 'minor' === WP_AUTO_UPDATE_CORE || false === WP_AUTO_UPDATE_CORE ) ) {
457
+ return array(
458
+ 'desc' => sprintf(
459
+ /* translators: %s: Name of the constant used. */
460
+ esc_html__( 'WordPress development updates are blocked by the %s constant.', 'health-check' ),
461
+ '<code>WP_AUTO_UPDATE_CORE</code>'
462
+ ),
463
+ 'severity' => 'fail',
464
+ );
465
+ }
466
+
467
+ if ( ! apply_filters( 'allow_dev_auto_core_updates', $wp_version ) ) {
468
+ return array(
469
+ 'desc' => sprintf(
470
+ /* translators: %s: Name of the filter used. */
471
+ esc_html__( 'WordPress development updates are blocked by the %s filter.', 'health-check' ),
472
+ '<code>allow_dev_auto_core_updates</code>'
473
+ ),
474
+ 'severity' => 'fail',
475
+ );
476
+ }
477
+ }
478
+
479
+ /**
480
+ * Check if the site supports automatic minor updates.
481
+ *
482
+ * @uses defined()
483
+ * @uses sprintf()
484
+ * @uses esc_html__()
485
+ * @uses apply_filters()
486
+ *
487
+ * @return array
488
+ */
489
+ function test_accepts_minor_updates() {
490
+ if ( defined( 'WP_AUTO_UPDATE_CORE' ) && false === WP_AUTO_UPDATE_CORE ) {
491
+ return array(
492
+ 'desc' => sprintf(
493
+ /* translators: %s: Name of the constant used. */
494
+ esc_html__( 'WordPress security and maintenance releases are blocked by %s.', 'health-check' ),
495
+ "<code>define( 'WP_AUTO_UPDATE_CORE', false );</code>"
496
+ ),
497
+ 'severity' => 'fail',
498
+ );
499
+ }
500
+
501
+ if ( ! apply_filters( 'allow_minor_auto_core_updates', true ) ) {
502
+ return array(
503
+ 'desc' => sprintf(
504
+ /* translators: %s: Name of the filter used. */
505
+ esc_html__( 'WordPress security and maintenance releases are blocked by the %s filter.', 'health-check' ),
506
+ '<code>allow_minor_auto_core_updates</code>'
507
+ ),
508
+ 'severity' => 'fail',
509
+ );
510
+ }
511
+ }
512
+ }
includes/class-health-check-debug-data.php CHANGED
@@ -10,6 +10,23 @@
10
  */
11
  class Health_Check_Debug_Data {
12
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
13
  static function debug_data( $locale = null ) {
14
  if ( ! empty( $locale ) ) {
15
  // Change the language used for translations
@@ -23,17 +40,30 @@ class Health_Check_Debug_Data {
23
  $upload_dir = wp_upload_dir();
24
  if ( file_exists( ABSPATH . 'wp-config.php' ) ) {
25
  $wp_config_path = ABSPATH . 'wp-config.php';
 
26
  } elseif ( @file_exists( dirname( ABSPATH ) . '/wp-config.php' ) && ! @file_exists( dirname( ABSPATH ) . '/wp-settings.php' ) ) {
27
  $wp_config_path = dirname( ABSPATH ) . '/wp-config.php';
28
  }
29
 
 
 
 
 
 
 
 
 
 
 
 
 
30
  $info = array(
31
  'wp-core' => array(
32
  'label' => __( 'WordPress', 'health-check' ),
33
  'fields' => array(
34
  array(
35
  'label' => __( 'Version', 'health-check' ),
36
- 'value' => get_bloginfo( 'version' ),
37
  ),
38
  array(
39
  'label' => __( 'Language', 'health-check' ),
@@ -55,7 +85,7 @@ class Health_Check_Debug_Data {
55
  ),
56
  array(
57
  'label' => __( 'Is this site using HTTPS?', 'health-check' ),
58
- 'value' => ( is_ssl() ? __( 'Yes' ) : __( 'No' ) ),
59
  ),
60
  array(
61
  'label' => __( 'Can anyone register on this site?', 'health-check' ),
@@ -71,13 +101,17 @@ class Health_Check_Debug_Data {
71
  ),
72
  ),
73
  ),
 
 
 
 
74
  'wp-dropins' => array(
75
  'label' => __( 'Drop-ins', 'health-check' ),
76
  'description' => __( 'Drop-ins are single files that replace or enhance WordPress features in ways that are not possible for traditional plugins', 'health-check' ),
77
  'fields' => array(),
78
  ),
79
  'wp-active-theme' => array(
80
- 'label' => __( 'Active theme', 'health-check' ),
81
  'fields' => array(),
82
  ),
83
  'wp-themes' => array(
@@ -114,7 +148,7 @@ class Health_Check_Debug_Data {
114
  'fields' => array(),
115
  ),
116
  'wp-constants' => array(
117
- 'label' => __( 'WordPress constants', 'health-check' ),
118
  'description' => __( 'These values represent values set in your websites code which affect WordPress in various ways that may be of importance when seeking help with your site.', 'health-check' ),
119
  'fields' => array(
120
  array(
@@ -172,7 +206,7 @@ class Health_Check_Debug_Data {
172
  ),
173
  ),
174
  'wp-filesystem' => array(
175
- 'label' => __( 'Filesystem permissions', 'health-check' ),
176
  'description' => __( 'The status of various locations WordPress needs to write files in various scenarios.', 'health-check' ),
177
  'fields' => array(
178
  array(
@@ -234,7 +268,9 @@ class Health_Check_Debug_Data {
234
  }
235
 
236
  // WordPress features requiring processing.
237
- $wp_dotorg = wp_remote_get( 'https://wordpress.org', array( 'timeout' => 10 ) );
 
 
238
  if ( ! is_wp_error( $wp_dotorg ) ) {
239
  $info['wp-core']['fields'][] = array(
240
  'label' => __( 'Communication with WordPress.org', 'health-check' ),
@@ -285,11 +321,11 @@ class Health_Check_Debug_Data {
285
  $imagick_version = 'Imagick not available';
286
  }
287
  $info['wp-media']['fields'][] = array(
288
- 'label' => __( 'Imagick Module Version' ),
289
  'value' => ( is_array( $imagick_version ) ? $imagick_version['versionNumber'] : $imagick_version ),
290
  );
291
  $info['wp-media']['fields'][] = array(
292
- 'label' => __( 'ImageMagick Version' ),
293
  'value' => ( is_array( $imagick_version ) ? $imagick_version['versionString'] : $imagick_version ),
294
  );
295
 
@@ -317,19 +353,19 @@ class Health_Check_Debug_Data {
317
  $gd = false;
318
  }
319
  $info['wp-media']['fields'][] = array(
320
- 'label' => __( 'GD Version' ),
321
- 'value' => ( is_array( $gd ) ? $gd['GD Version'] : 'GD not available' ),
322
  );
323
 
324
  // Get Ghostscript information, if available.
325
  if ( function_exists( 'exec' ) ) {
326
  $gs = exec( 'gs --version' );
327
- $gs = ( ! empty( $gs ) ? $gs : 'Not available' );
328
  } else {
329
  $gs = __( 'Unable to determine if Ghostscript is installed', 'health-check' );
330
  }
331
  $info['wp-media']['fields'][] = array(
332
- 'label' => __( 'Ghostscript Version' ),
333
  'value' => $gs,
334
  );
335
 
@@ -385,10 +421,10 @@ class Health_Check_Debug_Data {
385
  }
386
 
387
  if ( function_exists( 'curl_version' ) ) {
388
- $cURL = curl_version();
389
  $info['wp-server']['fields'][] = array(
390
  'label' => __( 'cURL Version', 'health-check' ),
391
- 'value' => sprintf( '%s %s', $cURL['version'], $cURL['ssl_version'] ),
392
  );
393
  } else {
394
  $info['wp-server']['fields'][] = array(
@@ -407,6 +443,20 @@ class Health_Check_Debug_Data {
407
  'value' => ( extension_loaded( 'imagick' ) ? __( 'Yes', 'health-check' ) : __( 'No', 'health-check' ) ),
408
  );
409
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
410
  // Populate the database debug fields.
411
  if ( is_resource( $wpdb->dbh ) ) {
412
  // Old mysql extension.
@@ -421,8 +471,10 @@ class Health_Check_Debug_Data {
421
 
422
  if ( method_exists( $wpdb, 'db_version' ) ) {
423
  if ( $wpdb->use_mysqli ) {
 
424
  $server = mysqli_get_server_info( $wpdb->dbh );
425
  } else {
 
426
  $server = mysql_get_server_info( $wpdb->dbh );
427
  }
428
  } else {
@@ -432,6 +484,7 @@ class Health_Check_Debug_Data {
432
  if ( isset( $wpdb->use_mysqli ) && $wpdb->use_mysqli ) {
433
  $client_version = $wpdb->dbh->client_info;
434
  } else {
 
435
  if ( preg_match( '|[0-9]{1,2}\.[0-9]{1,2}\.[0-9]{1,2}|', mysql_get_client_info(), $matches ) ) {
436
  $client_version = $matches[0];
437
  } else {
@@ -500,7 +553,8 @@ class Health_Check_Debug_Data {
500
  }
501
 
502
  // List all available plugins.
503
- $plugins = get_plugins();
 
504
 
505
  foreach ( $plugins as $plugin_path => $plugin ) {
506
  $plugin_part = ( is_plugin_active( $plugin_path ) ) ? 'wp-plugins-active' : 'wp-plugins-inactive';
@@ -523,9 +577,16 @@ class Health_Check_Debug_Data {
523
  $plugin_version_string = sprintf( __( 'Version %s', 'health-check' ), $plugin_version );
524
  }
525
 
 
 
 
 
 
 
 
526
  $info[ $plugin_part ]['fields'][] = array(
527
  'label' => $plugin['Name'],
528
- 'value' => $plugin_version_string,
529
  );
530
  }
531
 
@@ -538,18 +599,30 @@ class Health_Check_Debug_Data {
538
  }
539
  }
540
 
541
- $active_theme = wp_get_theme();
 
 
 
 
 
 
 
 
 
542
  $info['wp-active-theme']['fields'] = array(
543
  array(
544
  'label' => __( 'Name', 'health-check' ),
 
545
  'value' => $active_theme->Name,
546
  ),
547
  array(
548
  'label' => __( 'Version', 'health-check' ),
549
- 'value' => $active_theme->Version,
 
550
  ),
551
  array(
552
  'label' => __( 'Author', 'health-check' ),
 
553
  'value' => wp_kses( $active_theme->Author, array() ),
554
  ),
555
  array(
@@ -574,9 +647,10 @@ class Health_Check_Debug_Data {
574
  if ( $active_theme->stylesheet == $theme_slug ) {
575
  continue;
576
  }
577
-
578
  $theme_version = $theme->Version;
579
- $theme_author = $theme->Author;
 
580
 
581
  $theme_version_string = __( 'No version or author information available', 'health-check' );
582
 
@@ -593,10 +667,22 @@ class Health_Check_Debug_Data {
593
  $theme_version_string = sprintf( __( 'Version %s', 'health-check' ), $theme_version );
594
  }
595
 
 
 
 
 
 
 
 
596
  $info['wp-themes']['fields'][] = array(
597
- // translators: %1$s: Theme name. %2$s: Theme slug.
598
- 'label' => sprintf( __( '%1$s (%2$s)', 'health-check' ), $theme->Name, $theme_slug ),
599
- 'value' => $theme_version_string,
 
 
 
 
 
600
  );
601
  }
602
 
@@ -608,6 +694,8 @@ class Health_Check_Debug_Data {
608
  );
609
  }
610
 
 
 
611
  /**
612
  * Add or modify new debug sections.
613
  *
@@ -657,4 +745,98 @@ class Health_Check_Debug_Data {
657
 
658
  return $info;
659
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
660
  }
10
  */
11
  class Health_Check_Debug_Data {
12
 
13
+ /**
14
+ * Calls all core funtions to check for updates
15
+ *
16
+ * @uses wp_version_check()
17
+ * @uses wp_update_plugins()
18
+ * @uses wp_update_themes()
19
+ *
20
+ * @return void
21
+ */
22
+ static function check_for_updates() {
23
+
24
+ wp_version_check();
25
+ wp_update_plugins();
26
+ wp_update_themes();
27
+
28
+ }
29
+
30
  static function debug_data( $locale = null ) {
31
  if ( ! empty( $locale ) ) {
32
  // Change the language used for translations
40
  $upload_dir = wp_upload_dir();
41
  if ( file_exists( ABSPATH . 'wp-config.php' ) ) {
42
  $wp_config_path = ABSPATH . 'wp-config.php';
43
+ // phpcs:ignore Generic.PHP.NoSilencedErrors.Discouraged
44
  } elseif ( @file_exists( dirname( ABSPATH ) . '/wp-config.php' ) && ! @file_exists( dirname( ABSPATH ) . '/wp-settings.php' ) ) {
45
  $wp_config_path = dirname( ABSPATH ) . '/wp-config.php';
46
  }
47
 
48
+ $core_current_version = get_bloginfo( 'version' );
49
+ $core_updates = get_core_updates();
50
+
51
+ foreach ( $core_updates as $core => $update ) {
52
+ if ( 'upgrade' === $update->response ) {
53
+ // translators: %s: Latest WordPress version number.
54
+ $core_update_needed = ' ' . sprintf( __( '( Latest version: %s )', 'health-check' ), $update->version );
55
+ } else {
56
+ $core_update_needed = '';
57
+ }
58
+ }
59
+
60
  $info = array(
61
  'wp-core' => array(
62
  'label' => __( 'WordPress', 'health-check' ),
63
  'fields' => array(
64
  array(
65
  'label' => __( 'Version', 'health-check' ),
66
+ 'value' => $core_current_version . $core_update_needed,
67
  ),
68
  array(
69
  'label' => __( 'Language', 'health-check' ),
85
  ),
86
  array(
87
  'label' => __( 'Is this site using HTTPS?', 'health-check' ),
88
+ 'value' => ( is_ssl() ? __( 'Yes', 'health-check' ) : __( 'No', 'health-check' ) ),
89
  ),
90
  array(
91
  'label' => __( 'Can anyone register on this site?', 'health-check' ),
101
  ),
102
  ),
103
  ),
104
+ 'wp-install-size' => array(
105
+ 'label' => __( 'Installation size', 'health-check' ),
106
+ 'fields' => array(),
107
+ ),
108
  'wp-dropins' => array(
109
  'label' => __( 'Drop-ins', 'health-check' ),
110
  'description' => __( 'Drop-ins are single files that replace or enhance WordPress features in ways that are not possible for traditional plugins', 'health-check' ),
111
  'fields' => array(),
112
  ),
113
  'wp-active-theme' => array(
114
+ 'label' => __( 'Active Theme', 'health-check' ),
115
  'fields' => array(),
116
  ),
117
  'wp-themes' => array(
148
  'fields' => array(),
149
  ),
150
  'wp-constants' => array(
151
+ 'label' => __( 'WordPress Constants', 'health-check' ),
152
  'description' => __( 'These values represent values set in your websites code which affect WordPress in various ways that may be of importance when seeking help with your site.', 'health-check' ),
153
  'fields' => array(
154
  array(
206
  ),
207
  ),
208
  'wp-filesystem' => array(
209
+ 'label' => __( 'Filesystem Permissions', 'health-check' ),
210
  'description' => __( 'The status of various locations WordPress needs to write files in various scenarios.', 'health-check' ),
211
  'fields' => array(
212
  array(
268
  }
269
 
270
  // WordPress features requiring processing.
271
+ $wp_dotorg = wp_remote_get( 'https://wordpress.org', array(
272
+ 'timeout' => 10,
273
+ ) );
274
  if ( ! is_wp_error( $wp_dotorg ) ) {
275
  $info['wp-core']['fields'][] = array(
276
  'label' => __( 'Communication with WordPress.org', 'health-check' ),
321
  $imagick_version = 'Imagick not available';
322
  }
323
  $info['wp-media']['fields'][] = array(
324
+ 'label' => __( 'Imagick Module Version', 'health-check' ),
325
  'value' => ( is_array( $imagick_version ) ? $imagick_version['versionNumber'] : $imagick_version ),
326
  );
327
  $info['wp-media']['fields'][] = array(
328
+ 'label' => __( 'ImageMagick Version', 'health-check' ),
329
  'value' => ( is_array( $imagick_version ) ? $imagick_version['versionString'] : $imagick_version ),
330
  );
331
 
353
  $gd = false;
354
  }
355
  $info['wp-media']['fields'][] = array(
356
+ 'label' => __( 'GD Version', 'health-check' ),
357
+ 'value' => ( is_array( $gd ) ? $gd['GD Version'] : __( 'GD not available', 'health-check' ) ),
358
  );
359
 
360
  // Get Ghostscript information, if available.
361
  if ( function_exists( 'exec' ) ) {
362
  $gs = exec( 'gs --version' );
363
+ $gs = ( ! empty( $gs ) ? $gs : __( 'Not available', 'health-check' ) );
364
  } else {
365
  $gs = __( 'Unable to determine if Ghostscript is installed', 'health-check' );
366
  }
367
  $info['wp-media']['fields'][] = array(
368
+ 'label' => __( 'Ghostscript Version', 'health-check' ),
369
  'value' => $gs,
370
  );
371
 
421
  }
422
 
423
  if ( function_exists( 'curl_version' ) ) {
424
+ $curl = curl_version();
425
  $info['wp-server']['fields'][] = array(
426
  'label' => __( 'cURL Version', 'health-check' ),
427
+ 'value' => sprintf( '%s %s', $curl['version'], $curl['ssl_version'] ),
428
  );
429
  } else {
430
  $info['wp-server']['fields'][] = array(
443
  'value' => ( extension_loaded( 'imagick' ) ? __( 'Yes', 'health-check' ) : __( 'No', 'health-check' ) ),
444
  );
445
 
446
+ // Check if a .htaccess file exists.
447
+ if ( is_file( ABSPATH . '/.htaccess' ) ) {
448
+ // If the file exists, grab the content of it.
449
+ $htaccess_content = file_get_contents( ABSPATH . '/.htaccess' );
450
+
451
+ // Filter away the core WordPress rules.
452
+ $filtered_htaccess_content = trim( preg_replace( '/\# BEGIN WordPress[\s\S]+?# END WordPress/si', '', $htaccess_content ) );
453
+
454
+ $info['wp-server']['fields'][] = array(
455
+ 'label' => __( 'htaccess rules', 'health-check' ),
456
+ 'value' => ( ! empty( $filtered_htaccess_content ) ? __( 'Custom rules have been added to your htaccess file', 'health-check' ) : __( 'Your htaccess file only contains core WordPress features', 'health-check' ) ),
457
+ );
458
+ }
459
+
460
  // Populate the database debug fields.
461
  if ( is_resource( $wpdb->dbh ) ) {
462
  // Old mysql extension.
471
 
472
  if ( method_exists( $wpdb, 'db_version' ) ) {
473
  if ( $wpdb->use_mysqli ) {
474
+ // phpcs:ignore WordPress.DB.RestrictedFunctions.mysql_mysqli_get_server_info
475
  $server = mysqli_get_server_info( $wpdb->dbh );
476
  } else {
477
+ // phpcs:ignore WordPress.DB.RestrictedFunctions.mysql_mysql_get_server_info
478
  $server = mysql_get_server_info( $wpdb->dbh );
479
  }
480
  } else {
484
  if ( isset( $wpdb->use_mysqli ) && $wpdb->use_mysqli ) {
485
  $client_version = $wpdb->dbh->client_info;
486
  } else {
487
+ // phpcs:ignore WordPress.DB.RestrictedFunctions.mysql_mysql_get_client_info
488
  if ( preg_match( '|[0-9]{1,2}\.[0-9]{1,2}\.[0-9]{1,2}|', mysql_get_client_info(), $matches ) ) {
489
  $client_version = $matches[0];
490
  } else {
553
  }
554
 
555
  // List all available plugins.
556
+ $plugins = get_plugins();
557
+ $plugin_updates = get_plugin_updates();
558
 
559
  foreach ( $plugins as $plugin_path => $plugin ) {
560
  $plugin_part = ( is_plugin_active( $plugin_path ) ) ? 'wp-plugins-active' : 'wp-plugins-inactive';
577
  $plugin_version_string = sprintf( __( 'Version %s', 'health-check' ), $plugin_version );
578
  }
579
 
580
+ if ( array_key_exists( $plugin_path, $plugin_updates ) ) {
581
+ // translators: %s: Latest plugin version number.
582
+ $plugin_update_needed = ' ' . sprintf( __( '( Latest version: %s )', 'health-check' ), $plugin_updates[ $plugin_path ]->update->new_version );
583
+ } else {
584
+ $plugin_update_needed = '';
585
+ }
586
+
587
  $info[ $plugin_part ]['fields'][] = array(
588
  'label' => $plugin['Name'],
589
+ 'value' => $plugin_version_string . $plugin_update_needed,
590
  );
591
  }
592
 
599
  }
600
  }
601
 
602
+ $active_theme = wp_get_theme();
603
+ $theme_updates = get_theme_updates();
604
+
605
+ if ( array_key_exists( $active_theme->stylesheet, $theme_updates ) ) {
606
+ // translators: %s: Latest theme version number.
607
+ $theme_update_needed_active = ' ' . sprintf( __( '( Latest version: %s )', 'health-check' ), $theme_updates[ $active_theme->stylesheet ]->update['new_version'] );
608
+ } else {
609
+ $theme_update_needed_active = '';
610
+ }
611
+
612
  $info['wp-active-theme']['fields'] = array(
613
  array(
614
  'label' => __( 'Name', 'health-check' ),
615
+ // phpcs:ignore WordPress.NamingConventions.ValidVariableName.NotSnakeCaseMemberVar
616
  'value' => $active_theme->Name,
617
  ),
618
  array(
619
  'label' => __( 'Version', 'health-check' ),
620
+ // phpcs:ignore WordPress.NamingConventions.ValidVariableName.NotSnakeCaseMemberVar
621
+ 'value' => $active_theme->Version . $theme_update_needed_active,
622
  ),
623
  array(
624
  'label' => __( 'Author', 'health-check' ),
625
+ // phpcs:ignore WordPress.NamingConventions.ValidVariableName.NotSnakeCaseMemberVar
626
  'value' => wp_kses( $active_theme->Author, array() ),
627
  ),
628
  array(
647
  if ( $active_theme->stylesheet == $theme_slug ) {
648
  continue;
649
  }
650
+ // phpcs:ignore WordPress.NamingConventions.ValidVariableName.NotSnakeCaseMemberVar
651
  $theme_version = $theme->Version;
652
+ // phpcs:ignore WordPress.NamingConventions.ValidVariableName.NotSnakeCaseMemberVar
653
+ $theme_author = $theme->Author;
654
 
655
  $theme_version_string = __( 'No version or author information available', 'health-check' );
656
 
667
  $theme_version_string = sprintf( __( 'Version %s', 'health-check' ), $theme_version );
668
  }
669
 
670
+ if ( array_key_exists( $theme_slug, $theme_updates ) ) {
671
+ // translators: %s: Latest theme version number.
672
+ $theme_update_needed = ' ' . sprintf( __( '( Latest version: %s )', 'health-check' ), $theme_updates[ $theme_slug ]->update['new_version'] );
673
+ } else {
674
+ $theme_update_needed = '';
675
+ }
676
+
677
  $info['wp-themes']['fields'][] = array(
678
+ 'label' => sprintf(
679
+ // translators: %1$s: Theme name. %2$s: Theme slug.
680
+ __( '%1$s (%2$s)', 'health-check' ),
681
+ // phpcs:ignore WordPress.NamingConventions.ValidVariableName.NotSnakeCaseMemberVar
682
+ $theme->Name,
683
+ $theme_slug
684
+ ),
685
+ 'value' => $theme_version_string . $theme_update_needed,
686
  );
687
  }
688
 
694
  );
695
  }
696
 
697
+ $info['wp-install-size']['fields'] = Health_Check_Debug_Data::get_installation_size();
698
+
699
  /**
700
  * Add or modify new debug sections.
701
  *
745
 
746
  return $info;
747
  }
748
+
749
+ public static function get_installation_size() {
750
+ $uploads_dir = wp_upload_dir();
751
+
752
+ $sizes = array(
753
+ 'wp' => array(
754
+ 'path' => ABSPATH,
755
+ 'size' => 0,
756
+ ),
757
+ 'themes' => array(
758
+ 'path' => trailingslashit( get_theme_root() ),
759
+ 'size' => 0,
760
+ ),
761
+ 'plugins' => array(
762
+ 'path' => WP_PLUGIN_DIR,
763
+ 'size' => 0,
764
+ ),
765
+ 'uploads' => array(
766
+ 'path' => $uploads_dir['basedir'],
767
+ 'size' => 0,
768
+ ),
769
+ );
770
+
771
+ $inaccurate = false;
772
+
773
+ foreach ( $sizes as $size => $attributes ) {
774
+ try {
775
+ $sizes[ $size ]['size'] = Health_Check_Debug_Data::get_directory_size( $attributes['path'] );
776
+ } catch ( Exception $e ) {
777
+ $inaccurate = true;
778
+ }
779
+ }
780
+
781
+ $size_db = Health_Check_Debug_Data::get_database_size();
782
+
783
+ $size_total = $sizes['wp']['size'] + $size_db;
784
+
785
+ $result = array(
786
+ array(
787
+ 'label' => __( 'Uploads Directory', 'health-check' ),
788
+ 'value' => size_format( $sizes['uploads']['size'], 2 ),
789
+ ),
790
+ array(
791
+ 'label' => __( 'Themes Directory', 'health-check' ),
792
+ 'value' => size_format( $sizes['themes']['size'], 2 ),
793
+ ),
794
+ array(
795
+ 'label' => __( 'Plugins Directory', 'health-check' ),
796
+ 'value' => size_format( $sizes['plugins']['size'], 2 ),
797
+ ),
798
+ array(
799
+ 'label' => __( 'Database size', 'health-check' ),
800
+ 'value' => size_format( $size_db, 2 ),
801
+ ),
802
+ array(
803
+ 'label' => __( 'Whole WordPress Directory', 'health-check' ),
804
+ 'value' => size_format( $sizes['wp']['size'], 2 ),
805
+ ),
806
+ array(
807
+ 'label' => __( 'Total installation size', 'health-check' ),
808
+ 'value' => sprintf(
809
+ '%s%s',
810
+ size_format( $size_total, 2 ),
811
+ ( false === $inaccurate ? '' : __( '- Some errors, likely caused by invalid permissions, were encountered when determining the size of your installation. This means the values represented may be inaccurate.', 'health-check' ) )
812
+ ),
813
+ ),
814
+ );
815
+
816
+ return $result;
817
+ }
818
+
819
+ public static function get_directory_size( $path ) {
820
+ $size = 0;
821
+
822
+ foreach ( new RecursiveIteratorIterator( new RecursiveDirectoryIterator( $path ) ) as $file ) {
823
+ $size += $file->getSize();
824
+ }
825
+
826
+ return $size;
827
+ }
828
+
829
+ public static function get_database_size() {
830
+ global $wpdb;
831
+ $size = 0;
832
+ $rows = $wpdb->get_results( 'SHOW TABLE STATUS', ARRAY_A );
833
+
834
+ if ( $wpdb->num_rows > 0 ) {
835
+ foreach ( $rows as $row ) {
836
+ $size += $row['Data_length'] + $row['Index_length'];
837
+ }
838
+ }
839
+
840
+ return $size;
841
+ }
842
  }
includes/class-health-check-files-integrity.php CHANGED
@@ -45,7 +45,7 @@ class Health_Check_Files_Integrity {
45
  $wplocale = get_locale();
46
 
47
  // Setup API Call.
48
- $checksumapi = wp_remote_get( 'https://api.wordpress.org/core/checksums/1.0/?version=' . $wpversion . '&locale=' . $wplocale );
49
 
50
  // Encode the API response body.
51
  $checksumapibody = json_decode( wp_remote_retrieve_body( $checksumapi ), true );
@@ -109,7 +109,8 @@ class Health_Check_Files_Integrity {
109
  $output .= '</p></div>';
110
  } else {
111
  $output .= '<div class="notice notice-error inline"><p>';
112
- $output .= __( 'It appears that some files may have been modified.', 'health-check' );
 
113
  $output .= '</p></div><table class="widefat striped file-integrity-table"><thead><tr><th>';
114
  $output .= esc_html__( 'Status', 'health-check' );
115
  $output .= '</th><th>';
@@ -184,4 +185,40 @@ class Health_Check_Files_Integrity {
184
  wp_die();
185
  }
186
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
187
  }
45
  $wplocale = get_locale();
46
 
47
  // Setup API Call.
48
+ $checksumapi = wp_remote_get( 'https://api.wordpress.org/core/checksums/1.0/?version=' . $wpversion . '&locale=' . $wplocale, array( 'timeout' => 10000 ) );
49
 
50
  // Encode the API response body.
51
  $checksumapibody = json_decode( wp_remote_retrieve_body( $checksumapi ), true );
109
  $output .= '</p></div>';
110
  } else {
111
  $output .= '<div class="notice notice-error inline"><p>';
112
+ $output .= esc_html__( 'It appears as if some files may have been modified.', 'health-check' );
113
+ $output .= '<br>' . esc_html__( 'One possible reason for this may be that your installation contains translated versions. An easy way to clear this is to reinstall WordPress. Don\'t worry. This will only affect WordPress\' own files, not your themes, plugins or uploaded media.', 'health-check' );
114
  $output .= '</p></div><table class="widefat striped file-integrity-table"><thead><tr><th>';
115
  $output .= esc_html__( 'Status', 'health-check' );
116
  $output .= '</th><th>';
185
  wp_die();
186
  }
187
 
188
+ /**
189
+ * Add the Files integrity checker to the tools tab.
190
+ *
191
+ * @param array $tabs
192
+ *
193
+ * return array
194
+ */
195
+ static function tools_tab( $tabs ) {
196
+ ob_start();
197
+ ?>
198
+
199
+ <div>
200
+ <p>
201
+ <?php _e( 'The File Integrity checks all the core files with the <code>checksums</code> provided by the WordPress API to see if they are intact. If there are changes you will be able to make a Diff between the files hosted on WordPress.org and your installation to see what has been changed.', 'health-check' ); ?>
202
+ </p>
203
+ <form action="#" id="health-check-file-integrity" method="POST">
204
+ <p>
205
+ <input type="submit" class="button button-primary" value="<?php esc_html_e( 'Check the Files Integrity', 'health-check' ); ?>">
206
+ </p>
207
+ </form>
208
+
209
+ <div id="tools-file-integrity-response-holder">
210
+ <span class="spinner"></span>
211
+ </div>
212
+ </div>
213
+
214
+ <?php
215
+ $tab_content = ob_get_clean();
216
+
217
+ $tabs[] = array(
218
+ 'label' => esc_html__( 'File Integrity', 'health-check' ),
219
+ 'content' => $tab_content,
220
+ );
221
+
222
+ return $tabs;
223
+ }
224
  }
includes/class-health-check-loopback.php CHANGED
@@ -44,14 +44,21 @@ class Health_Check_Loopback {
44
  $url = admin_url();
45
 
46
  if ( ! empty( $disable_plugin_hash ) ) {
47
- $url = add_query_arg( array( 'health-check-disable-plugin-hash' => $disable_plugin_hash ), $url );
 
 
48
  }
49
  if ( ! empty( $allowed_plugins ) ) {
50
  if ( ! is_array( $allowed_plugins ) ) {
51
  $allowed_plugins = (array) $allowed_plugins;
52
  }
53
 
54
- $url = add_query_arg( array( 'health-check-allowed-plugins' => implode( ',', $allowed_plugins ) ), $url );
 
 
 
 
 
55
  }
56
 
57
  $r = wp_remote_get( $url, compact( 'cookies', 'headers', 'timeout' ) );
@@ -94,7 +101,7 @@ class Health_Check_Loopback {
94
  *
95
  * @uses ob_start()
96
  * @uses Health_Check_Troubleshoot::mu_plugin_exists()
97
- * @uses Health_Check_Troubleshoot::get_filesystem_credentials()
98
  * @uses Health_Check_Troubleshoot::setup_must_use_plugin()
99
  * @uses Health_Check_Troubleshoot::maybe_update_must_use_plugin()
100
  * @uses ob_get_clean()
@@ -117,7 +124,7 @@ class Health_Check_Loopback {
117
  $needs_creds = false;
118
 
119
  if ( ! Health_Check_Troubleshoot::mu_plugin_exists() ) {
120
- if ( ! Health_Check_Troubleshoot::get_filesystem_credentials() ) {
121
  $needs_creds = true;
122
  } else {
123
  $check_output = Health_Check_Troubleshoot::setup_must_use_plugin();
@@ -173,7 +180,7 @@ class Health_Check_Loopback {
173
  *
174
  * @uses ob_start()
175
  * @uses Health_Check_Troubleshoot::mu_plugin_exists()
176
- * @uses Health_Check_Troubleshoot::get_filesystem_credentials()
177
  * @uses Health_Check_Troubleshoot::setup_must_use_plugin()
178
  * @uses ob_get_clean()
179
  * @uses wp_send_json_error()
@@ -198,7 +205,7 @@ class Health_Check_Loopback {
198
  $needs_creds = false;
199
 
200
  if ( ! Health_Check_Troubleshoot::mu_plugin_exists() ) {
201
- if ( ! Health_Check_Troubleshoot::get_filesystem_credentials() ) {
202
  $needs_creds = true;
203
  } else {
204
  Health_Check_Troubleshoot::setup_must_use_plugin();
44
  $url = admin_url();
45
 
46
  if ( ! empty( $disable_plugin_hash ) ) {
47
+ $url = add_query_arg( array(
48
+ 'health-check-disable-plugin-hash' => $disable_plugin_hash,
49
+ ), $url );
50
  }
51
  if ( ! empty( $allowed_plugins ) ) {
52
  if ( ! is_array( $allowed_plugins ) ) {
53
  $allowed_plugins = (array) $allowed_plugins;
54
  }
55
 
56
+ $url = add_query_arg(
57
+ array(
58
+ 'health-check-allowed-plugins' => implode( ',', $allowed_plugins ),
59
+ ),
60
+ $url
61
+ );
62
  }
63
 
64
  $r = wp_remote_get( $url, compact( 'cookies', 'headers', 'timeout' ) );
101
  *
102
  * @uses ob_start()
103
  * @uses Health_Check_Troubleshoot::mu_plugin_exists()
104
+ * @uses HealthCheck::get_filesystem_credentials()
105
  * @uses Health_Check_Troubleshoot::setup_must_use_plugin()
106
  * @uses Health_Check_Troubleshoot::maybe_update_must_use_plugin()
107
  * @uses ob_get_clean()
124
  $needs_creds = false;
125
 
126
  if ( ! Health_Check_Troubleshoot::mu_plugin_exists() ) {
127
+ if ( ! HealthCheck::get_filesystem_credentials() ) {
128
  $needs_creds = true;
129
  } else {
130
  $check_output = Health_Check_Troubleshoot::setup_must_use_plugin();
180
  *
181
  * @uses ob_start()
182
  * @uses Health_Check_Troubleshoot::mu_plugin_exists()
183
+ * @uses HealthCheck::get_filesystem_credentials()
184
  * @uses Health_Check_Troubleshoot::setup_must_use_plugin()
185
  * @uses ob_get_clean()
186
  * @uses wp_send_json_error()
205
  $needs_creds = false;
206
 
207
  if ( ! Health_Check_Troubleshoot::mu_plugin_exists() ) {
208
+ if ( ! HealthCheck::get_filesystem_credentials() ) {
209
  $needs_creds = true;
210
  } else {
211
  Health_Check_Troubleshoot::setup_must_use_plugin();
includes/class-health-check-mail-check.php CHANGED
@@ -22,12 +22,29 @@ class Health_Check_Mail_Check {
22
  * @return void
23
  */
24
  static function run_mail_check() {
25
- $output = '';
26
- $sendmail = false;
27
- $email = sanitize_email( $_POST['email'] );
28
- $emailsubject = __( 'This is a test message from Health Check.', 'health-check' );
29
- $emailbody = __( 'This is a test message from Health Check.', 'health-check' );
30
- $sendmail = wp_mail( $email, $emailsubject, $emailbody );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
31
 
32
  if ( ! empty( $sendmail ) ) {
33
  $output .= '<div class="notice notice-success inline"><p>';
@@ -49,4 +66,57 @@ class Health_Check_Mail_Check {
49
 
50
  }
51
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
52
  }
22
  * @return void
23
  */
24
  static function run_mail_check() {
25
+ $output = '';
26
+ $sendmail = false;
27
+ $email = sanitize_email( $_POST['email'] );
28
+ $email_message = sanitize_text_field( $_POST['email_message'] );
29
+ $wp_address = get_bloginfo( 'url' );
30
+ $wp_name = get_bloginfo( 'name' );
31
+ $date = date( 'F j, Y' );
32
+ $time = date( 'g:i a' );
33
+
34
+ // translators: %s: website url.
35
+ $email_subject = sprintf( esc_html__( 'Health Check – Test Message from %s', 'health-check' ), $wp_address );
36
+
37
+ $email_body = sprintf(
38
+ // translators: %1$s: website name. %2$s: website url. %3$s: The date the message was sent. %4$s: The time the message was sent. %5$s: Additional custom message from the administrator.
39
+ __( 'Hi! This test message was sent by the Health Check plugin from %1$s (%2$s) on %3$s at %4$s. Since you’re reading this, it obviously works. Additional message from admin: %5$s', 'health-check' ),
40
+ $wp_name,
41
+ $wp_address,
42
+ $date,
43
+ $time,
44
+ $email_message
45
+ );
46
+
47
+ $sendmail = wp_mail( $email, $email_subject, $email_body );
48
 
49
  if ( ! empty( $sendmail ) ) {
50
  $output .= '<div class="notice notice-success inline"><p>';
66
 
67
  }
68
 
69
+ /**
70
+ * Add the Mail Checker to the tools tab.
71
+ *
72
+ * @param array $tabs
73
+ *
74
+ * return array
75
+ */
76
+ public static function tools_tab( $tabs ) {
77
+ ob_start();
78
+ ?>
79
+
80
+ <div>
81
+ <p>
82
+ <?php _e( 'The Mail Check will invoke the <code>wp_mail()</code> function and check if it succeeds. We will use the E-mail address you have set up, but you can change it below if you like.', 'health-check' ); ?>
83
+ </p>
84
+ <form action="#" id="health-check-mail-check" method="POST">
85
+ <table class="widefat tools-email-table">
86
+ <tr>
87
+ <td>
88
+ <p>
89
+ <?php
90
+ $current_user = wp_get_current_user();
91
+ ?>
92
+ <label for="email"><?php _e( 'E-mail', 'health-check' ); ?></label>
93
+ <input type="text" name="email" id="email" value="<?php echo $current_user->user_email; ?>">
94
+ </p>
95
+ </td>
96
+ <td>
97
+ <p>
98
+ <label for="email_message"><?php _e( 'Additional message', 'health-check' ); ?></label>
99
+ <input type="text" name="email_message" id="email_message" value="">
100
+ </p>
101
+ </td>
102
+ </tr>
103
+ </table>
104
+ <input type="submit" class="button button-primary" value="<?php esc_html_e( 'Send test mail', 'health-check' ); ?>">
105
+ </form>
106
+
107
+ <div id="tools-mail-check-response-holder">
108
+ <span class="spinner"></span>
109
+ </div>
110
+ </div>
111
+
112
+ <?php
113
+ $tab_content = ob_get_clean();
114
+
115
+ $tabs[] = array(
116
+ 'label' => esc_html__( 'Mail Check', 'health-check' ),
117
+ 'content' => $tab_content,
118
+ );
119
+
120
+ return $tabs;
121
+ }
122
  }
includes/class-health-check-troubleshoot.php CHANGED
@@ -11,34 +11,30 @@
11
  class Health_Check_Troubleshoot {
12
 
13
  /**
14
- * Conditionally show a form for providing filesystem credentials when introducing our troubleshooting mode plugin.
15
  *
16
- * @uses wp_nonce_url()
17
- * @uses add_query_arg()
18
- * @uses admin_url()
19
- * @uses request_filesystem_credentials()
20
- * @uses WP_Filesystem
21
  *
22
- * @return bool
 
 
23
  */
24
- static function get_filesystem_credentials() {
25
- $url = wp_nonce_url( add_query_arg(
26
- array(
27
- 'page' => 'health-check',
28
- 'tab' => 'troubleshoot',
29
- ),
30
- admin_url() ) );
31
- $creds = request_filesystem_credentials( $url, '', false, WP_CONTENT_DIR, array( 'health-check-troubleshoot-mode', 'action' ) );
32
- if ( false === $creds ) {
33
- return false;
34
  }
35
 
36
- if ( ! WP_Filesystem( $creds ) ) {
37
- request_filesystem_credentials( $url, '', true, WPMU_PLUGIN_DIR, array( 'health-check-troubleshoot-mode', 'action' ) );
38
- return false;
39
- }
40
 
41
- return true;
 
 
 
 
42
  }
43
 
44
  /**
@@ -49,6 +45,17 @@ class Health_Check_Troubleshoot {
49
  * @return bool
50
  */
51
  static function mu_plugin_exists() {
 
 
 
 
 
 
 
 
 
 
 
52
  return file_exists( WPMU_PLUGIN_DIR . '/health-check-disable-plugins.php' );
53
  }
54
 
@@ -86,7 +93,7 @@ class Health_Check_Troubleshoot {
86
  $user_meta = get_user_meta( get_current_user_id(), 'health-check', true );
87
  if ( empty( $user_meta ) ) {
88
  $user_meta = array(
89
- 'warning'
90
  );
91
  }
92
 
@@ -115,6 +122,7 @@ class Health_Check_Troubleshoot {
115
  static function setup_must_use_plugin( $redirect = true ) {
116
  global $wp_filesystem;
117
 
 
118
  if ( ! is_dir( WPMU_PLUGIN_DIR ) ) {
119
  if ( ! $wp_filesystem->mkdir( WPMU_PLUGIN_DIR ) ) {
120
  HealthCheck::display_notice( esc_html__( 'We were unable to create the mu-plugins directory.', 'health-check' ), 'error' );
@@ -122,7 +130,16 @@ class Health_Check_Troubleshoot {
122
  }
123
  }
124
 
125
- if ( ! $wp_filesystem->copy( trailingslashit( HEALTH_CHECK_PLUGIN_DIRECTORY ) . 'assets/mu-plugin/health-check-disable-plugins.php', trailingslashit( WPMU_PLUGIN_DIR ) . 'health-check-disable-plugins.php' ) ) {
 
 
 
 
 
 
 
 
 
126
  HealthCheck::display_notice( esc_html__( 'We were unable to copy the plugin file required to enable the Troubleshooting Mode.', 'health-check' ), 'error' );
127
  return false;
128
  }
@@ -140,7 +157,7 @@ class Health_Check_Troubleshoot {
140
  * @global $wp_filesystem
141
  *
142
  * @uses Health_Check_Troubleshoot::mu_plugin_exists()
143
- * @uses Health_Check_Troubleshoot::get_filesystem_credentials()
144
  * @uses get_plugin_data()
145
  * @uses trailingslashit()
146
  * @uses version_compare()
@@ -153,12 +170,12 @@ class Health_Check_Troubleshoot {
153
  if ( ! Health_Check_Troubleshoot::mu_plugin_exists() ) {
154
  return false;
155
  }
156
- if ( ! Health_Check_Troubleshoot::get_filesystem_credentials() ) {
157
  return false;
158
  }
159
 
160
- $current = get_plugin_data( trailingslashit( HEALTH_CHECK_PLUGIN_DIRECTORY ) . 'assets/mu-plugin/health-check-disable-plugins.php' );
161
- $active = get_plugin_data( trailingslashit( WPMU_PLUGIN_DIR ) . 'health-check-disable-plugins.php' );
162
 
163
  $current_version = ( isset( $current['Version'] ) ? $current['Version'] : '0.0' );
164
  $active_version = ( isset( $active['Version'] ) ? $active['Version'] : '0.0' );
@@ -166,7 +183,7 @@ class Health_Check_Troubleshoot {
166
  if ( version_compare( $current_version, $active_version, '>' ) ) {
167
  global $wp_filesystem;
168
 
169
- if ( ! $wp_filesystem->copy( trailingslashit( HEALTH_CHECK_PLUGIN_DIRECTORY ) . 'assets/mu-plugin/health-check-disable-plugins.php', trailingslashit( WPMU_PLUGIN_DIR ) . 'health-check-disable-plugins.php', true ) ) {
170
  HealthCheck::display_notice( esc_html__( 'We were unable to replace the plugin file required to enable the Troubleshooting Mode.', 'health-check' ), 'error' );
171
  return false;
172
  }
@@ -208,12 +225,30 @@ class Health_Check_Troubleshoot {
208
  * @uses Health_Check_Troubleshoot::mu_plugin_exists()
209
  * @uses Health_Check_Troubleshoot::maybe_update_must_use_plugin()
210
  * @uses Health_Check_Troubleshoot::session_started()
211
- * @uses Health_Check_Troubleshoot::get_filesystem_credentials()
212
  * @uses Health_Check_Troubleshoot::setup_must_use_plugin()
213
  * @uses esc_html_e()
214
  *
215
  * @return void
216
  */
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
217
  static function show_enable_troubleshoot_form() {
218
  if ( isset( $_POST['health-check-troubleshoot-mode'] ) ) {
219
  if ( Health_Check_Troubleshoot::mu_plugin_exists() ) {
@@ -222,7 +257,7 @@ class Health_Check_Troubleshoot {
222
  }
223
  Health_Check_Troubleshoot::session_started();
224
  } else {
225
- if ( ! Health_Check_Troubleshoot::get_filesystem_credentials() ) {
226
  return;
227
  } else {
228
  Health_Check_Troubleshoot::setup_must_use_plugin();
@@ -230,19 +265,32 @@ class Health_Check_Troubleshoot {
230
  }
231
  }
232
 
233
- ?>
234
  <div class="notice inline">
 
 
 
 
 
 
 
 
 
 
 
235
  <form action="" method="post" class="form" style="text-align: center;">
236
  <input type="hidden" name="health-check-troubleshoot-mode" value="true">
237
-
238
  <p>
239
  <button type="submit" class="button button-primary">
240
  <?php esc_html_e( 'Enable Troubleshooting Mode', 'health-check' ); ?>
241
  </button>
242
  </p>
243
  </form>
 
 
 
244
  </div>
245
 
246
- <?php
247
  }
248
  }
11
  class Health_Check_Troubleshoot {
12
 
13
  /**
14
+ * Initiate the troubleshooting mode by setting meta data and cookies.
15
  *
16
+ * @uses is_array()
17
+ * @uses md5()
18
+ * @uses rand()
19
+ * @uses update_option()
20
+ * @uses setcookie()
21
  *
22
+ * @param array $allowed_plugins An array of plugins that may be active right away.
23
+ *
24
+ * @return void
25
  */
26
+ static function initiate_troubleshooting_mode( $allowed_plugins = array() ) {
27
+ if ( ! is_array( $allowed_plugins ) ) {
28
+ $allowed_plugins = (array) $allowed_plugins;
 
 
 
 
 
 
 
29
  }
30
 
31
+ $loopback_hash = md5( rand() );
 
 
 
32
 
33
+ update_option( 'health-check-allowed-plugins', $allowed_plugins );
34
+
35
+ update_option( 'health-check-disable-plugin-hash', $loopback_hash );
36
+
37
+ setcookie( 'health-check-disable-plugins', $loopback_hash, 0, COOKIEPATH, COOKIE_DOMAIN );
38
  }
39
 
40
  /**
45
  * @return bool
46
  */
47
  static function mu_plugin_exists() {
48
+ return file_exists( WPMU_PLUGIN_DIR . '/health-check-troubleshooting-mode.php' );
49
+ }
50
+
51
+ /**
52
+ * Check if the old Must-Use plugin exists.
53
+ *
54
+ * @uses file_exists()
55
+ *
56
+ * @return bool
57
+ */
58
+ static function old_mu_plugin_exists() {
59
  return file_exists( WPMU_PLUGIN_DIR . '/health-check-disable-plugins.php' );
60
  }
61
 
93
  $user_meta = get_user_meta( get_current_user_id(), 'health-check', true );
94
  if ( empty( $user_meta ) ) {
95
  $user_meta = array(
96
+ 'warning',
97
  );
98
  }
99
 
122
  static function setup_must_use_plugin( $redirect = true ) {
123
  global $wp_filesystem;
124
 
125
+ // Make sure the `mu-plugins` directory exists.
126
  if ( ! is_dir( WPMU_PLUGIN_DIR ) ) {
127
  if ( ! $wp_filesystem->mkdir( WPMU_PLUGIN_DIR ) ) {
128
  HealthCheck::display_notice( esc_html__( 'We were unable to create the mu-plugins directory.', 'health-check' ), 'error' );
130
  }
131
  }
132
 
133
+ // Remove instances of the old plugin, to avoid collisions.
134
+ if ( Health_Check_Troubleshoot::old_mu_plugin_exists() ) {
135
+ if ( ! $wp_filesystem->delete( trailingslashit( WPMU_PLUGIN_DIR ) . 'health-check-disable-plugins.php' ) ) {
136
+ HealthCheck::display_notice( esc_html__( 'We could not remove the old must-use plugin.', 'health-check' ), 'error' );
137
+ return false;
138
+ }
139
+ }
140
+
141
+ // Copy the must-use plugin to the local directory.
142
+ if ( ! $wp_filesystem->copy( trailingslashit( HEALTH_CHECK_PLUGIN_DIRECTORY ) . 'assets/mu-plugin/health-check-troubleshooting-mode.php', trailingslashit( WPMU_PLUGIN_DIR ) . 'health-check-troubleshooting-mode.php' ) ) {
143
  HealthCheck::display_notice( esc_html__( 'We were unable to copy the plugin file required to enable the Troubleshooting Mode.', 'health-check' ), 'error' );
144
  return false;
145
  }
157
  * @global $wp_filesystem
158
  *
159
  * @uses Health_Check_Troubleshoot::mu_plugin_exists()
160
+ * @uses HealthCheck::get_filesystem_credentials()
161
  * @uses get_plugin_data()
162
  * @uses trailingslashit()
163
  * @uses version_compare()
170
  if ( ! Health_Check_Troubleshoot::mu_plugin_exists() ) {
171
  return false;
172
  }
173
+ if ( ! HealthCheck::get_filesystem_credentials() ) {
174
  return false;
175
  }
176
 
177
+ $current = get_plugin_data( trailingslashit( HEALTH_CHECK_PLUGIN_DIRECTORY ) . 'assets/mu-plugin/health-check-troubleshooting-mode.php' );
178
+ $active = get_plugin_data( trailingslashit( WPMU_PLUGIN_DIR ) . 'health-check-troubleshooting-mode.php' );
179
 
180
  $current_version = ( isset( $current['Version'] ) ? $current['Version'] : '0.0' );
181
  $active_version = ( isset( $active['Version'] ) ? $active['Version'] : '0.0' );
183
  if ( version_compare( $current_version, $active_version, '>' ) ) {
184
  global $wp_filesystem;
185
 
186
+ if ( ! $wp_filesystem->copy( trailingslashit( HEALTH_CHECK_PLUGIN_DIRECTORY ) . 'assets/mu-plugin/health-check-troubleshooting-mode.php', trailingslashit( WPMU_PLUGIN_DIR ) . 'health-check-troubleshooting-mode.php', true ) ) {
187
  HealthCheck::display_notice( esc_html__( 'We were unable to replace the plugin file required to enable the Troubleshooting Mode.', 'health-check' ), 'error' );
188
  return false;
189
  }
225
  * @uses Health_Check_Troubleshoot::mu_plugin_exists()
226
  * @uses Health_Check_Troubleshoot::maybe_update_must_use_plugin()
227
  * @uses Health_Check_Troubleshoot::session_started()
228
+ * @uses HealthCheck::get_filesystem_credentials()
229
  * @uses Health_Check_Troubleshoot::setup_must_use_plugin()
230
  * @uses esc_html_e()
231
  *
232
  * @return void
233
  */
234
+
235
+ /**
236
+ * Display the form for enabling troubleshooting mode.
237
+ *
238
+ * @uses printf()
239
+ * @uses esc_html__()
240
+ * @uses Health_Check_Troubleshoot::mu_plugin_exists()
241
+ * @uses Health_Check_Troubleshoot::maybe_update_must_use_plugin()
242
+ * @uses Health_Check_Troubleshoot::session_started()
243
+ * @uses HealthCheck::get_filesystem_credentials()
244
+ * @uses Health_Check_Troubleshoot::setup_must_use_plugin()
245
+ * @uses Health_Check_Troubleshooting_MU::is_troubleshooting()
246
+ * @uses esc_url()
247
+ * @uses add_query_arg()
248
+ * @uses esc_html_e()
249
+ *
250
+ * @return void
251
+ */
252
  static function show_enable_troubleshoot_form() {
253
  if ( isset( $_POST['health-check-troubleshoot-mode'] ) ) {
254
  if ( Health_Check_Troubleshoot::mu_plugin_exists() ) {
257
  }
258
  Health_Check_Troubleshoot::session_started();
259
  } else {
260
+ if ( ! HealthCheck::get_filesystem_credentials() ) {
261
  return;
262
  } else {
263
  Health_Check_Troubleshoot::setup_must_use_plugin();
265
  }
266
  }
267
 
268
+ ?>
269
  <div class="notice inline">
270
+
271
+ <?php if ( class_exists( 'Health_Check_Troubleshooting_MU' ) && Health_Check_Troubleshooting_MU::is_troubleshooting() ) : ?>
272
+
273
+ <p style="text-align: center;">
274
+ <a class="button button-primary" href="<?php echo esc_url( add_query_arg( array( 'health-check-disable-troubleshooting' => true ) ) ); ?>">
275
+ <?php esc_html_e( 'Disable Troubleshooting Mode', 'health-check' ); ?>
276
+ </a>
277
+ </p>
278
+
279
+ <?php else : ?>
280
+
281
  <form action="" method="post" class="form" style="text-align: center;">
282
  <input type="hidden" name="health-check-troubleshoot-mode" value="true">
 
283
  <p>
284
  <button type="submit" class="button button-primary">
285
  <?php esc_html_e( 'Enable Troubleshooting Mode', 'health-check' ); ?>
286
  </button>
287
  </p>
288
  </form>
289
+
290
+ <?php endif; ?>
291
+
292
  </div>
293
 
294
+ <?php
295
  }
296
  }
includes/class-health-check-wp-cron.php CHANGED
@@ -1,100 +1,100 @@
1
- <?php
2
- /**
3
- * Perform tests to see if WP_Cron is operating as it should.
4
- *
5
- * @package Health Check
6
- */
7
-
8
- /**
9
- * Class Health_Check_WP_Cron
10
- */
11
- class Health_Check_WP_Cron {
12
- public $schedules;
13
- public $crons;
14
- public $last_missed_cron = null;
15
-
16
- /**
17
- * Health_Check_WP_Cron constructor.
18
- */
19
- public function __construct() {
20
- $this->init();
21
- }
22
-
23
- /**
24
- * Initiate the class
25
- *
26
- * @uses wp_get_schedules()
27
- * @uses Health_Check_WP_Cron::get_cron_tasks()
28
- *
29
- * @return void
30
- */
31
- public function init() {
32
- $this->schedules = wp_get_schedules();
33
- $this->get_cron_tasks();
34
- }
35
-
36
- /**
37
- * Populate our list of cron events and store them to a class-wide variable.
38
- *
39
- * Derived from `get_cron_events()` in WP Crontrol (https://plugins.svn.wordpress.org/wp-crontrol)
40
- * by John Blackburn.
41
- *
42
- * @uses _get_cron_array()
43
- * @uses WP_Error
44
- *
45
- * @return void
46
- */
47
- private function get_cron_tasks() {
48
- $cron_tasks = _get_cron_array();
49
-
50
- if ( empty( $cron_tasks ) ) {
51
- $this->crons = new WP_Error( 'no_tasks', __( 'No scheduled events exist on this site.', 'health-check' ) );
52
- return;
53
- }
54
-
55
- $this->crons = array();
56
-
57
- foreach ( $cron_tasks as $time => $cron ) {
58
- foreach ( $cron as $hook => $dings ) {
59
- foreach ( $dings as $sig => $data ) {
60
-
61
- $this->crons[ "$hook-$sig-$time" ] = (object) array(
62
- 'hook' => $hook,
63
- 'time' => $time,
64
- 'sig' => $sig,
65
- 'args' => $data['args'],
66
- 'schedule' => $data['schedule'],
67
- 'interval' => isset( $data['interval'] ) ? $data['interval'] : null,
68
- );
69
-
70
- }
71
- }
72
- }
73
- }
74
-
75
- /**
76
- * Check if any scheduled tasks have been missed.
77
- *
78
- * Returns a boolean value of `true` if a scheduled task has been missed and ends processing.
79
- * If the list of crons is an instance of WP_Error, return the instance instead of a boolean value.
80
- *
81
- * @uses is_wp_error()
82
- * @uses time()
83
- *
84
- * @return bool|WP_Error
85
- */
86
- public function has_missed_cron() {
87
- if ( is_wp_error( $this->crons ) ) {
88
- return $this->crons;
89
- }
90
-
91
- foreach ( $this->crons as $id => $cron ) {
92
- if ( ( $cron->time - time() ) < 0 ) {
93
- $this->last_missed_cron = $cron->hook;
94
- return true;
95
- }
96
- }
97
-
98
- return false;
99
- }
100
- }
1
+ <?php
2
+ /**
3
+ * Perform tests to see if WP_Cron is operating as it should.
4
+ *
5
+ * @package Health Check
6
+ */
7
+
8
+ /**
9
+ * Class Health_Check_WP_Cron
10
+ */
11
+ class Health_Check_WP_Cron {
12
+ public $schedules;
13
+ public $crons;
14
+ public $last_missed_cron = null;
15
+
16
+ /**
17
+ * Health_Check_WP_Cron constructor.
18
+ */
19
+ public function __construct() {
20
+ $this->init();
21
+ }
22
+
23
+ /**
24
+ * Initiate the class
25
+ *
26
+ * @uses wp_get_schedules()
27
+ * @uses Health_Check_WP_Cron::get_cron_tasks()
28
+ *
29
+ * @return void
30
+ */
31
+ public function init() {
32
+ $this->schedules = wp_get_schedules();
33
+ $this->get_cron_tasks();
34
+ }
35
+
36
+ /**
37
+ * Populate our list of cron events and store them to a class-wide variable.
38
+ *
39
+ * Derived from `get_cron_events()` in WP Crontrol (https://plugins.svn.wordpress.org/wp-crontrol)
40
+ * by John Blackburn.
41
+ *
42
+ * @uses _get_cron_array()
43
+ * @uses WP_Error
44
+ *
45
+ * @return void
46
+ */
47
+ private function get_cron_tasks() {
48
+ $cron_tasks = _get_cron_array();
49
+
50
+ if ( empty( $cron_tasks ) ) {
51
+ $this->crons = new WP_Error( 'no_tasks', __( 'No scheduled events exist on this site.', 'health-check' ) );
52
+ return;
53
+ }
54
+
55
+ $this->crons = array();
56
+
57
+ foreach ( $cron_tasks as $time => $cron ) {
58
+ foreach ( $cron as $hook => $dings ) {
59
+ foreach ( $dings as $sig => $data ) {
60
+
61
+ $this->crons[ "$hook-$sig-$time" ] = (object) array(
62
+ 'hook' => $hook,
63
+ 'time' => $time,
64
+ 'sig' => $sig,
65
+ 'args' => $data['args'],
66
+ 'schedule' => $data['schedule'],
67
+ 'interval' => isset( $data['interval'] ) ? $data['interval'] : null,
68
+ );
69
+
70
+ }
71
+ }
72
+ }
73
+ }
74
+
75
+ /**
76
+ * Check if any scheduled tasks have been missed.
77
+ *
78
+ * Returns a boolean value of `true` if a scheduled task has been missed and ends processing.
79
+ * If the list of crons is an instance of WP_Error, return the instance instead of a boolean value.
80
+ *
81
+ * @uses is_wp_error()
82
+ * @uses time()
83
+ *
84
+ * @return bool|WP_Error
85
+ */
86
+ public function has_missed_cron() {
87
+ if ( is_wp_error( $this->crons ) ) {
88
+ return $this->crons;
89
+ }
90
+
91
+ foreach ( $this->crons as $id => $cron ) {
92
+ if ( ( $cron->time - time() ) < 0 ) {
93
+ $this->last_missed_cron = $cron->hook;
94
+ return true;
95
+ }
96
+ }
97
+
98
+ return false;
99
+ }
100
+ }
includes/class-healthcheck.php ADDED
@@ -0,0 +1,454 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Primary class file for the Health Check plugin.
4
+ *
5
+ * @package Health Check
6
+ */
7
+
8
+ /**
9
+ * Class HealthCheck
10
+ */
11
+ class HealthCheck {
12
+
13
+ /**
14
+ * Notices to show at the head of the admin screen.
15
+ *
16
+ * @access public
17
+ *
18
+ * @var array
19
+ */
20
+ public $admin_notices = array();
21
+
22
+ /**
23
+ * HealthCheck constructor.
24
+ *
25
+ * @uses HealthCheck::init()
26
+ *
27
+ * @return void
28
+ */
29
+ public function __construct() {
30
+ $this->init();
31
+ }
32
+
33
+ /**
34
+ * Plugin initiation.
35
+ *
36
+ * A helper function, called by `HealthCheck::__construct()` to initiate actions, hooks and other features needed.
37
+ *
38
+ * @uses add_action()
39
+ * @uses add_filter()
40
+ *
41
+ * @return void
42
+ */
43
+ public function init() {
44
+ add_action( 'plugins_loaded', array( $this, 'load_i18n' ) );
45
+
46
+ add_action( 'admin_menu', array( $this, 'action_admin_menu' ) );
47
+
48
+ add_filter( 'plugin_row_meta', array( $this, 'settings_link' ), 10, 2 );
49
+
50
+ add_filter( 'plugin_action_links', array( $this, 'troubeshoot_plugin_action' ), 20, 4 );
51
+
52
+ add_action( 'admin_footer', array( $this, 'show_backup_warning' ) );
53
+
54
+ add_action( 'admin_notices', array( $this, 'admin_notices' ) );
55
+
56
+ add_action( 'admin_enqueue_scripts', array( $this, 'enqueues' ) );
57
+
58
+ add_action( 'init', array( $this, 'start_troubleshoot_mode' ) );
59
+ add_action( 'load-plugins.php', array( $this, 'start_troubleshoot_single_plugin_mode' ) );
60
+
61
+ add_action( 'wp_ajax_health-check-loopback-no-plugins', array( 'Health_Check_Loopback', 'loopback_no_plugins' ) );
62
+ add_action( 'wp_ajax_health-check-loopback-individual-plugins', array( 'Health_Check_Loopback', 'loopback_test_individual_plugins' ) );
63
+ add_action( 'wp_ajax_health-check-files-integrity-check', array( 'Health_Check_Files_Integrity', 'run_files_integrity_check' ) );
64
+ add_action( 'wp_ajax_health-check-view-file-diff', array( 'Health_Check_Files_Integrity', 'view_file_diff' ) );
65
+ add_action( 'wp_ajax_health-check-mail-check', array( 'Health_Check_Mail_Check', 'run_mail_check' ) );
66
+ add_action( 'wp_ajax_health-check-confirm-warning', array( 'Health_Check_Troubleshoot', 'confirm_warning' ) );
67
+
68
+ add_filter( 'health_check_tools_tab', array( 'Health_Check_Files_Integrity', 'tools_tab' ) );
69
+ add_filter( 'health_check_tools_tab', array( 'Health_Check_Mail_Check', 'tools_tab' ) );
70
+ }
71
+
72
+ /**
73
+ * Show a warning modal about keeping backups.
74
+ *
75
+ * @uses Health_Check_Troubleshoot::has_seen_warning()
76
+ *
77
+ * @return void
78
+ */
79
+ public function show_backup_warning() {
80
+ if ( Health_Check_Troubleshoot::has_seen_warning() ) {
81
+ return;
82
+ }
83
+
84
+ include_once( HEALTH_CHECK_PLUGIN_DIRECTORY . '/modals/backup-warning.php' );
85
+ }
86
+
87
+ /**
88
+ * Initiate troubleshooting mode.
89
+ *
90
+ * Catch when the troubleshooting form has been submitted, and appropriately set required options and cookies.
91
+ *
92
+ * @uses current_user_can()
93
+ * @uses Health_Check_Troubleshoot::initiate_troubleshooting_mode()
94
+ *
95
+ * @return void
96
+ */
97
+ public function start_troubleshoot_mode() {
98
+ if ( ! isset( $_POST['health-check-troubleshoot-mode'] ) || ! current_user_can( 'manage_options' ) ) {
99
+ return;
100
+ }
101
+
102
+ Health_Check_Troubleshoot::initiate_troubleshooting_mode();
103
+ }
104
+
105
+ /**
106
+ * Initiate troubleshooting mode for a specific plugin.
107
+ *
108
+ * Catch when the troubleshooting link on an individual plugin has been clicked, and appropriately sets the
109
+ * required options and cookies.
110
+ *
111
+ * @uses current_user_can()
112
+ * @uses ob_start()
113
+ * @uses Health_Check_Troubleshoot::mu_plugin_exists()
114
+ * @uses HealthCheck::get_filesystem_credentials()
115
+ * @uses Health_Check_Troubleshoot::setup_must_use_plugin()
116
+ * @uses Health_Check_Troubleshoot::maybe_update_must_use_plugin()
117
+ * @uses ob_get_clean()
118
+ * @uses Health_Check_Troubleshoot::initiate_troubleshooting_mode()
119
+ * @uses wp_redirect()
120
+ * @uses admin_url()
121
+ *
122
+ * @return void
123
+ */
124
+ public function start_troubleshoot_single_plugin_mode() {
125
+ if ( ! isset( $_GET['health-check-troubleshoot-plugin'] ) || ! current_user_can( 'manage_options' ) ) {
126
+ return;
127
+ }
128
+
129
+ ob_start();
130
+
131
+ $needs_credentials = false;
132
+
133
+ if ( ! Health_Check_Troubleshoot::mu_plugin_exists() ) {
134
+ if ( ! HealthCheck::get_filesystem_credentials() ) {
135
+ $needs_credentials = true;
136
+ } else {
137
+ $check_output = Health_Check_Troubleshoot::setup_must_use_plugin( false );
138
+ if ( false === $check_output ) {
139
+ $needs_credentials = true;
140
+ }
141
+ }
142
+ } else {
143
+ if ( ! Health_Check_Troubleshoot::maybe_update_must_use_plugin() ) {
144
+ $needs_credentials = true;
145
+ }
146
+ }
147
+
148
+ $result = ob_get_clean();
149
+
150
+ if ( $needs_credentials ) {
151
+ $this->admin_notices[] = (object) array(
152
+ 'message' => $result,
153
+ 'type' => 'warning',
154
+ );
155
+ return;
156
+ }
157
+
158
+ Health_Check_Troubleshoot::initiate_troubleshooting_mode( array(
159
+ $_GET['health-check-troubleshoot-plugin'] => $_GET['health-check-troubleshoot-plugin'],
160
+ ) );
161
+
162
+ wp_redirect( admin_url( 'plugins.php' ) );
163
+ }
164
+
165
+ /**
166
+ * Load translations.
167
+ *
168
+ * Loads the textdomain needed to get translations for our plugin.
169
+ *
170
+ * @uses load_plugin_textdomain()
171
+ * @uses basename()
172
+ * @uses dirname()
173
+ *
174
+ * @return void
175
+ */
176
+ public function load_i18n() {
177
+ load_plugin_textdomain( 'health-check', false, basename( dirname( __FILE__ ) ) . '/languages/' );
178
+ }
179
+
180
+ /**
181
+ * Enqueue assets.
182
+ *
183
+ * Conditionally enqueue our CSS and JavaScript when viewing plugin related pages in wp-admin.
184
+ *
185
+ * @uses wp_enqueue_style()
186
+ * @uses plugins_url()
187
+ * @uses wp_enqueue_script()
188
+ * @uses wp_localize_script()
189
+ * @uses esc_html__()
190
+ *
191
+ * @return void
192
+ */
193
+ public function enqueues() {
194
+ // Don't enqueue anything unless we're on the health check page
195
+ if ( ! isset( $_GET['page'] ) || 'health-check' !== $_GET['page'] ) {
196
+
197
+ /*
198
+ * Special consideration, if warnings are not dismissed we need to display
199
+ * our modal, and thus require our styles, in other locations, before bailing.
200
+ */
201
+ if ( ! Health_Check_Troubleshoot::has_seen_warning() ) {
202
+ wp_enqueue_style( 'health-check', HEALTH_CHECK_PLUGIN_URL . '/assets/css/health-check.css', array(), HEALTH_CHECK_PLUGIN_VERSION );
203
+ }
204
+ return;
205
+ }
206
+
207
+ wp_enqueue_style( 'health-check', HEALTH_CHECK_PLUGIN_URL . '/assets/css/health-check.css', array(), HEALTH_CHECK_PLUGIN_VERSION );
208
+
209
+ wp_enqueue_script( 'health-check', HEALTH_CHECK_PLUGIN_URL . '/assets/javascript/health-check.js', array( 'jquery' ), HEALTH_CHECK_PLUGIN_VERSION, true );
210
+
211
+ wp_localize_script( 'health-check', 'HealthCheck', array(
212
+ 'string' => array(
213
+ 'please_wait' => esc_html__( 'Please wait...', 'health-check' ),
214
+ 'copied' => esc_html__( 'Copied', 'health-check' ),
215
+ ),
216
+ 'warning' => array(
217
+ 'seen_backup' => Health_Check_Troubleshoot::has_seen_warning(),
218
+ ),
219
+ ) );
220
+ }
221
+
222
+ /**
223
+ * Add item to the admin menu.
224
+ *
225
+ * @uses add_dashboard_page()
226
+ * @uses __()
227
+ *
228
+ * @return void
229
+ */
230
+ public function action_admin_menu() {
231
+ add_dashboard_page( _x( 'Health Check', 'Menu, Section and Page Title', 'health-check' ), _x( 'Health Check', 'Menu, Section and Page Title', 'health-check' ), 'manage_options', 'health-check', array( $this, 'dashboard_page' ) );
232
+ }
233
+
234
+ /**
235
+ * Add a quick-access link under our plugin name on the plugins-list.
236
+ *
237
+ * @uses plugin_basename()
238
+ * @uses sprintf()
239
+ * @uses menu_page_url()
240
+ *
241
+ * @param array $meta An array containing meta links.
242
+ * @param string $name The plugin slug that these metas relate to.
243
+ *
244
+ * @return array
245
+ */
246
+ public function settings_link( $meta, $name ) {
247
+ if ( plugin_basename( __FILE__ ) === $name ) {
248
+ $meta[] = sprintf( '<a href="%s">' . _x( 'Health Check', 'Menu, Section and Page Title', 'health-check' ) . '</a>', menu_page_url( 'health-check', false ) );
249
+ }
250
+
251
+ return $meta;
252
+ }
253
+
254
+ /**
255
+ * Add a troubleshooting action link to plugins.
256
+ *
257
+ * @param $actions
258
+ * @param $plugin_file
259
+ * @param $plugin_data
260
+ * @param $context
261
+ *
262
+ * @return array
263
+ */
264
+ public function troubeshoot_plugin_action( $actions, $plugin_file, $plugin_data, $context ) {
265
+ // Don't add anything if this is a Must-Use plugin, we can't touch those.
266
+ if ( 'mustuse' === $context ) {
267
+ return $actions;
268
+ }
269
+
270
+ // Only add troubleshooting actions to active plugins.
271
+ if ( ! is_plugin_active( $plugin_file ) ) {
272
+ return $actions;
273
+ }
274
+
275
+ // Set a slug if the plugin lives in the plugins directory root.
276
+ if ( ! stristr( $plugin_file, '/' ) ) {
277
+ $plugin_data['slug'] = $plugin_file;
278
+ }
279
+
280
+ $actions['troubleshoot'] = sprintf(
281
+ '<a href="%s">%s</a>',
282
+ esc_url( add_query_arg( array(
283
+ 'health-check-troubleshoot-plugin' => ( isset( $plugin_data['slug'] ) ? $plugin_data['slug'] : sanitize_title( $plugin_data['Name'] ) ),
284
+ ), admin_url( 'plugins.php' ) ) ),
285
+ esc_html__( 'Troubleshoot', 'health-check' )
286
+ );
287
+
288
+ return $actions;
289
+ }
290
+
291
+ /**
292
+ * Render our admin page.
293
+ *
294
+ * @uses _e()
295
+ * @uses esc_html__()
296
+ * @uses printf()
297
+ * @uses sprintf()
298
+ * @uses menu_page_url()
299
+ * @uses dirname()
300
+ *
301
+ * @return void
302
+ */
303
+ public function dashboard_page() {
304
+ ?>
305
+ <div class="wrap">
306
+ <h1>
307
+ <?php _ex( 'Health Check', 'Menu, Section and Page Title', 'health-check' ); ?>
308
+ </h1>
309
+
310
+ <?php
311
+ $tabs = array(
312
+ 'health-check' => esc_html_x( 'Health Check', 'Menu, Section and Page Title', 'health-check' ),
313
+ 'debug' => esc_html__( 'Debug Information', 'health-check' ),
314
+ 'troubleshoot' => esc_html__( 'Troubleshooting', 'health-check' ),
315
+ 'phpinfo' => esc_html__( 'PHP Information', 'health-check' ),
316
+ 'tools' => esc_html__( 'Tools', 'health-check' ),
317
+ );
318
+
319
+ $current_tab = ( isset( $_GET['tab'] ) ? $_GET['tab'] : 'health-check' );
320
+ ?>
321
+
322
+ <h2 class="nav-tab-wrapper wp-clearfix">
323
+ <?php
324
+ foreach ( $tabs as $tab => $label ) {
325
+ printf(
326
+ '<a href="%s" class="nav-tab %s">%s</a>',
327
+ sprintf(
328
+ '%s&tab=%s',
329
+ menu_page_url( 'health-check', false ),
330
+ $tab
331
+ ),
332
+ ( $current_tab === $tab ? 'nav-tab-active' : '' ),
333
+ $label
334
+ );
335
+ }
336
+ ?>
337
+ </h2>
338
+
339
+ <?php
340
+ switch ( $current_tab ) {
341
+ case 'debug':
342
+ include_once( HEALTH_CHECK_PLUGIN_DIRECTORY . '/pages/debug-data.php' );
343
+ break;
344
+ case 'phpinfo':
345
+ include_once( HEALTH_CHECK_PLUGIN_DIRECTORY . '/pages/phpinfo.php' );
346
+ break;
347
+ case 'troubleshoot':
348
+ include_once( HEALTH_CHECK_PLUGIN_DIRECTORY . '/pages/troubleshoot.php' );
349
+ break;
350
+ case 'tools':
351
+ include_once( HEALTH_CHECK_PLUGIN_DIRECTORY . '/pages/tools.php' );
352
+ break;
353
+ case 'health-check':
354
+ default:
355
+ include_once( HEALTH_CHECK_PLUGIN_DIRECTORY . '/pages/health-check.php' );
356
+ }
357
+ ?>
358
+ </div>
359
+ <?php
360
+ }
361
+
362
+ /**
363
+ * Display styled admin notices.
364
+ *
365
+ * @uses printf()
366
+ *
367
+ * @param string $message A sanitized string containing our notice message.
368
+ * @param string $status A string representing the status type.
369
+ *
370
+ * @return void
371
+ */
372
+ static function display_notice( $message, $status = 'success' ) {
373
+ printf(
374
+ '<div class="notice notice-%s inline">',
375
+ $status
376
+ );
377
+
378
+ printf(
379
+ '<p>%s</p>',
380
+ $message
381
+ );
382
+
383
+ echo '</div>';
384
+ }
385
+
386
+ /**
387
+ * Display admin notices if we have any queued.
388
+ *
389
+ * @return void
390
+ */
391
+ public function admin_notices() {
392
+ foreach ( $this->admin_notices as $admin_notice ) {
393
+ printf(
394
+ '<div class="notice notice-%s"><p>%s</p></div>',
395
+ esc_attr( $admin_notice->type ),
396
+ $admin_notice->message
397
+ );
398
+ }
399
+ }
400
+
401
+
402
+ /**
403
+ * Conditionally show a form for providing filesystem credentials when introducing our troubleshooting mode plugin.
404
+ *
405
+ * @uses wp_nonce_url()
406
+ * @uses add_query_arg()
407
+ * @uses admin_url()
408
+ * @uses request_filesystem_credentials()
409
+ * @uses WP_Filesystem
410
+ *
411
+ * @param array $args Any WP_Filesystem arguments you wish to pass.
412
+ *
413
+ * @return bool
414
+ */
415
+ static function get_filesystem_credentials( $args = array() ) {
416
+ $args = array_merge(
417
+ array(
418
+ 'page' => 'health-check',
419
+ 'tab' => 'troubleshoot',
420
+ ),
421
+ $args
422
+ );
423
+
424
+ $url = wp_nonce_url( add_query_arg( $args, admin_url() ) );
425
+ $creds = request_filesystem_credentials( $url, '', false, WP_CONTENT_DIR, array( 'health-check-troubleshoot-mode', 'action' ) );
426
+ if ( false === $creds ) {
427
+ return false;
428
+ }
429
+
430
+ if ( ! WP_Filesystem( $creds ) ) {
431
+ request_filesystem_credentials( $url, '', true, WPMU_PLUGIN_DIR, array( 'health-check-troubleshoot-mode', 'action' ) );
432
+ return false;
433
+ }
434
+
435
+ return true;
436
+ }
437
+
438
+ /**
439
+ * Perform a check to see is JSON is enabled.
440
+ *
441
+ * @uses extension_loaded()
442
+ * @uses function_Exists()
443
+ * @uses son_encode()
444
+ *
445
+ * @return bool
446
+ */
447
+ static function json_check() {
448
+ $extension_loaded = extension_loaded( 'json' );
449
+ $functions_exist = function_exists( 'json_encode' ) && function_exists( 'json_decode' );
450
+ $functions_work = function_exists( 'json_encode' ) && ( '' != json_encode( 'my test string' ) );
451
+
452
+ return $extension_loaded && $functions_exist && $functions_work;
453
+ }
454
+ }
modals/backup-warning.php CHANGED
@@ -1,45 +1,45 @@
1
- <div class="health-check-modal" id="health-check-backup-warning" data-modal-action="" data-parent-field="">
2
- <div class="modal-content">
3
- <h2>
4
- <?php esc_html_e( 'Remember to keep backups', 'health-check' ); ?>
5
- </h2>
6
-
7
- <p>
8
- <?php _e( 'Because of how Troubleshooting Mode functions, unforeseen conflicts with other plugins or themes may in rare cases occur, leading to unexpected behaviors.', 'health-check' ); ?>
9
- </p>
10
-
11
- <p>
12
- <?php _e( 'We therefore strongly recommend <a href="https://codex.wordpress.org/WordPress_Backups">making a backup of your site</a> before you enter troubleshooting mode.', 'health-check' ); ?>
13
- </p>
14
-
15
- <p>
16
- <?php _e( 'Additionally, since we really want to make this plugin as safe as possible, if you should have any problems with the troubleshooting mode, please create a new topic in the <a href="https://wordpress.org/support/plugin/health-check">plugins support forum</a> with details about what theme and what plugins you’re using and the steps needed to reproduce the problem. This will help us to analyze and fix such problems.', 'health-check' ); ?>
17
- </p>
18
-
19
- <p>
20
- <button class="button button-primary" id="health-check-accept-backup-warning"><?php esc_html_e( 'I understand', 'health-check' ); ?></button>
21
- </p>
22
- </div>
23
- </div>
24
-
25
- <script type="text/javascript">
26
- jQuery( document ).ready(function( $ ) {
27
- if ( 'undefined' === typeof( health_check ) || false === health_check.warning.seen_backup ) {
28
- $( "#health-check-backup-warning" ).show();
29
- }
30
-
31
- $( "#health-check-accept-backup-warning" ).click(function( e ) {
32
- $( "#health-check-backup-warning" ).hide();
33
-
34
- var data = {
35
- action: 'health-check-confirm-warning',
36
- warning: 'backup'
37
- };
38
-
39
- $.post(
40
- ajaxurl,
41
- data
42
- );
43
- });
44
- });
45
- </script>
1
+ <div class="health-check-modal" id="health-check-backup-warning" data-modal-action="" data-parent-field="">
2
+ <div class="modal-content">
3
+ <h2>
4
+ <?php esc_html_e( 'Remember to keep backups', 'health-check' ); ?>
5
+ </h2>
6
+
7
+ <p>
8
+ <?php _e( 'Because of how Troubleshooting Mode functions, unforeseen conflicts with other plugins or themes may in rare cases occur, leading to unexpected behaviors.', 'health-check' ); ?>
9
+ </p>
10
+
11
+ <p>
12
+ <?php _e( 'We therefore strongly recommend <a href="https://codex.wordpress.org/WordPress_Backups">making a backup of your site</a> before you enable troubleshooting mode.', 'health-check' ); ?>
13
+ </p>
14
+
15
+ <p>
16
+ <?php _e( 'Additionally, since we really want to make this plugin as safe as possible, if you should have any problems with the troubleshooting mode, please create a new topic in the <a href="https://wordpress.org/support/plugin/health-check">plugins support forum</a> with details about what theme and what plugins you’re using and the steps needed to reproduce the problem. This will help us to analyze and fix such problems.', 'health-check' ); ?>
17
+ </p>
18
+
19
+ <p>
20
+ <button class="button button-primary" id="health-check-accept-backup-warning"><?php esc_html_e( 'I understand', 'health-check' ); ?></button>
21
+ </p>
22
+ </div>
23
+ </div>
24
+
25
+ <script type="text/javascript">
26
+ jQuery( document ).ready(function( $ ) {
27
+ if ( 'undefined' === typeof( health_check ) || false === health_check.warning.seen_backup ) {
28
+ $( "#health-check-backup-warning" ).show();
29
+ }
30
+
31
+ $( "#health-check-accept-backup-warning" ).click(function( e ) {
32
+ $( "#health-check-backup-warning" ).hide();
33
+
34
+ var data = {
35
+ action: 'health-check-confirm-warning',
36
+ warning: 'backup'
37
+ };
38
+
39
+ $.post(
40
+ ajaxurl,
41
+ data
42
+ );
43
+ });
44
+ });
45
+ </script>
pages/debug-data.php CHANGED
@@ -10,6 +10,8 @@ if ( ! defined( 'ABSPATH' ) ) {
10
  die( 'We\'re sorry, but you can not directly access this file.' );
11
  }
12
 
 
 
13
  $info = Health_Check_Debug_Data::debug_data();
14
  ?>
15
 
@@ -139,7 +141,7 @@ $info = Health_Check_Debug_Data::debug_data();
139
  </div>
140
 
141
  <h2 id="system-information-table-of-contents">
142
- <?php esc_html_e( 'Table of contents', 'health-check' ); ?>
143
  </h2>
144
  <div>
145
  <?php
@@ -191,7 +193,6 @@ foreach ( $info as $section => $details ) {
191
  <tbody>
192
  <?php
193
  foreach ( $details['fields'] as $field ) {
194
- $values = esc_html( $field['value'] );
195
  if ( is_array( $field['value'] ) ) {
196
  $values = '';
197
  foreach ( $field['value'] as $name => $value ) {
@@ -201,6 +202,8 @@ foreach ( $info as $section => $details ) {
201
  esc_html( $value )
202
  );
203
  }
 
 
204
  }
205
 
206
  printf(
10
  die( 'We\'re sorry, but you can not directly access this file.' );
11
  }
12
 
13
+ Health_Check_Debug_Data::check_for_updates();
14
+
15
  $info = Health_Check_Debug_Data::debug_data();
16
  ?>
17
 
141
  </div>
142
 
143
  <h2 id="system-information-table-of-contents">
144
+ <?php esc_html_e( 'Table Of Contents', 'health-check' ); ?>
145
  </h2>
146
  <div>
147
  <?php
193
  <tbody>
194
  <?php
195
  foreach ( $details['fields'] as $field ) {
 
196
  if ( is_array( $field['value'] ) ) {
197
  $values = '';
198
  foreach ( $field['value'] as $name => $value ) {
202
  esc_html( $value )
203
  );
204
  }
205
+ } else {
206
+ $values = esc_html( $field['value'] );
207
  }
208
 
209
  printf(
pages/health-check.php CHANGED
@@ -20,8 +20,10 @@ $mariadb = false;
20
  $mysql_server_version = null;
21
  if ( method_exists( $wpdb, 'db_version' ) ) {
22
  if ( $wpdb->use_mysqli ) {
 
23
  $mysql_server_type = mysqli_get_server_info( $wpdb->dbh );
24
  } else {
 
25
  $mysql_server_type = mysql_get_server_info( $wpdb->dbh );
26
  }
27
 
@@ -57,22 +59,22 @@ $db_dropin = file_exists( WP_CONTENT_DIR . '/db.php' );
57
  $status = 'good';
58
  $notice = array();
59
 
60
- if ( ! $php_rec_version_check ) {
61
- $status = 'warning';
62
  $notice[] = sprintf(
63
  '<a href="%s">%s</a>',
64
  esc_url(
65
  _x( 'https://wordpress.org/support/upgrade-php/', 'The link to the Update PHP page, which may be localized.', 'health-check' )
66
  ),
67
  sprintf(
68
- // translators: %s: Recommended PHP version
69
- esc_html__( 'For performance and security reasons, we strongly recommend running PHP version %s or higher.', 'health-check' ),
70
- HEALTH_CHECK_PHP_REC_VERSION
 
 
71
  )
72
  );
73
- }
74
-
75
- if ( ! $php_supported_version_check ) {
76
  $status = 'warning';
77
  $notice[] = sprintf(
78
  '<a href="%s">%s</a>',
@@ -86,21 +88,17 @@ $db_dropin = file_exists( WP_CONTENT_DIR . '/db.php' );
86
  HEALTH_CHECK_PHP_REC_VERSION
87
  )
88
  );
89
- }
90
-
91
- if ( ! $php_min_version_check ) {
92
- $status = 'error';
93
  $notice[] = sprintf(
94
  '<a href="%s">%s</a>',
95
  esc_url(
96
  _x( 'https://wordpress.org/support/upgrade-php/', 'The link to the Update PHP page, which may be localized.', 'health-check' )
97
  ),
98
  sprintf(
99
- // translators: %1$s: Current PHP version. %2$s: Recommended PHP version. %3$s: Minimum PHP version.
100
- esc_html__( 'Your version of PHP, %1$s, is very outdated and no longer receiving security updates and is not supported by WordPress. You should contact your host for an upgrade, WordPress recommends using PHP version %2$s, but will work with version %3$s or newer.', 'health-check' ),
101
- PHP_VERSION,
102
- HEALTH_CHECK_PHP_REC_VERSION,
103
- HEALTH_CHECK_PHP_MIN_VERSION
104
  )
105
  );
106
  }
@@ -156,7 +154,16 @@ $db_dropin = file_exists( WP_CONTENT_DIR . '/db.php' );
156
 
157
  if ( $db_dropin ) {
158
  // translators: %s: The database engine in use (MySQL or MariaDB).
159
- $notice[] = wp_kses( sprintf( __( 'You are using a <code>wp-content/db.php</code> drop-in which might mean that a %s database is not being used.', 'health-check' ), ( $mariadb ? 'MariaDB' : 'MySQL' ) ), array( 'code' => true ) );
 
 
 
 
 
 
 
 
 
160
  }
161
 
162
  printf(
@@ -233,8 +240,10 @@ $db_dropin = file_exists( WP_CONTENT_DIR . '/db.php' );
233
  }
234
 
235
  if ( $wpdb->use_mysqli ) {
 
236
  $mysql_client_version = mysqli_get_client_info();
237
  } else {
 
238
  $mysql_client_version = mysql_get_client_info();
239
  }
240
 
@@ -276,7 +285,9 @@ $db_dropin = file_exists( WP_CONTENT_DIR . '/db.php' );
276
  <td><?php esc_html_e( 'Communication with WordPress.org', 'health-check' ); ?></td>
277
  <td>
278
  <?php
279
- $wp_dotorg = wp_remote_get( 'https://wordpress.org', array( 'timeout' => 10 ) );
 
 
280
  if ( ! is_wp_error( $wp_dotorg ) ) {
281
  printf(
282
  '<span class="good"></span> %s',
@@ -337,54 +348,6 @@ $db_dropin = file_exists( WP_CONTENT_DIR . '/db.php' );
337
  </td>
338
  </tr>
339
 
340
- <?php if ( function_exists( 'curl_version' ) ) : ?>
341
- <tr>
342
- <td>
343
- <?php
344
- // translators: 'cURL' being a code library for communicating with other services.
345
- esc_html_e( 'cURL version', 'health-check' );
346
- ?>
347
- </td>
348
- <td>
349
- <?php
350
- $cURL = curl_version();
351
- if ( version_compare( $cURL['version'], HEALTH_CHECK_CURL_MIN_VERSION, '<' ) ) {
352
- printf(
353
- '<span class="error"></span> %s',
354
- sprintf(
355
- // translators: %1$s: Current cURL version number. %2$s: Recommended minimum cURL version.
356
- esc_html__( 'Your version of cURL, %1$s, is lower than the recommended minimum version of %2$s. Your site may experience connection problems with other services and WordPress.org', 'health-check' ),
357
- $cURL['version'],
358
- HEALTH_CHECK_CURL_MIN_VERSION
359
- )
360
- );
361
- }
362
- elseif ( version_compare( $cURL['version'], HEALTH_CHECK_CURL_VERSION, '<' ) ) {
363
- printf(
364
- '<span class="warning"></span> %s',
365
- sprintf(
366
- // translators: %1$s: cURL version number running on the website. %2$s: The currently available cURL version.
367
- esc_html__( 'Your version of cURL, %1$s, is slightly out of date. The most recent version is %2$s. This may in some cases affect your sites ability to communicate with other services. If you are experiencing connectivity issues connecting to various services, please contact your host.', 'health-check' ),
368
- $cURL['version'],
369
- HEALTH_CHECK_CURL_VERSION
370
- )
371
- );
372
- }
373
- else {
374
- printf(
375
- '<span class="good"></span> %s',
376
- sprintf(
377
- // translators: %s: cURL version number.
378
- esc_html__( 'Your version of cURL, %s, is up to date.', 'health-check' ),
379
- $cURL['version']
380
- )
381
- );
382
- }
383
- ?>
384
- </td>
385
- </tr>
386
- <?php endif; ?>
387
-
388
  <tr>
389
  <td><?php esc_html_e( 'Scheduled events', 'health-check' ); ?></td>
390
  <td>
@@ -446,7 +409,7 @@ $db_dropin = file_exists( WP_CONTENT_DIR . '/db.php' );
446
  printf(
447
  '<span class="%s"></span> %s',
448
  esc_attr( $check_loopback->status ),
449
- esc_html( $check_loopback->message )
450
  );
451
 
452
  if ( 'error' === $check_loopback->status ) {
20
  $mysql_server_version = null;
21
  if ( method_exists( $wpdb, 'db_version' ) ) {
22
  if ( $wpdb->use_mysqli ) {
23
+ // phpcs:ignore WordPress.DB.RestrictedFunctions.mysql_mysqli_get_server_info
24
  $mysql_server_type = mysqli_get_server_info( $wpdb->dbh );
25
  } else {
26
+ // phpcs:ignore WordPress.DB.RestrictedFunctions.mysql_mysql_get_server_info
27
  $mysql_server_type = mysql_get_server_info( $wpdb->dbh );
28
  }
29
 
59
  $status = 'good';
60
  $notice = array();
61
 
62
+ if ( ! $php_min_version_check ) {
63
+ $status = 'error';
64
  $notice[] = sprintf(
65
  '<a href="%s">%s</a>',
66
  esc_url(
67
  _x( 'https://wordpress.org/support/upgrade-php/', 'The link to the Update PHP page, which may be localized.', 'health-check' )
68
  ),
69
  sprintf(
70
+ // translators: %1$s: Current PHP version. %2$s: Recommended PHP version. %3$s: Minimum PHP version.
71
+ esc_html__( 'Your version of PHP, %1$s, is very outdated and no longer receiving security updates and is not supported by WordPress. You should contact your host for an upgrade, WordPress recommends using PHP version %2$s, but will work with version %3$s or newer.', 'health-check' ),
72
+ PHP_VERSION,
73
+ HEALTH_CHECK_PHP_REC_VERSION,
74
+ HEALTH_CHECK_PHP_MIN_VERSION
75
  )
76
  );
77
+ } elseif ( ! $php_supported_version_check ) {
 
 
78
  $status = 'warning';
79
  $notice[] = sprintf(
80
  '<a href="%s">%s</a>',
88
  HEALTH_CHECK_PHP_REC_VERSION
89
  )
90
  );
91
+ } elseif ( ! $php_rec_version_check ) {
92
+ $status = 'warning';
 
 
93
  $notice[] = sprintf(
94
  '<a href="%s">%s</a>',
95
  esc_url(
96
  _x( 'https://wordpress.org/support/upgrade-php/', 'The link to the Update PHP page, which may be localized.', 'health-check' )
97
  ),
98
  sprintf(
99
+ // translators: %s: Recommended PHP version
100
+ esc_html__( 'For best performance we recommend using PHP %s or higher.', 'health-check' ),
101
+ HEALTH_CHECK_PHP_REC_VERSION
 
 
102
  )
103
  );
104
  }
154
 
155
  if ( $db_dropin ) {
156
  // translators: %s: The database engine in use (MySQL or MariaDB).
157
+ $notice[] = wp_kses(
158
+ sprintf(
159
+ // translators: %s: The name of the database engine being used.
160
+ __( 'You are using a <code>wp-content/db.php</code> drop-in which might mean that a %s database is not being used.', 'health-check' ),
161
+ ( $mariadb ? 'MariaDB' : 'MySQL' )
162
+ ),
163
+ array(
164
+ 'code' => true,
165
+ )
166
+ );
167
  }
168
 
169
  printf(
240
  }
241
 
242
  if ( $wpdb->use_mysqli ) {
243
+ // phpcs:ignore WordPress.DB.RestrictedFunctions.mysql_mysqli_get_client_info
244
  $mysql_client_version = mysqli_get_client_info();
245
  } else {
246
+ // phpcs:ignore WordPress.DB.RestrictedFunctions.mysql_mysql_get_client_info
247
  $mysql_client_version = mysql_get_client_info();
248
  }
249
 
285
  <td><?php esc_html_e( 'Communication with WordPress.org', 'health-check' ); ?></td>
286
  <td>
287
  <?php
288
+ $wp_dotorg = wp_remote_get( 'https://wordpress.org', array(
289
+ 'timeout' => 10,
290
+ ) );
291
  if ( ! is_wp_error( $wp_dotorg ) ) {
292
  printf(
293
  '<span class="good"></span> %s',
348
  </td>
349
  </tr>
350
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
351
  <tr>
352
  <td><?php esc_html_e( 'Scheduled events', 'health-check' ); ?></td>
353
  <td>
409
  printf(
410
  '<span class="%s"></span> %s',
411
  esc_attr( $check_loopback->status ),
412
+ $check_loopback->message
413
  );
414
 
415
  if ( 'error' === $check_loopback->status ) {
pages/phpinfo.php CHANGED
@@ -1,61 +1,61 @@
1
- <?php
2
- /**
3
- * The PHPInfo tab contents.
4
- *
5
- * @package Health Check
6
- */
7
-
8
- // Make sure the file is not directly accessible.
9
- if ( ! defined( 'ABSPATH' ) ) {
10
- die( 'We\'re sorry, but you can not directly access this file.' );
11
- }
12
-
13
- if ( ! function_exists( 'phpinfo' ) ) {
14
- ?>
15
-
16
- <div class="notice notice-error inline">
17
- <p>
18
- <?php esc_html_e( 'The phpinfo() function has been disabled by your host. Please contact the host if you need more information about your setup.' ); ?>
19
- </p>
20
- </div>
21
-
22
- <?php } else { ?>
23
-
24
- <div class="notice notice-warning inline">
25
- <p>
26
- <?php esc_html_e( 'Some scenarios require you to look up more detailed server configurations than what is normally required. This page allows you to view all available configuration options for your PHP setup. Please be advised that WordPress does not guarantee that any information shown on this page may not be considered private.' ); ?>
27
- </p>
28
- </div>
29
-
30
- <?php
31
- ob_start();
32
- phpinfo();
33
- $phpinfo_raw = ob_get_clean();
34
-
35
- // Extract the body of the `phpinfo()` call, to avoid all the styles they introduce.
36
- preg_match_all( '/<body[^>]*>(.*)<\/body>/siU', $phpinfo_raw, $phpinfo );
37
-
38
- // Extract the styles `phpinfo()` creates for this page.
39
- preg_match_all( '/<style[^>]*>(.*)<\/style>/siU', $phpinfo_raw, $styles );
40
-
41
- // We remove various styles that break the visual flow of wp-admin.
42
- $remove_patterns = array(
43
- "/a:.+?\n/si",
44
- "/body.+?\n/si",
45
- );
46
-
47
- // Output the styles as an inline style block.
48
- if ( isset( $styles[1][0] ) ) {
49
- $styles = preg_replace( $remove_patterns, '', $styles[1][0] );
50
-
51
- echo '<style type="text/css">' . $styles . '</style>';
52
- }
53
-
54
- // Output the actual phpinfo data.
55
- if ( isset( $phpinfo[1][0] ) ) {
56
- echo $phpinfo[1][0];
57
- }
58
- ?>
59
-
60
- <?php
61
- }
1
+ <?php
2
+ /**
3
+ * The PHPInfo tab contents.
4
+ *
5
+ * @package Health Check
6
+ */
7
+
8
+ // Make sure the file is not directly accessible.
9
+ if ( ! defined( 'ABSPATH' ) ) {
10
+ die( 'We\'re sorry, but you can not directly access this file.' );
11
+ }
12
+
13
+ if ( ! function_exists( 'phpinfo' ) ) {
14
+ ?>
15
+
16
+ <div class="notice notice-error inline">
17
+ <p>
18
+ <?php esc_html_e( 'The phpinfo() function has been disabled by your host. Please contact the host if you need more information about your setup.', 'health-check' ); ?>
19
+ </p>
20
+ </div>
21
+
22
+ <?php } else { ?>
23
+
24
+ <div class="notice notice-warning inline">
25
+ <p>
26
+ <?php esc_html_e( 'Some scenarios require you to look up more detailed server configurations than what is normally required. This page allows you to view all available configuration options for your PHP setup. Please be advised that WordPress does not guarantee that any information shown on this page may not be considered private.', 'health-check' ); ?>
27
+ </p>
28
+ </div>
29
+
30
+ <?php
31
+ ob_start();
32
+ phpinfo();
33
+ $phpinfo_raw = ob_get_clean();
34
+
35
+ // Extract the body of the `phpinfo()` call, to avoid all the styles they introduce.
36
+ preg_match_all( '/<body[^>]*>(.*)<\/body>/siU', $phpinfo_raw, $phpinfo );
37
+
38
+ // Extract the styles `phpinfo()` creates for this page.
39
+ preg_match_all( '/<style[^>]*>(.*)<\/style>/siU', $phpinfo_raw, $styles );
40
+
41
+ // We remove various styles that break the visual flow of wp-admin.
42
+ $remove_patterns = array(
43
+ "/a:.+?\n/si",
44
+ "/body.+?\n/si",
45
+ );
46
+
47
+ // Output the styles as an inline style block.
48
+ if ( isset( $styles[1][0] ) ) {
49
+ $styles = preg_replace( $remove_patterns, '', $styles[1][0] );
50
+
51
+ echo '<style type="text/css">' . $styles . '</style>';
52
+ }
53
+
54
+ // Output the actual phpinfo data.
55
+ if ( isset( $phpinfo[1][0] ) ) {
56
+ echo $phpinfo[1][0];
57
+ }
58
+ ?>
59
+
60
+ <?php
61
+ }
pages/tools.php CHANGED
@@ -12,35 +12,27 @@ if ( ! defined( 'ABSPATH' ) ) {
12
 
13
  ?>
14
 
15
- <div class="notice notice-info inline">
16
- <h2><?php esc_html_e( 'File Integrity', 'health-check' ); ?></h2>
17
- <p>
18
- <?php _e( 'The File Integrity checks all the core files with the <code>checksums</code> provided by the WordPress API to see if they are intact. If there are changes you will be able to make a Diff between the files hosted on WordPress.org and your installation to see what has been changed.', 'health-check' ); ?>
19
- </p>
20
- <form action="#" id="health-check-file-integrity" method="POST">
21
- <input type="submit" class="button button-primary" value="<?php esc_html_e( 'Check the Files Integrity', 'health-check' ); ?>">
22
- </form>
23
- </div>
24
- <div class="notice notice-info inline">
25
- <h2><?php esc_html_e( 'Mail Check', 'health-check' ); ?></h2>
26
- <p>
27
- <?php _e( 'The Mail Check will invoke the <code>wp_mail()</code> function and check if it succeeds. We will use the E-mail address you have set up, but you can change it below if you like.', 'health-check' ); ?>
28
- </p>
29
- <form action="#" id="health-check-mail-check" method="POST">
30
- <p>
31
- <?php
32
- $current_user = wp_get_current_user();
33
- ?>
34
- <label for="email"><?php _e( 'E-mail', 'health-check' ); ?></label>
35
- <input type="text" name="email" id="email" value="<?php echo $current_user->user_email; ?>">
36
- </p>
37
- <input type="submit" class="button button-primary" value="<?php esc_html_e( 'Check Mail', 'health-check' ); ?>">
38
- </form>
39
- </div>
40
 
41
- <div id="tools-response-holder">
42
- <span class="spinner"></span>
43
- </div>
44
 
45
- <?php
46
- include_once( HEALTH_CHECK_PLUGIN_DIRECTORY . '/modals/diff.php' );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
12
 
13
  ?>
14
 
15
+ <dl id="health-check-tools" role="presentation" class="health-check-accordion">
16
+ <?php
17
+ $tabs = apply_filters( 'health_check_tools_tab', array() );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
18
 
19
+ foreach ( $tabs as $count => $tab ) :
20
+ ?>
 
21
 
22
+ <dt role="heading" aria-level="2">
23
+ <button aria-expanded="false" class="health-check-accordion-trigger" aria-controls="health-check-accordion-block-<?php echo esc_attr( $count ); ?>" id="health-check-accordion-heading-<?php echo esc_attr( $count ); ?>" type="button">
24
+ <span class="title">
25
+ <?php echo $tab['label']; ?>
26
+ </span>
27
+ <span class="icon"></span>
28
+ </button>
29
+ </dt>
30
+ <dd id="health-check-accordion-block-<?php echo esc_attr( $count ); ?>" role="region" aria-labelledby="health-check-accordion-heading-<?php echo esc_attr( $count ); ?>" class="health-check-accordion-panel" hidden="hidden">
31
+ <?php echo $tab['content']; ?>
32
+ </dd>
33
+
34
+ <?php endforeach; ?>
35
+ </dl>
36
+
37
+ <?php
38
+ include_once( HEALTH_CHECK_PLUGIN_DIRECTORY . '/modals/diff.php' );
pages/troubleshoot.php CHANGED
@@ -1,38 +1,38 @@
1
- <?php
2
- /**
3
- * The Troubleshooting tab contents.
4
- *
5
- * @package Health Check
6
- */
7
-
8
- // Make sure the file is not directly accessible.
9
- if ( ! defined( 'ABSPATH' ) ) {
10
- die( 'We\'re sorry, but you can not directly access this file.' );
11
- }
12
-
13
- ?>
14
- <div class="notice notice-warning inline">
15
- <p>
16
- <?php esc_html_e( 'When troubleshooting issues on your site, you are likely to be told to disable all plugins and switch to the default theme.', 'health-check' ); ?>
17
- <?php esc_html_e( 'Understandably, you do not wish to do so as it may affect your site visitors, leaving them with lost functionality.', 'health-check' ); ?>
18
- </p>
19
-
20
- <p>
21
- <?php esc_html_e( 'By enabling the Troubleshooting Mode, all plugins will appear inactive and your site will switch to the default theme only for you. All other users will see your site as usual.', 'health-check' ); ?>
22
- </p>
23
-
24
- <p>
25
- <?php esc_html_e( 'A Troubleshooting Mode menu is added to your admin bar, which will allow you to enable plugins individually, switch back to your current theme, and disable Troubleshooting Mode.', 'health-check' ); ?>
26
- </p>
27
-
28
- <p>
29
- <?php esc_html_e( 'Please note, that due to how Must Use plugins work, any such plugin will not be disabled for the troubleshooting session.', 'health-check' ); ?>
30
- </p>
31
- </div>
32
-
33
- <?php
34
- Health_Check_Troubleshoot::show_enable_troubleshoot_form();
35
-
36
- if ( ! Health_Check_Troubleshoot::has_seen_warning() ) {
37
- include_once( HEALTH_CHECK_PLUGIN_DIRECTORY . '/modals/backup-warning.php' );
38
- }
1
+ <?php
2
+ /**
3
+ * The Troubleshooting tab contents.
4
+ *
5
+ * @package Health Check
6
+ */
7
+
8
+ // Make sure the file is not directly accessible.
9
+ if ( ! defined( 'ABSPATH' ) ) {
10
+ die( 'We\'re sorry, but you can not directly access this file.' );
11
+ }
12
+
13
+ ?>
14
+ <div class="notice notice-warning inline">
15
+ <p>
16
+ <?php esc_html_e( 'When troubleshooting issues on your site, you are likely to be told to disable all plugins and switch to the default theme.', 'health-check' ); ?>
17
+ <?php esc_html_e( 'Understandably, you do not wish to do so as it may affect your site visitors, leaving them with lost functionality.', 'health-check' ); ?>
18
+ </p>
19
+
20
+ <p>
21
+ <?php esc_html_e( 'By enabling the Troubleshooting Mode, all plugins will appear inactive and your site will switch to the default theme only for you. All other users will see your site as usual.', 'health-check' ); ?>
22
+ </p>
23
+
24
+ <p>
25
+ <?php esc_html_e( 'A Troubleshooting Mode menu is added to your admin bar, which will allow you to enable plugins individually, switch back to your current theme, and disable Troubleshooting Mode.', 'health-check' ); ?>
26
+ </p>
27
+
28
+ <p>
29
+ <?php esc_html_e( 'Please note, that due to how Must Use plugins work, any such plugin will not be disabled for the troubleshooting session.', 'health-check' ); ?>
30
+ </p>
31
+ </div>
32
+
33
+ <?php
34
+ Health_Check_Troubleshoot::show_enable_troubleshoot_form();
35
+
36
+ if ( ! Health_Check_Troubleshoot::has_seen_warning() ) {
37
+ include_once( HEALTH_CHECK_PLUGIN_DIRECTORY . '/modals/backup-warning.php' );
38
+ }
readme.txt CHANGED
@@ -3,7 +3,9 @@ Tags: health check
3
  Contributors: wordpressdotorg, westi, pento, Clorith
4
  Requires at least: 3.8
5
  Tested up to: 4.9
6
- Stable tag: 1.0.1
 
 
7
 
8
  == Description ==
9
 
@@ -33,42 +35,17 @@ In the future we may introduce more checks, and welcome feedback both through th
33
 
34
  == Changelog ==
35
 
36
- = v 1.0.1 =
37
- * Fixed email tester having the wrong class reference, preventing it from running.
38
- * Add some missing text domains preventing full translations.
39
-
40
- = v 1.0.0 =
41
- * Added minimum PHP version checks with documentation links.
42
- * Added testing with a default theme to the loopback checker.
43
- * Added cURL version checker to the health check tab.
44
- * Added simple e-mail tester.
45
- * Added core file integrity checker.
46
- * Added capability checks, to avoid installing things that may modify the database while troubleshooting.
47
- * Added a prompt to install a default theme if none exist.
48
- * Added a warning encouraging users to maintain up to date backups when troubleshooting.
49
- * Fixed MU plugin not always updating (if available) when a user tries to troubleshoot.
50
- * Fixed fatal error when trying to troubleshoot "too early".
51
- * Updated troubleshooting drop down, it no longer shows theme switching if no default theme exists.
52
- * Removed the checkbox requirement from the Troubleshooting tab, it wasn't needed any more, and added pointless complexity now.
53
-
54
- = v 0.9.0 =
55
- * Various string changes, typo fixes and translation enhancements.
56
- * Added conditional hiding of the plugins list from the admin bar, if there's too many plugins it becomes a bad experience. (Hidden if there are more than 20 active plugins)
57
- * Added ability to enable/disable plugins in Troubleshooting Mode from the plugins list.
58
- * Added filter to remove actions from the plugin list in Troubleshooting Mode.
59
- * Fixed notices on the plugin screen when plugin data may be inconsistent.
60
- * Fixed jumping directly to troubleshooting mode for single file plugins placed directly in the plugin directory root.
61
- * Fixed issue where troubleshooting a plugin directly made it impossible to disable it while in Troubleshooting Mode.
62
- * Fixed so that the original language is returned when translating the debug data for copying.
63
- * Fixed issue where the Debug screen would turn to half-English when using a non-English language.
64
- * Fixed an issue where plugins could become truly disabled on a site when in Troubleshooting Mode.
65
- * Fixed so that enabled/disabled plugins don't carry over between troubleshooting sessions.
66
-
67
- = v 0.8.0 =
68
- * Updated recommended PHP version to mirror WordPress.org.
69
- * Updated texts for troubleshooting mode.
70
- * Re-labeled database terms to be more user friendly.
71
- * Added media information to the debug tab.
72
- * Added individual `Troubleshoot` links for the list of active plugins.
73
- * Added automatic copy to clipboard with supported browsers in the debug tab.
74
-
3
  Contributors: wordpressdotorg, westi, pento, Clorith
4
  Requires at least: 3.8
5
  Tested up to: 4.9
6
+ Stable tag: 1.1.0
7
+ License: GPLv2
8
+ License URI: https://www.gnu.org/licenses/gpl-2.0.html
9
 
10
  == Description ==
11
 
35
 
36
  == Changelog ==
37
 
38
+ = v 1.1.0 =
39
+ * Check for theme, plugin and WordPress updates when visiting the debug tab.
40
+ * Improved wording on some failure situations.
41
+ * Made the Debug Information tab a bit easier to read with fixed table styles.
42
+ * Redesigned tools page, with added accordion to avoid information overload, and different features mixing together.
43
+ * Mail test tool now allows you to include an optional customized message.
44
+ * Users can now change between any installed theme while in troubleshooting mode.
45
+ * Renamed the Must-Use plugin, making it align with what features present in the file.
46
+ * Improved the plugin cleanup process, when the plugin is deleted.
47
+ * Show full plugin names, and not slugs, in the troubleshooting admin bar menu.
48
+ * Check if the .htaccess file contains any rules not added by WordPress core in the debug section.
49
+ * Allow the disabling of Troubleshooting Mode from the same page as you previously enabled it from.
50
+ * Removed cURL checks from the automated test page, this was more confusion than help.
51
+ * Add installation size to the debug information.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
uninstall.php CHANGED
@@ -1,32 +1,39 @@
1
- <?php
2
- /**
3
- * Perform plugin installation routines.
4
- *
5
- * @package Health Check
6
- */
7
-
8
- global $wpdb;
9
-
10
- // Make sure the uninstall file can't be accessed directly.
11
- if ( ! defined( 'WP_UNINSTALL_PLUGIN' ) ) {
12
- die;
13
- }
14
-
15
- // Remove options introduced by the plugin.
16
- delete_option( 'health-check-disable-plugin-hash' );
17
-
18
- /*
19
- * Remove any user meta entries we made, done with a custom query as core
20
- * does not provide an option to clear them for all users.
21
- */
22
- $wpdb->delete(
23
- $wpdb->usermeta,
24
- array(
25
- 'meta_key' => 'health-check'
26
- )
27
- );
28
-
29
- // Remove the Must-Use plugin if it was implemented.
30
- if ( file_exists( trailingslashit( WPMU_PLUGIN_DIR ) . 'health-check-disable-plugins.php' ) ) {
31
- unlink( trailingslashit( WPMU_PLUGIN_DIR ) . 'health-check-disable-plugins.php' );
32
- }
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Perform plugin installation routines.
4
+ *
5
+ * @package Health Check
6
+ */
7
+
8
+ global $wpdb;
9
+
10
+ // Make sure the uninstall file can't be accessed directly.
11
+ if ( ! defined( 'WP_UNINSTALL_PLUGIN' ) ) {
12
+ die;
13
+ }
14
+
15
+ // Remove options introduced by the plugin.
16
+ delete_option( 'health-check-disable-plugin-hash' );
17
+ delete_option( 'health-check-default-theme' );
18
+ delete_option( 'health-check-current-theme' );
19
+
20
+ /*
21
+ * Remove any user meta entries we made, done with a custom query as core
22
+ * does not provide an option to clear them for all users.
23
+ */
24
+ $wpdb->delete(
25
+ $wpdb->usermeta,
26
+ array(
27
+ 'meta_key' => 'health-check',
28
+ )
29
+ );
30
+
31
+ // Remove the old Must-Use plugin if it was implemented.
32
+ if ( file_exists( trailingslashit( WPMU_PLUGIN_DIR ) . 'health-check-disable-plugins.php' ) ) {
33
+ wp_delete_file( trailingslashit( WPMU_PLUGIN_DIR ) . 'health-check-disable-plugins.php' );
34
+ }
35
+
36
+ // Remove the renamed Must-Use plugin if it exists
37
+ if ( file_exists( trailingslashit( WPMU_PLUGIN_DIR ) . 'health-check-troubleshooting-mode.php' ) ) {
38
+ wp_delete_file( trailingslashit( WPMU_PLUGIN_DIR ) . 'health-check-troubleshooting-mode.php' );
39
+ }