Theme Check - Version 20210617

Version Description

Download this release

Release Info

Developer githubsync
Plugin Icon 128x128 Theme Check
Version 20210617
Comparing to
See all releases

Code changes from version 20200922.1 to 20210617

Files changed (105) hide show
  1. README.md +54 -0
  2. checkbase.php +170 -135
  3. checks/admin_menu.php +0 -73
  4. checks/adminbar.php +0 -55
  5. checks/badthings.php +0 -60
  6. checks/basic.php +0 -47
  7. checks/cdn.php +0 -45
  8. checks/class-admin-menu-check.php +107 -0
  9. checks/class-bad-things-check.php +114 -0
  10. checks/class-basic-check.php +84 -0
  11. checks/class-block-patterns-check.php +62 -0
  12. checks/class-cdn-check.php +79 -0
  13. checks/class-comment-pagination-check.php +62 -0
  14. checks/class-comment-reply-check.php +63 -0
  15. checks/class-comments-check.php +67 -0
  16. checks/class-constants-check.php +83 -0
  17. checks/class-customizer-check.php +99 -0
  18. checks/class-deprecated-check.php +1201 -0
  19. checks/{more_deprecated.php → class-deprecated-param-check.php} +43 -9
  20. checks/class-deregister-check.php +45 -0
  21. checks/class-directories-check.php +73 -0
  22. checks/class-editor-style-check.php +55 -0
  23. checks/{escaping.php → class-escaping-check.php} +122 -105
  24. checks/class-favicon-check.php +66 -0
  25. checks/{filenames.php → class-file-check.php} +53 -18
  26. checks/class-filesystem-http-check.php +81 -0
  27. checks/class-fse-required-files-check.php +63 -0
  28. checks/class-generated-check.php +74 -0
  29. checks/class-gravatar-check.php +56 -0
  30. checks/class-i18n-check.php +103 -0
  31. checks/class-iframe-check.php +70 -0
  32. checks/class-include-check.php +69 -0
  33. checks/class-included-zip-check.php +69 -0
  34. checks/class-line-endings-check.php +92 -0
  35. checks/class-link-check.php +93 -0
  36. checks/class-nav-menu-check.php +127 -0
  37. checks/class-no-hidden-admin-bar-check.php +86 -0
  38. checks/class-non-gpl-check.php +75 -0
  39. checks/class-non-printable-check.php +61 -0
  40. checks/class-php-short-tags-check.php +58 -0
  41. checks/{plugin-territory.php → class-plugin-territory-check.php} +39 -10
  42. checks/class-post-format-check.php +77 -0
  43. checks/class-post-pagination-check.php +60 -0
  44. checks/class-post-thumbnail-check.php +63 -0
  45. checks/class-screen-reader-text-check.php +60 -0
  46. checks/class-screenshot-check.php +102 -0
  47. checks/class-script-tag-check.php +64 -0
  48. checks/class-search-form-check.php +86 -0
  49. checks/{siteurl.php → class-site-url-check.php} +59 -54
  50. checks/class-style-css-header-check.php +68 -0
  51. checks/class-style-tags-check.php +238 -0
  52. checks/class-suggested-styles-check.php +78 -0
  53. checks/class-tag-check.php +41 -0
  54. checks/class-theme-support-check.php +64 -0
  55. checks/class-theme-support-title-tag.php +53 -0
  56. checks/class-time-date-check.php +67 -0
  57. checks/class-title-check.php +82 -0
  58. checks/class-underscores-check.php +115 -0
  59. checks/class-uri-check.php +81 -0
  60. checks/class-widgets-check.php +103 -0
  61. checks/class-worms-check.php +61 -0
  62. checks/comment_reply.php +0 -27
  63. checks/commpage.php +0 -26
  64. checks/constants.php +0 -41
  65. checks/content-width.php +16 -8
  66. checks/customizer.php +0 -59
  67. checks/customs.php +0 -26
  68. checks/dep_recommend.php +0 -67
  69. checks/deprecated.php +0 -345
  70. checks/deregister.php +0 -29
  71. checks/directories.php +0 -36
  72. checks/editorstyle.php +0 -21
  73. checks/favicon.php +0 -33
  74. checks/generated.php +0 -42
  75. checks/gravatar.php +0 -24
  76. checks/i18n.php +0 -70
  77. checks/iframes.php +0 -29
  78. checks/include.php +0 -29
  79. checks/included-plugins.php +0 -34
  80. checks/lineendings.php +0 -43
  81. checks/links.php +0 -34
  82. checks/malware.php +0 -34
  83. checks/navmenu.php +0 -73
  84. checks/nongplsites.php +0 -46
  85. checks/nonprintable.php +0 -27
  86. checks/phpshort.php +0 -24
  87. checks/post-formats.php +0 -38
  88. checks/postsnav.php +0 -28
  89. checks/postthumb.php +0 -27
  90. checks/screenshot.php +0 -45
  91. checks/searchform.php +0 -26
  92. checks/style_needed.php +0 -43
  93. checks/style_suggested.php +0 -29
  94. checks/style_tags.php +0 -158
  95. checks/tags.php +0 -22
  96. checks/textdomain.php +138 -92
  97. checks/time_date.php +0 -31
  98. checks/title.php +0 -70
  99. checks/underscores.php +0 -57
  100. checks/uri.php +0 -31
  101. checks/widgets.php +0 -42
  102. checks/worms.php +0 -33
  103. main.php +147 -187
  104. readme.txt +3 -3
  105. theme-check.php +7 -5
README.md ADDED
@@ -0,0 +1,54 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Theme Check
2
+
3
+ The theme check plugin is an easy way to test your theme and make sure it's up to spec with the latest [theme review](https://make.wordpress.org/themes/handbook/review/) standards. With it, you can run all the same automated testing tools on your theme that WordPress.org uses for theme submissions.
4
+
5
+ The tests are run through a simple admin menu and all results are displayed at once. This is very handy for theme developers, or anybody looking to make sure that their theme supports the latest WordPress theme standards and practices.
6
+
7
+ ## Frequently Asked Questions
8
+
9
+ ### Why does it flag something as bad?
10
+
11
+ It's not flagging "bad" things, as such. The theme check is designed to be a non-perfect way to test for compliance with the [Theme Review](https://make.wordpress.org/themes/handbook/review/) guidelines. Not all themes must adhere to these guidelines. The purpose of the checking tool is to ensure that themes uploaded to the central [WordPress.org theme repository](http://wordpress.org/themes/) meet the latest standards of WordPress themes and will work on a wide variety of sites.
12
+
13
+ Many sites use customized themes, and that's perfectly okay. But themes that are intended for use on many different kinds of sites by the public need to have a certain minimum level of capabilities, in order to ensure proper functioning in many different environments. The Theme Review guidelines are created with that goal in mind.
14
+
15
+ This theme checker is not perfect, and never will be. It is only a tool to help theme authors, or anybody else who wants to make their theme more capable. All themes submitted to WordPress.org are hand-reviewed by a team of experts. The automated theme checker is meant to be a useful tool only, not an absolute system of measurement.
16
+
17
+ This plugin does not decide the guidelines used. Any issues with particular theme review guidelines should be discussed on the [Make Themes site](https://make.wordpress.org/themes), or [https://github.com/WPTRT/Theme-Requirements](https://github.com/WPTRT/Theme-Requirements)
18
+
19
+ ## Other Notes
20
+
21
+ ### How to enable trac formatting
22
+ The Theme Review team use this plugin while reviewing themes and copy/paste the output into trac tickets, the trac system has its own markup language.
23
+ To enable trac formatting in Theme-Check you need to define a couple of variables in wp-config.php:
24
+ *TC_PRE* and *TC_POST* are used as a ticket header and footer.
25
+ Examples:
26
+ ```
27
+ define( 'TC_PRE', 'Theme Review:[[br]]
28
+ - Themes should be reviewed using "define(\'WP_DEBUG\', true);" in wp-config.php[[br]]
29
+ - Themes should be reviewed using the test data from the Theme Checklists (TC)
30
+ -----
31
+ ' );
32
+ ```
33
+
34
+ ```
35
+ define( 'TC_POST', 'Feel free to make use of the contact details below if you have any questions,
36
+ comments, or feedback:[[br]]
37
+ [[br]]
38
+ * Leave a comment on this ticket[[br]]
39
+ * Send an email to the Theme Review email list[[br]]
40
+ * Use the #wordpress-themes IRC channel on Freenode.' );
41
+ ```
42
+
43
+ If **either** of these two vars are defined a new trac tickbox will appear next to the *Check it!* button.
44
+
45
+ If you want to exclude checking other files in development directories return `true` for the filter `tc_skip_development_directories`.
46
+
47
+ ```
48
+ add_filter( 'tc_skip_development_directories', '__return_true' );
49
+ ```
50
+
51
+ To add more directories to the paths where other files are excluded then add them to the array through the `tc_common_dev_directories` filter.
52
+
53
+ ## Contributors
54
+ Otto42, pross, The theme review team
checkbase.php CHANGED
@@ -1,9 +1,18 @@
1
  <?php
2
- // main global to hold our checks
 
 
 
 
 
 
 
 
 
3
  global $themechecks;
4
  $themechecks = array();
5
 
6
- // counter for the checks
7
  global $checkcount;
8
  $checkcount = 0;
9
 
@@ -18,21 +27,83 @@ interface themecheck {
18
  }
19
 
20
  // load all the checks in the checks directory.
21
- $dir = 'checks';
22
- foreach ( glob( dirname( __FILE__ ) . "/{$dir}/*.php" ) as $file ) {
23
  include $file;
24
  }
25
 
26
  do_action( 'themecheck_checks_loaded' );
27
 
28
- function run_themechecks( $php, $css, $other ) {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
29
  global $themechecks;
 
30
  $pass = true;
 
 
 
31
  foreach ( $themechecks as $check ) {
32
  if ( $check instanceof themecheck ) {
 
 
 
 
33
  $pass = $pass & $check->check( $php, $css, $other );
34
  }
35
  }
 
36
  return $pass;
37
  }
38
 
@@ -93,7 +164,7 @@ function tc_grep( $error, $file ) {
93
  $error = str_replace( '"', "'", $error );
94
  $this_line = str_replace( '"', "'", $this_line );
95
  $error = ltrim( $error );
96
- $pos = strpos( $this_line, $error );
97
  $pre = ( false !== $pos ? substr( $this_line, 0, $pos ) : false );
98
  $pre = ltrim( htmlspecialchars( $pre ) );
99
  $bad_lines .= "<pre class='tc-grep'>" . __( 'Line ', 'theme-check' ) . ( $line_index + 1 ) . ': ' . $pre . htmlspecialchars( substr( stristr( $this_line, $error ), 0, 75 ) ) . '</pre>';
@@ -149,152 +220,116 @@ function tc_trac( $e ) {
149
  return $e;
150
  }
151
 
152
- function listdir( $dir ) {
153
- $files = array();
154
- $dir_iterator = new RecursiveDirectoryIterator( $dir );
155
- $iterator = new RecursiveIteratorIterator( $dir_iterator, RecursiveIteratorIterator::SELF_FIRST );
156
-
157
- foreach ( $iterator as $file ) {
158
- array_push( $files, $file->getPathname() );
159
- }
160
- return $files;
161
- }
162
-
163
- function get_theme_data_from_contents( $theme_data ) {
164
- $themes_allowed_tags = array(
165
- 'a' => array(
166
- 'href' => array(),
167
- 'title' => array(),
168
- ),
169
- 'abbr' => array(
170
- 'title' => array(),
171
- ),
172
- 'acronym' => array(
173
- 'title' => array(),
174
- ),
175
- 'code' => array(),
176
- 'em' => array(),
177
- 'strong' => array(),
178
  );
179
-
180
- $theme_data = str_replace( '\r', '\n', $theme_data );
181
- preg_match( '|^[ \t\/*#@]*Theme Name:(.*)$|mi', $theme_data, $theme_name );
182
- preg_match( '|^[ \t\/*#@]*Theme URI:(.*)$|mi', $theme_data, $theme_uri );
183
- preg_match( '|^[ \t\/*#@]*Description:(.*)$|mi', $theme_data, $description );
184
-
185
- if ( preg_match( '|^[ \t\/*#@]*Author URI:(.*)$|mi', $theme_data, $author_uri ) ) {
186
- $author_uri = esc_url( trim( $author_uri[1] ) );
187
- } else {
188
- $author_uri = '';
189
- }
190
-
191
- if ( preg_match( '|^[ \t\/*#@]*Template:(.*)$|mi', $theme_data, $template ) ) {
192
- $template = wp_kses( trim( $template[1] ), $themes_allowed_tags );
193
- } else {
194
- $template = '';
195
- }
196
-
197
- if ( preg_match( '|^[ \t\/*#@]*Version:(.*)|mi', $theme_data, $version ) ) {
198
- $version = wp_kses( trim( $version[1] ), $themes_allowed_tags );
199
- } else {
200
- $version = '';
201
- }
202
-
203
- if ( preg_match( '|^[ \t\/*#@]*Status:(.*)|mi', $theme_data, $status ) ) {
204
- $status = wp_kses( trim( $status[1] ), $themes_allowed_tags );
205
- } else {
206
- $status = 'publish';
207
- }
208
-
209
- if ( preg_match( '|^[ \t\/*#@]*Tags:(.*)|mi', $theme_data, $tags ) ) {
210
- $tags = array_map( 'trim', explode( ',', wp_kses( trim( $tags[1] ), array() ) ) );
211
- } else {
212
- $tags = array();
213
- }
214
-
215
- $theme = ( isset( $theme_name[1] ) ) ? wp_kses( trim( $theme_name[1] ), $themes_allowed_tags ) : '';
216
-
217
- $theme_uri = ( isset( $theme_uri[1] ) ) ? esc_url( trim( $theme_uri[1] ) ) : '';
218
-
219
- $description = ( isset( $description[1] ) ) ? wp_kses( trim( $description[1] ), $themes_allowed_tags ) : '';
220
-
221
- if ( preg_match( '|^[ \t\/*#@]*Author:(.*)$|mi', $theme_data, $author_name ) ) {
222
- if ( empty( $author_uri ) ) {
223
- $author = wp_kses( trim( $author_name[1] ), $themes_allowed_tags );
224
  } else {
225
- $author = sprintf( '<a href="%1$s" title="%2$s">%3$s</a>', $author_uri, __( 'Visit author homepage', 'theme-check' ), wp_kses( trim( $author_name[1] ), $themes_allowed_tags ) );
 
 
 
 
226
  }
227
- } else {
228
- $author = __( 'Anonymous', 'theme-check' );
229
  }
 
 
230
 
231
- return array(
232
- 'Name' => $theme,
233
- 'Title' => $theme,
234
- 'URI' => $theme_uri,
235
- 'Description' => $description,
236
- 'Author' => $author,
237
- 'Author_URI' => $author_uri,
238
- 'Version' => $version,
239
- 'Template' => $template,
240
- 'Status' => $status,
241
- 'Tags' => $tags,
 
 
 
 
 
242
  );
 
 
 
 
 
 
 
243
  }
244
 
245
- /*
246
- * 3.3/3.4 compat
247
  *
 
 
 
 
 
248
  */
249
- function tc_get_themes() {
 
250
 
251
- if ( ! class_exists( 'WP_Theme' ) ) {
252
- return wp_get_theme();
 
 
253
  }
254
 
255
- global $wp_themes;
256
- if ( isset( $wp_themes ) ) {
257
- return $wp_themes;
258
  }
259
 
260
- $themes = wp_get_themes();
261
- $wp_themes = array();
262
-
263
- foreach ( $themes as $theme ) {
264
- $name = $theme->get( 'Name' );
265
- if ( isset( $wp_themes[ $name ] ) ) {
266
- $wp_themes[ $name . '/' . $theme->get_stylesheet() ] = $theme;
267
- } else {
268
- $wp_themes[ $name ] = $theme;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
269
  }
270
  }
271
 
272
- return $wp_themes;
273
- }
274
-
275
- function tc_get_theme_data( $theme_file ) {
276
 
277
- if ( ! class_exists( 'WP_Theme' ) ) {
278
- return wp_get_theme( $theme_file );
279
- }
280
-
281
- $theme = new WP_Theme( basename( dirname( $theme_file ) ), dirname( dirname( $theme_file ) ) );
282
-
283
- $theme_data = array(
284
- 'Name' => $theme->get( 'Name' ),
285
- 'URI' => $theme->display( 'ThemeURI', true, false ),
286
- 'Description' => $theme->display( 'Description', true, false ),
287
- 'Author' => $theme->display( 'Author', true, false ),
288
- 'AuthorURI' => $theme->display( 'AuthorURI', true, false ),
289
- 'Version' => $theme->get( 'Version' ),
290
- 'Template' => $theme->get( 'Template' ),
291
- 'Status' => $theme->get( 'Status' ),
292
- 'Tags' => $theme->get( 'Tags' ),
293
- 'Title' => $theme->get( 'Name' ),
294
- 'AuthorName' => $theme->display( 'Author', false, false ),
295
- 'License' => $theme->display( 'License', false, false ),
296
- 'License URI' => $theme->display( 'License URI', false, false ),
297
- 'Template Version' => $theme->display( 'Template Version', false, false ),
298
- );
299
- return $theme_data;
300
  }
1
  <?php
2
+ /**
3
+ * Runs checks against themes and displays the results
4
+ *
5
+ * Runs checks against themes and displays the results. Includes helper functions
6
+ * for performing checks.
7
+ *
8
+ * @package Theme Check
9
+ */
10
+
11
+ // main global to hold our checks.
12
  global $themechecks;
13
  $themechecks = array();
14
 
15
+ // counter for the checks.
16
  global $checkcount;
17
  $checkcount = 0;
18
 
27
  }
28
 
29
  // load all the checks in the checks directory.
30
+ foreach ( glob( __DIR__ . '/checks/*.php' ) as $file ) {
 
31
  include $file;
32
  }
33
 
34
  do_action( 'themecheck_checks_loaded' );
35
 
36
+ /**
37
+ * Run Theme Check against a given theme.
38
+ *
39
+ * @param WP_Theme $theme A WP_Theme instance.
40
+ * @param string $theme_slug The slug of the given theme.
41
+ * @return bool
42
+ */
43
+ function run_themechecks_against_theme( $theme, $theme_slug ) {
44
+ $files = $theme->get_files(
45
+ null /* all file types */,
46
+ -1 /* infinite recursion */,
47
+ true /* include parent theme files */
48
+ );
49
+
50
+ foreach ( $files as $filename ) {
51
+ if ( substr( $filename, -4 ) === '.php' ) {
52
+ $php[ $filename ] = file_get_contents( $filename );
53
+ $php[ $filename ] = tc_strip_comments( $php[ $filename ] );
54
+ } elseif ( substr( $filename, -4 ) === '.css' ) {
55
+ $css[ $filename ] = file_get_contents( $filename );
56
+ } else {
57
+ // In local development it might be useful to skip other files
58
+ // (non .php or .css files) in dev directories.
59
+ if ( apply_filters( 'tc_skip_development_directories', false ) ) {
60
+ if ( tc_is_other_file_in_dev_directory( $filename ) ) {
61
+ continue;
62
+ }
63
+ }
64
+ $other[ $filename ] = file_get_contents( $filename );
65
+ }
66
+ }
67
+
68
+ // Run the checks.
69
+ return run_themechecks(
70
+ $php,
71
+ $css,
72
+ $other,
73
+ array(
74
+ 'theme' => $theme,
75
+ 'slug' => $theme_slug,
76
+ )
77
+ );
78
+ }
79
+
80
+ /**
81
+ * Run the Theme Checks against a set of files.
82
+ *
83
+ * @param array $php The PHP files.
84
+ * @param array $css The CSS files.
85
+ * @param array $other Any non-php/css files.
86
+ * @param array $context Any context for the Theme Checks.
87
+ *
88
+ * @return bool
89
+ */
90
+ function run_themechecks( $php, $css, $other, $context = array() ) {
91
  global $themechecks;
92
+
93
  $pass = true;
94
+
95
+ tc_adapt_checks_for_fse_themes( $php, $css, $other );
96
+
97
  foreach ( $themechecks as $check ) {
98
  if ( $check instanceof themecheck ) {
99
+ if ( $context && is_callable( array( $check, 'set_context' ) ) ) {
100
+ $check->set_context( $context );
101
+ }
102
+
103
  $pass = $pass & $check->check( $php, $css, $other );
104
  }
105
  }
106
+
107
  return $pass;
108
  }
109
 
164
  $error = str_replace( '"', "'", $error );
165
  $this_line = str_replace( '"', "'", $this_line );
166
  $error = ltrim( $error );
167
+ $pos = strpos( $this_line, $error );
168
  $pre = ( false !== $pos ? substr( $this_line, 0, $pos ) : false );
169
  $pre = ltrim( htmlspecialchars( $pre ) );
170
  $bad_lines .= "<pre class='tc-grep'>" . __( 'Line ', 'theme-check' ) . ( $line_index + 1 ) . ': ' . $pre . htmlspecialchars( substr( stristr( $this_line, $error ), 0, 75 ) ) . '</pre>';
220
  return $e;
221
  }
222
 
223
+ // Strip comments from a PHP file in a way that will not change the underlying structure of the file.
224
+ function tc_strip_comments( $code ) {
225
+ $strip = array(
226
+ T_COMMENT => true,
227
+ T_DOC_COMMENT => true,
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
228
  );
229
+ $newlines = array(
230
+ "\n" => true,
231
+ "\r" => true,
232
+ );
233
+ $tokens = token_get_all( $code );
234
+ reset( $tokens );
235
+ $return = '';
236
+ $token = current( $tokens );
237
+ while ( $token ) {
238
+ if ( ! is_array( $token ) ) {
239
+ $return .= $token;
240
+ } elseif ( ! isset( $strip[ $token[0] ] ) ) {
241
+ $return .= $token[1];
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
242
  } else {
243
+ for ( $i = 0, $token_length = strlen( $token[1] ); $i < $token_length; ++$i ) {
244
+ if ( isset( $newlines[ $token[1][ $i ] ] ) ) {
245
+ $return .= $token[1][ $i ];
246
+ }
247
+ }
248
  }
249
+ $token = next( $tokens );
 
250
  }
251
+ return $return;
252
+ }
253
 
254
+ /**
255
+ * Used to allow some directories to be skipped during development.
256
+ *
257
+ * @param string $filename a filename/path.
258
+ * @return boolean
259
+ */
260
+ function tc_is_other_file_in_dev_directory( $filename ) {
261
+ $skip = false;
262
+ // Filterable List of dirs that you may want to skip other files in during
263
+ // development.
264
+ $dev_dirs = apply_filters(
265
+ 'tc_common_dev_directories',
266
+ array(
267
+ 'node_modules',
268
+ 'vendor',
269
+ )
270
  );
271
+ foreach ( $dev_dirs as $dev_dir ) {
272
+ if ( strpos( $filename, $dev_dir ) ) {
273
+ $skip = true;
274
+ break;
275
+ }
276
+ }
277
+ return $skip;
278
  }
279
 
280
+ /**
281
+ * Adapt the Theme Checks if the theme is an experiment Full-Site Editing theme.
282
  *
283
+ * @param array $php_files The theme's PHP files.
284
+ * @param array $css_files The theme's CSS files.
285
+ * @param array $other_files Any other theme files.
286
+ *
287
+ * @return bool Whether the theme checks were adapted for FSE or not.
288
  */
289
+ function tc_adapt_checks_for_fse_themes( $php_files, $css_files, $other_files ) {
290
+ global $themechecks;
291
 
292
+ // Get a list of all non PHP and CSS file paths, relative to the theme root.
293
+ $other_filenames = array();
294
+ foreach ( $other_files as $path => $contents ) {
295
+ $other_filenames[] = tc_filename( $path );
296
  }
297
 
298
+ // Check whether this is a FSE theme by searching for an index.html block template.
299
+ if ( ! in_array( 'block-templates/index.html', $other_filenames, true ) ) {
300
+ return false;
301
  }
302
 
303
+ // Remove theme checks that do not apply to FSE themes.
304
+ foreach ( $themechecks as $key => $check ) {
305
+ if ( $check instanceof Tag_Check
306
+ || $check instanceof Suggested_Styles_Check
307
+ || $check instanceof Widgets_Check
308
+ || $check instanceof Gravatar_Check
309
+ || $check instanceof Post_Pagination_Check
310
+ || $check instanceof Basic_Check
311
+ || $check instanceof Comments_Check
312
+ || $check instanceof Comment_Pagination_Check
313
+ || $check instanceof Comment_Reply_Check
314
+ || $check instanceof Nav_Menu_Check
315
+ || $check instanceof Post_Thumbnail_Check
316
+ || $check instanceof Theme_Support_Check
317
+ || $check instanceof Editor_Style_Check
318
+ || $check instanceof Underscores_Check
319
+ || $check instanceof Constants_Check
320
+ || $check instanceof Customizer_Check
321
+ || $check instanceof Post_Format_Check
322
+ || $check instanceof Search_Form_Check
323
+ || $check instanceof Theme_Support_Title_Tag_Check
324
+ || $check instanceof Screen_Reader_Text_Check
325
+ || $check instanceof Include_Check
326
+ ) {
327
+ unset( $themechecks[ $key ] );
328
  }
329
  }
330
 
331
+ // Add FSE specific checks.
332
+ $themechecks[] = new FSE_Required_Files_Check();
 
 
333
 
334
+ return true;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
335
  }
checks/admin_menu.php DELETED
@@ -1,73 +0,0 @@
1
- <?php
2
- class AdminMenu implements themecheck {
3
- protected $error = array();
4
-
5
- function check( $php_files, $css_files, $other_files) {
6
-
7
- $ret = true;
8
-
9
-
10
- //check for levels deprecated in 2.0 in creating menus.
11
-
12
- $checks = array(
13
- '/([^_](add_(admin|submenu|menu|dashboard|posts|media|links|pages|comments|theme|plugins|users|management|options)_page)\s?\([^,]*,[^,]*,\s[\'|"]?(level_[0-9]|[0-9])[^;|\r|\r\n]*)/' => __( 'User levels were deprecated in <strong>2.0</strong>. Please see <a href="https://wordpress.org/support/article/roles-and-capabilities/">Roles_and_Capabilities</a>', 'theme-check' ),
14
- '/[^a-z0-9](current_user_can\s?\(\s?[\'\"]level_[0-9][\'\"]\s?\))[^\r|\r\n]*/' => __( 'User levels were deprecated in <strong>2.0</strong>. Please see <a href="https://wordpress.org/support/article/roles-and-capabilities/">Roles_and_Capabilities</a>', 'theme-check' )
15
- );
16
-
17
- foreach ( $php_files as $php_key => $phpfile ) {
18
- foreach ( $checks as $key => $check ) {
19
- checkcount();
20
- if ( preg_match( $key, $phpfile, $matches ) ) {
21
- $filename = tc_filename( $php_key );
22
- $grep = ( isset( $matches[2] ) ) ? tc_grep( $matches[2], $php_key ) : tc_grep( $matches[1], $php_key );
23
- $this->error[] = sprintf('<span class="tc-lead tc-warning">'.__( 'WARNING', 'theme-check' ) . '</span>: <strong>%1$s</strong>. %2$s%3$s', $filename, $check, $grep );
24
- $ret = false;
25
- }
26
- }
27
- }
28
-
29
-
30
- // check for add_admin_page's, except for add_theme_page
31
- // Note to TGMPA: Stop trying to bypass theme check.
32
-
33
- $checks = array(
34
- '/(?<!function)[^_>:](add_[^_\'",();]+?_page)/' => _x(
35
- 'Themes must not use <strong>%s()</strong>.',
36
- 'function name',
37
- 'theme-check'
38
- )
39
- );
40
-
41
-
42
- foreach ( $php_files as $php_key => $phpfile ) {
43
- foreach ( $checks as $key => $check ) {
44
- checkcount();
45
- if ( preg_match_all( $key, $phpfile, $matches ) ) {
46
- foreach ($matches[1] as $match) {
47
- if ( in_array( $match, array( 'add_theme_page', 'add_menu_page', 'add_submenu_page' ), true ) ) {
48
- continue;
49
- }
50
- $filename = tc_filename( $php_key );
51
- $error = ltrim( rtrim( $match, '(' ) );
52
- $grep = tc_grep( $error, $php_key );
53
- $notallowed = sprintf( $check, $match );
54
-
55
- $this->error[] = sprintf(
56
- '<span class="tc-lead tc-required">'.__( 'REQUIRED', 'theme-check' ) .'</span>: <strong>%1$s</strong>. %2$s%3$s%',
57
- $filename,
58
- $notallowed,
59
- $grep
60
- );
61
- $ret = false;
62
- }
63
- }
64
- }
65
- }
66
-
67
- return $ret;
68
- }
69
-
70
- function getError() { return $this->error; }
71
- }
72
-
73
- $themechecks[] = new AdminMenu;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
checks/adminbar.php DELETED
@@ -1,55 +0,0 @@
1
- <?php
2
- /**
3
- * This checks if the admin bar gets hidden by the theme.
4
- **/
5
- class NoHiddenAdminBar implements themecheck {
6
- protected $error = array();
7
-
8
- function check( $php_files, $css_files, $other_files ) {
9
- $ret = true;
10
-
11
- $php_regex = "/(add_filter(\s*)\((\s*)(\"|')show_admin_bar(\"|')(\s*)(.*))|(([^\S])show_admin_bar(\s*)\((.*))/";
12
- $css_regex = "/(#wpadminbar)/";
13
-
14
- checkcount();
15
- // Check php files for filter show_admin_bar, show_admin_bar_front, and show_admin_bar().
16
- foreach ( $php_files as $file_path => $file_content ) {
17
-
18
- $filename = tc_filename( $file_path );
19
-
20
- if ( preg_match( $php_regex, $file_content, $matches ) ) {
21
-
22
- $error = '/show_admin_bar/';
23
- $grep = tc_preg( $error, $file_path );
24
-
25
- $this->error[] = sprintf( '<span class="tc-lead tc-warning">' . __( 'WARNING', 'theme-check' ) . '</span>: ' . __( '%1$s Themes are not allowed to hide the admin bar. This warning must be manually checked.', 'theme-check' ),
26
- '<strong>' . $filename . '</strong>' ) . $grep;
27
- }
28
- }
29
-
30
- checkcount();
31
- // Check CSS Files for #wpadminbar.
32
- foreach ( $css_files as $file_path => $file_content ) {
33
-
34
- $filename = tc_filename( $file_path );
35
- $error = '/#wpadminbar/';
36
- // Don't print minified files.
37
- if ( strpos( $filename, '.min.' ) === false ) {
38
- $grep = tc_preg( $error, $file_path );
39
- } else {
40
- $grep = '';
41
- }
42
-
43
- if ( preg_match( $css_regex, $file_content, $matches ) ) {
44
- $this->error[] = sprintf( '<span class="tc-lead tc-warning">' . __( 'WARNING', 'theme-check' ) . '</span>: ' . __( 'The theme is using `#wpadminbar` in %1$s. Hiding the admin bar is not allowed. This warning must be manually checked.', 'theme-check' ),
45
- '<strong>' . $filename . '</strong>' ) . $grep;
46
- }
47
- }
48
-
49
- return $ret;
50
- }
51
-
52
- function getError() { return $this->error; }
53
- }
54
-
55
- $themechecks[] = new NoHiddenAdminBar();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
checks/badthings.php DELETED
@@ -1,60 +0,0 @@
1
- <?php
2
- class Bad_Checks implements themecheck {
3
- protected $error = array();
4
-
5
- function check( $php_files, $css_files, $other_files ) {
6
- $ret = true;
7
-
8
- $checks = array(
9
- '/(?<![_|a-z0-9|\.])eval\s?\(/i' => __( 'eval() is not allowed.', 'theme-check' ),
10
- '/[^a-z0-9](?<!_)(popen|proc_open|[^_]exec|shell_exec|system|passthru)\(/' => __( 'PHP system calls are often disabled by server admins and should not be in themes', 'theme-check' ),
11
- '/\s?ini_set\(/' => __( 'Themes should not change server PHP settings', 'theme-check' ),
12
- '/base64_decode/' => __( 'base64_decode() is not allowed', 'theme-check' ),
13
- '/base64_encode/' => __( 'base64_encode() is not allowed', 'theme-check' ),
14
- '/uudecode/ims' => __( 'uudecode() is not allowed', 'theme-check' ),
15
- '/str_rot13/ims' => __( 'str_rot13() is not allowed', 'theme-check' ),
16
- '/cx=[0-9]{21}:[a-z0-9]{10}/' => __( 'Google search code detected', 'theme-check' ),
17
- '/pub-[0-9]{16}/i' => __( 'Google advertising code detected', 'theme-check' ),
18
- '/sharesale/i' => __( 'Sharesale affiliate link detected', 'theme-check' ),
19
- '/affiliate_id/i' => __( 'Potential affiliate link detected', 'theme-check' ),
20
- '/(elementor_partner_id)|(wpbeaverbuilder.*?fla)/i' => __( 'Potential affiliate link detected', 'theme-check' ),
21
- );
22
-
23
- $grep = '';
24
-
25
- foreach ( $php_files as $php_key => $phpfile ) {
26
- foreach ( $checks as $key => $check ) {
27
- checkcount();
28
- if ( preg_match( $key, $phpfile, $matches ) ) {
29
- $filename = tc_filename( $php_key );
30
- $error = ltrim( trim( $matches[0], '(' ) );
31
- $grep = tc_grep( $error, $php_key );
32
- $this->error[] = sprintf('<span class="tc-lead tc-required">'. __( 'REQUIRED', 'theme-check' ) . '</span>: ' . __( 'Found %1$s in the file %2$s. %3$s. %4$s', 'theme-check' ), '<strong>' . $error . '</strong>', '<strong>' . $filename . '</strong>', $check, $grep );
33
- $ret = false;
34
- }
35
- }
36
- }
37
-
38
-
39
- $checks = array(
40
- '/cx=[0-9]{21}:[a-z0-9]{10}/' => __( 'Google search code detected', 'theme-check' ),
41
- '/pub-[0-9]{16}/' => __( 'Google advertising code detected', 'theme-check' )
42
- );
43
-
44
- foreach ( $other_files as $php_key => $phpfile ) {
45
- foreach ( $checks as $key => $check ) {
46
- checkcount();
47
- if ( preg_match( $key, $phpfile, $matches ) ) {
48
- $filename = tc_filename( $php_key );
49
- $error = ltrim( rtrim( $matches[0],'(' ) );
50
- $grep = tc_grep( $error, $php_key );
51
- $this->error[] = sprintf(__('<span class="tc-lead tc-required">REQUIRED</span>: Found <strong>%1$s</strong> in the file <strong>%2$s</strong>. %3$s.%4$s', 'theme-check'), $error, $filename, $check, $grep);
52
- $ret = false;
53
- }
54
- }
55
- }
56
- return $ret;
57
- }
58
- function getError() { return $this->error; }
59
- }
60
- $themechecks[] = new Bad_Checks;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
checks/basic.php DELETED
@@ -1,47 +0,0 @@
1
- <?php
2
-
3
- // do some basic checks for strings
4
- class Basic_Checks implements themecheck {
5
- protected $error = array();
6
-
7
- function check( $php_files, $css_files, $other_files) {
8
-
9
- $php = implode( ' ', $php_files );
10
- $grep = '';
11
- $ret = true;
12
-
13
- $checks = array(
14
- 'DOCTYPE' => __( 'See: <a href="https://codex.wordpress.org/HTML_to_XHTML">https://codex.wordpress.org/HTML_to_XHTML</a><pre>&lt;!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"<br />"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"?&gt;</pre>', 'theme-check' ),
15
- '(wp_body_open\s*\()|(do_action\s*\(\s*["\']wp_body_open)' => __( 'See: <a href="https://developer.wordpress.org/reference/functions/wp_body_open/">wp_body_open</a><pre> &lt;?php wp_body_open(); ?&gt;</pre>', 'theme-check' ),
16
- 'wp_footer\s*\(' => __( 'See: <a href="https://developer.wordpress.org/reference/functions/wp_footer/">wp_footer</a><pre> &lt;?php wp_footer(); ?&gt;</pre>', 'theme-check' ),
17
- 'wp_head\s*\(' => __( 'See: <a href="https://developer.wordpress.org/reference/functions/wp_head/">wp_head</a><pre> &lt;?php wp_head(); ?&gt;</pre>', 'theme-check' ),
18
- 'language_attributes' => __( 'See: <a href="https://developer.wordpress.org/reference/functions/language_attributes/">language_attributes</a><pre>&lt;html &lt;?php language_attributes(); ?&gt;</pre>', 'theme-check' ),
19
- 'charset' => __( 'There must be a charset defined in the Content-Type or the meta charset tag in the head.', 'theme-check' ),
20
- 'add_theme_support\s*\(\s?("|\')automatic-feed-links("|\')\s?\)' => __( 'See: <a href="https://developer.wordpress.org/reference/functions/add_theme_support/">add_theme_support</a><pre> &lt;?php add_theme_support( $feature ); ?&gt;</pre>', 'theme-check' ),
21
- 'comments_template\s*\(' => __( 'See: <a href="https://developer.wordpress.org/reference/functions/comments_template/">comments_template</a><pre> &lt;?php comments_template( $file, $separate_comments ); ?&gt;</pre>', 'theme-check' ),
22
- 'wp_list_comments\s*\(' => __( 'See: <a href="https://developer.wordpress.org/reference/functions/wp_list_comments/">wp_list_comments</a><pre> &lt;?php wp_list_comments( $args ); ?&gt;</pre>', 'theme-check' ),
23
- 'comment_form\s*\(' => __( 'See: <a href="https://developer.wordpress.org/reference/functions/comment_form/">comment_form</a><pre> &lt;?php comment_form(); ?&gt;</pre>', 'theme-check' ),
24
- 'body_class\s*\(' => __( 'See: <a href="https://developer.wordpress.org/reference/functions/body_class/">body_class</a><pre> &lt;?php body_class( $class ); ?&gt;</pre>', 'theme-check' ),
25
- 'wp_link_pages\s*\(' => __( 'See: <a href="https://developer.wordpress.org/reference/functions/wp_link_pages/">wp_link_pages</a><pre> &lt;?php wp_link_pages( $args ); ?&gt;</pre>', 'theme-check' ),
26
- 'post_class\s*\(' => __( 'See: <a href="https://developer.wordpress.org/reference/functions/post_class/">post_class</a><pre> &lt;div id="post-&lt;?php the_ID(); ?&gt;" &lt;?php post_class(); ?&gt;&gt;</pre>', 'theme-check' )
27
- );
28
-
29
- foreach ($checks as $key => $check) {
30
- checkcount();
31
- if ( !preg_match( '/' . $key . '/i', $php ) ) {
32
- if ( $key === 'add_theme_support\s*\(\s?("|\')automatic-feed-links("|\')\s?\)' ) $key = __( 'add_theme_support( \'automatic-feed-links\' )', 'theme-check');
33
- if ( $key === 'body_class\s*\(' ) $key = __( 'body_class call in body tag', 'theme-check');
34
- if ( $key === '(wp_body_open\s*\()|(do_action\s*\(\s*["\']wp_body_open)' ) $key = __( 'wp_body_open action or function call at the very top of the body just after the opening body tag', 'theme-check');
35
- $key = str_replace( '\s*\(', '', $key );
36
- $this->error[] = sprintf( '<span class="tc-lead tc-required">'.__('REQUIRED','theme-check').'</span>: '.__('Could not find %1$s. %2$s', 'theme-check' ), '<strong>' . $key . '</strong>', $check );
37
- $ret = false;
38
- }
39
- }
40
-
41
- return $ret;
42
- }
43
-
44
- function getError() { return $this->error; }
45
- }
46
-
47
- $themechecks[] = new Basic_Checks;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
checks/cdn.php DELETED
@@ -1,45 +0,0 @@
1
- <?php
2
- /**
3
- * Checks for resources being loaded from CDNs.
4
- */
5
-
6
- class CDNCheck implements themecheck {
7
- protected $error = array();
8
-
9
- function check( $php_files, $css_files, $other_files) {
10
-
11
- $ret = true;
12
- $php_code = implode( ' ', $php_files );
13
- $css_code = implode( ' ', $css_files );
14
- $all_code = $php_code . ' ' . $css_code;
15
-
16
- checkcount();
17
-
18
- $cdn_list = array(
19
- 'bootstrap-maxcdn' => 'maxcdn.bootstrapcdn.com',
20
- 'bootstrap-netdna' => 'netdna.bootstrapcdn.com',
21
- 'bootstrap-stackpath' => 'stackpath.bootstrapcdn.com',
22
- 'fontawesome' => 'kit.fontawesome.com',
23
- 'googlecode' => 'googlecode.com/svn/',
24
- 'oss.maxcdn' => 'oss.maxcdn.com',
25
- 'jquery' => 'code.jquery.com/jquery-',
26
- 'aspnetcdn' => 'aspnetcdn.com',
27
- 'cloudflare' => 'cloudflare.com',
28
- 'keycdn' => 'keycdn.com',
29
- 'pxgcdn' => 'pxgcdn.com',
30
- 'vimeocdn' => 'vimeocdn.com', //usually in JS files
31
- );
32
-
33
- foreach( $cdn_list as $cdn_slug => $cdn_url ) {
34
- if ( false !== strpos( $all_code, $cdn_url ) ) {
35
- $this->error[] = '<span class="tc-lead tc-required">' . __( 'REQUIRED','theme-check' ) . '</span>: ' . sprintf( __( 'Found the URL of a CDN in the code: %s. You should not load CSS or Javascript resources from a CDN, please bundle them with the theme.', 'theme-check' ), '<code>' . esc_html( $cdn_url ) . '</code>' );
36
- $ret = false;
37
- }
38
- }
39
-
40
- return $ret;
41
- }
42
-
43
- function getError() { return $this->error; }
44
- }
45
- $themechecks[] = new CDNCheck;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
checks/class-admin-menu-check.php ADDED
@@ -0,0 +1,107 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Check for creation of admin menus
4
+ *
5
+ * Checks that user levels are not used when creating admin menus.
6
+ * Checks that only add_theme_page, add_menu_page and add_submenu_page are used to create admin menus.
7
+ *
8
+ * @package Theme Check
9
+ */
10
+
11
+ /**
12
+ * Check for creation of admin menus.
13
+ *
14
+ * Checks that user levels are not used when creating admin menus.
15
+ * Checks that only add_theme_page, add_menu_page and add_submenu_page are used to create admin menus.
16
+ */
17
+ class Admin_Menu_Check implements themecheck {
18
+ /**
19
+ * Error messages, warnings and info notices.
20
+ *
21
+ * @var array $error
22
+ */
23
+ protected $error = array();
24
+
25
+ /**
26
+ * Check that return true for good/okay/acceptable, false for bad/not-okay/unacceptable.
27
+ *
28
+ * @param array $php_files File paths and content for PHP files.
29
+ * @param array $css_files File paths and content for CSS files.
30
+ * @param array $other_files Folder names, file paths and content for other files.
31
+ */
32
+ public function check( $php_files, $css_files, $other_files ) {
33
+
34
+ $ret = true;
35
+
36
+ // Check for levels deprecated in 2.0 in creating menus.
37
+ $checks = array(
38
+ '/([^_](add_(admin|submenu|menu|dashboard|posts|media|links|pages|comments|theme|plugins|users|management|options)_page)\s?\([^,]*,[^,]*,\s[\'|"]?(level_[0-9]|[0-9])[^;|\r|\r\n]*)/' => __( 'User levels were deprecated in <strong>2.0</strong>. Please see <a href="https://wordpress.org/support/article/roles-and-capabilities/">Roles and Capabilities</a>', 'theme-check' ),
39
+ '/[^a-z0-9](current_user_can\s?\(\s?[\'\"]level_[0-9][\'\"]\s?\))[^\r|\r\n]*/' => __( 'User levels were deprecated in <strong>2.0</strong>. Please see <a href="https://wordpress.org/support/article/roles-and-capabilities/">Roles and Capabilities</a>', 'theme-check' ),
40
+ );
41
+
42
+ foreach ( $php_files as $php_key => $phpfile ) {
43
+ foreach ( $checks as $key => $check ) {
44
+ checkcount();
45
+ if ( preg_match( $key, $phpfile, $matches ) ) {
46
+ $filename = tc_filename( $php_key );
47
+ $grep = tc_grep( isset( $matches[2] ) ? $matches[2] : $matches[1], $php_key );
48
+ $this->error[] = sprintf(
49
+ '<span class="tc-lead tc-warning">%s</span>: <strong>%s</strong>. %s %s',
50
+ __( 'WARNING', 'theme-check' ),
51
+ $filename,
52
+ $check,
53
+ $grep
54
+ );
55
+ }
56
+ }
57
+ }
58
+
59
+ // Check for add_admin_page's, except for add_theme_page.
60
+ // Note to TGMPA: Stop trying to bypass theme check.
61
+ $checks = array(
62
+ '/(?<!function)[^_>:](add_[a-z]+_page)/' => _x(
63
+ 'Themes should not use <strong>%s()</strong>.',
64
+ 'function name',
65
+ 'theme-check'
66
+ ),
67
+ );
68
+
69
+ foreach ( $php_files as $php_key => $phpfile ) {
70
+ foreach ( $checks as $key => $check ) {
71
+ checkcount();
72
+ if ( preg_match_all( $key, $phpfile, $matches ) ) {
73
+ foreach ( $matches[1] as $match ) {
74
+ if ( in_array( $match, array( 'add_theme_page', 'add_menu_page', 'add_submenu_page' ), true ) ) {
75
+ continue;
76
+ }
77
+ $filename = tc_filename( $php_key );
78
+ $error = ltrim( rtrim( $match, '(' ) );
79
+ $grep = tc_grep( $error, $php_key );
80
+ $notallowed = sprintf( $check, $match );
81
+
82
+ $this->error[] = sprintf(
83
+ '<span class="tc-lead tc-recommended">%s</span>: <strong>%s</strong>. %s %s',
84
+ __( 'RECOMMENDED', 'theme-check' ),
85
+ $filename,
86
+ $notallowed,
87
+ $grep
88
+ );
89
+ }
90
+ }
91
+ }
92
+ }
93
+
94
+ return true;
95
+ }
96
+
97
+ /**
98
+ * Get error messages from the checks.
99
+ *
100
+ * @return array Error message.
101
+ */
102
+ public function getError() {
103
+ return $this->error;
104
+ }
105
+ }
106
+
107
+ $themechecks[] = new Admin_Menu_Check();
checks/class-bad-things-check.php ADDED
@@ -0,0 +1,114 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Check for code that is not allowed
4
+ *
5
+ * Checks for code that is not allowed, server settings, and affiliate links.
6
+ *
7
+ * @package Theme Check
8
+ */
9
+
10
+ /**
11
+ * Check for code that is not allowed.
12
+ *
13
+ * Checks for code that is not allowed, server settings, and affiliate links.
14
+ */
15
+ class Bad_Things_Check implements themecheck {
16
+ /**
17
+ * Error messages, warnings and info notices.
18
+ *
19
+ * @var array $error
20
+ */
21
+ protected $error = array();
22
+
23
+ /**
24
+ * Check that return true for good/okay/acceptable, false for bad/not-okay/unacceptable.
25
+ *
26
+ * @param array $php_files File paths and content for PHP files.
27
+ * @param array $css_files File paths and content for CSS files.
28
+ * @param array $other_files Folder names, file paths and content for other files.
29
+ */
30
+ public function check( $php_files, $css_files, $other_files ) {
31
+ $ret = true;
32
+
33
+ $checks = array(
34
+ '/(?<![_|a-z0-9|\.])eval\s?\(/i' => __( 'eval() is not allowed.', 'theme-check' ),
35
+ '/[^a-z0-9](?<!_)(popen|proc_open|[^_]exec|shell_exec|system|passthru)\(/' => __( 'PHP system calls are often disabled by server admins and should not be in themes', 'theme-check' ),
36
+ '/\s?ini_set\(/' => __( 'Themes should not change server PHP settings', 'theme-check' ),
37
+ '/base64_decode/' => __( 'base64_decode() is not allowed', 'theme-check' ),
38
+ '/base64_encode/' => __( 'base64_encode() is not allowed', 'theme-check' ),
39
+ '/uudecode/ims' => __( 'uudecode() is not allowed', 'theme-check' ),
40
+ '/str_rot13/ims' => __( 'str_rot13() is not allowed', 'theme-check' ),
41
+ '/cx=[0-9]{21}:[a-z0-9]{10}/' => __( 'Google search code detected', 'theme-check' ),
42
+ '/pub-[0-9]{16}/i' => __( 'Google advertising code detected', 'theme-check' ),
43
+ '/sharesale/i' => __( 'Sharesale affiliate link detected', 'theme-check' ),
44
+ '/affiliate_id/i' => __( 'Potential affiliate link detected', 'theme-check' ),
45
+ '/(elementor_partner_id)|(wpbeaverbuilder.*?fla)/i' => __( 'Potential affiliate link detected', 'theme-check' ),
46
+ );
47
+
48
+ $grep = '';
49
+
50
+ foreach ( $php_files as $php_key => $phpfile ) {
51
+ foreach ( $checks as $key => $check ) {
52
+ checkcount();
53
+ if ( preg_match( $key, $phpfile, $matches ) ) {
54
+ $filename = tc_filename( $php_key );
55
+ $error = ltrim( trim( $matches[0], '(' ) );
56
+ $grep = tc_grep( $error, $php_key );
57
+ $this->error[] = sprintf(
58
+ '<span class="tc-lead tc-required">%s</span>: %s %s %s',
59
+ __( 'REQUIRED', 'theme-check' ),
60
+ sprintf(
61
+ __( 'Found %1$s in the file %2$s.', 'theme-check' ),
62
+ '<strong>' . $error . '</strong>',
63
+ '<strong>' . $filename . '</strong>'
64
+ ),
65
+ $check,
66
+ $grep
67
+ );
68
+ $ret = false;
69
+ }
70
+ }
71
+ }
72
+
73
+ $checks = array(
74
+ '/cx=[0-9]{21}:[a-z0-9]{10}/' => __( 'Google search code detected', 'theme-check' ),
75
+ '/pub-[0-9]{16}/i' => __( 'Google advertising code detected', 'theme-check' ),
76
+ );
77
+
78
+ foreach ( $other_files as $php_key => $phpfile ) {
79
+ foreach ( $checks as $key => $check ) {
80
+ checkcount();
81
+ if ( preg_match( $key, $phpfile, $matches ) ) {
82
+ $filename = tc_filename( $php_key );
83
+ $error = ltrim( rtrim( $matches[0], '(' ) );
84
+ $grep = tc_grep( $error, $php_key );
85
+ $this->error[] = sprintf(
86
+ '<span class="tc-lead tc-required">%s</span>: %s %s %s',
87
+ __( 'REQUIRED', 'theme-check' ),
88
+ sprintf(
89
+ __( 'Found <strong>%1$s</strong> in the file <strong>%2$s</strong>.', 'theme-check' ),
90
+ $error,
91
+ $filename
92
+ ),
93
+ $check,
94
+ $grep
95
+ );
96
+ $ret = false;
97
+ }
98
+ }
99
+ }
100
+
101
+ return $ret;
102
+ }
103
+
104
+ /**
105
+ * Get error messages from the checks.
106
+ *
107
+ * @return array Error message.
108
+ */
109
+ public function getError() {
110
+ return $this->error;
111
+ }
112
+ }
113
+
114
+ $themechecks[] = new Bad_Things_Check();
checks/class-basic-check.php ADDED
@@ -0,0 +1,84 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Check for basic functions needed for classic themes to work correctly
4
+ *
5
+ * @package Theme Check
6
+ */
7
+
8
+ /**
9
+ * Check for basic functions needed for classic themes to work correctly.
10
+ */
11
+ class Basic_Check implements themecheck {
12
+ /**
13
+ * Error messages, warnings and info notices.
14
+ *
15
+ * @var array $error
16
+ */
17
+ protected $error = array();
18
+
19
+ /**
20
+ * Check that return true for good/okay/acceptable, false for bad/not-okay/unacceptable.
21
+ *
22
+ * @param array $php_files File paths and content for PHP files.
23
+ * @param array $css_files File paths and content for CSS files.
24
+ * @param array $other_files Folder names, file paths and content for other files.
25
+ */
26
+ public function check( $php_files, $css_files, $other_files ) {
27
+
28
+ $php = implode( ' ', $php_files );
29
+ $grep = '';
30
+ $ret = true;
31
+
32
+ $checks = array(
33
+ 'DOCTYPE' => __( 'See: <a href="https://codex.wordpress.org/HTML_to_XHTML">https://codex.wordpress.org/HTML_to_XHTML</a><pre>&lt;!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"<br />"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"?&gt;</pre>', 'theme-check' ),
34
+ '(wp_body_open\s*\()|(do_action\s*\(\s*["\']wp_body_open)' => __( 'See: <a href="https://developer.wordpress.org/reference/functions/wp_body_open/">wp_body_open</a><pre> &lt;?php wp_body_open(); ?&gt;</pre>', 'theme-check' ),
35
+ 'wp_footer\s*\(' => __( 'See: <a href="https://developer.wordpress.org/reference/functions/wp_footer/">wp_footer</a><pre> &lt;?php wp_footer(); ?&gt;</pre>', 'theme-check' ),
36
+ 'wp_head\s*\(' => __( 'See: <a href="https://developer.wordpress.org/reference/functions/wp_head/">wp_head</a><pre> &lt;?php wp_head(); ?&gt;</pre>', 'theme-check' ),
37
+ 'language_attributes' => __( 'See: <a href="https://developer.wordpress.org/reference/functions/language_attributes/">language_attributes</a><pre>&lt;html &lt;?php language_attributes(); ?&gt;</pre>', 'theme-check' ),
38
+ 'charset' => __( 'There must be a charset defined in the Content-Type or the meta charset tag in the head.', 'theme-check' ),
39
+ 'add_theme_support\s*\(\s?("|\')automatic-feed-links("|\')\s?\)' => __( 'See: <a href="https://developer.wordpress.org/reference/functions/add_theme_support/">add_theme_support</a><pre> &lt;?php add_theme_support( $feature ); ?&gt;</pre>', 'theme-check' ),
40
+ 'body_class\s*\(' => __( 'See: <a href="https://developer.wordpress.org/reference/functions/body_class/">body_class</a><pre> &lt;?php body_class( $class ); ?&gt;</pre>', 'theme-check' ),
41
+ 'wp_link_pages\s*\(' => __( 'See: <a href="https://developer.wordpress.org/reference/functions/wp_link_pages/">wp_link_pages</a><pre> &lt;?php wp_link_pages( $args ); ?&gt;</pre>', 'theme-check' ),
42
+ 'post_class\s*\(' => __( 'See: <a href="https://developer.wordpress.org/reference/functions/post_class/">post_class</a><pre> &lt;div id="post-&lt;?php the_ID(); ?&gt;" &lt;?php post_class(); ?&gt;&gt;</pre>', 'theme-check' ),
43
+ );
44
+
45
+ foreach ( $checks as $key => $check ) {
46
+ checkcount();
47
+ if ( ! preg_match( '/' . $key . '/i', $php ) ) {
48
+ if ( $key === 'add_theme_support\s*\(\s?("|\')automatic-feed-links("|\')\s?\)' ) {
49
+ $key = __( 'add_theme_support( \'automatic-feed-links\' )', 'theme-check' );
50
+ }
51
+ if ( $key === 'body_class\s*\(' ) {
52
+ $key = __( 'body_class call in body tag', 'theme-check' );
53
+ }
54
+ if ( $key === '(wp_body_open\s*\()|(do_action\s*\(\s*["\']wp_body_open)' ) {
55
+ $key = __( 'wp_body_open action or function call at the very top of the body just after the opening body tag', 'theme-check' );
56
+ }
57
+ $key = str_replace( '\s*\(', '', $key );
58
+ $this->error[] = sprintf(
59
+ '<span class="tc-lead tc-required">%s</span>: %s',
60
+ __( 'REQUIRED', 'theme-check' ),
61
+ sprintf(
62
+ __( 'Could not find %1$s. %2$s', 'theme-check' ),
63
+ '<strong>' . $key . '</strong>',
64
+ $check
65
+ )
66
+ );
67
+ $ret = false;
68
+ }
69
+ }
70
+
71
+ return $ret;
72
+ }
73
+
74
+ /**
75
+ * Get error messages from the checks.
76
+ *
77
+ * @return array Error message.
78
+ */
79
+ public function getError() {
80
+ return $this->error;
81
+ }
82
+ }
83
+
84
+ $themechecks[] = new Basic_Check();
checks/class-block-patterns-check.php ADDED
@@ -0,0 +1,62 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Check if block patterns and block styles are included
4
+ *
5
+ * @package Theme Check
6
+ */
7
+
8
+ /**
9
+ * Check if block patterns and block styles are included.
10
+ *
11
+ * Check if block patterns and block styles are included, if not, recommend it.
12
+ */
13
+ class Block_Patterns_Check implements themecheck {
14
+ /**
15
+ * Error messages, warnings and info notices.
16
+ *
17
+ * @var array $error
18
+ */
19
+ protected $error = array();
20
+
21
+ /**
22
+ * Check that return true for good/okay/acceptable, false for bad/not-okay/unacceptable.
23
+ *
24
+ * @param array $php_files File paths and content for PHP files.
25
+ * @param array $css_files File paths and content for CSS files.
26
+ * @param array $other_files Folder names, file paths and content for other files.
27
+ */
28
+ public function check( $php_files, $css_files, $other_files ) {
29
+ checkcount();
30
+
31
+ $php = implode( ' ', $php_files );
32
+
33
+ if ( strpos( $php, 'register_block_pattern' ) === false ) {
34
+ $this->error[] = sprintf(
35
+ '<span class="tc-lead tc-recommended">%s</span>: %s',
36
+ __( 'RECOMMENDED', 'theme-check' ),
37
+ __( 'No reference to <strong>register_block_pattern</strong> was found in the theme. Theme authors are encouraged to implement custom block patterns as a transition to block themes.', 'theme-check' )
38
+ );
39
+ }
40
+
41
+ if ( strpos( $php, 'register_block_style' ) === false ) {
42
+ $this->error[] = sprintf(
43
+ '<span class="tc-lead tc-recommended">%s</span>: %s',
44
+ __( 'RECOMMENDED', 'theme-check' ),
45
+ __( 'No reference to <strong>register_block_style</strong> was found in the theme. Theme authors are encouraged to implement new block styles as a transition to block themes.', 'theme-check' )
46
+ );
47
+ }
48
+
49
+ return true;
50
+ }
51
+
52
+ /**
53
+ * Get error messages from the checks.
54
+ *
55
+ * @return array Error message.
56
+ */
57
+ public function getError() {
58
+ return $this->error;
59
+ }
60
+ }
61
+
62
+ $themechecks[] = new Block_Patterns_Check();
checks/class-cdn-check.php ADDED
@@ -0,0 +1,79 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Checks for resources being loaded from CDNs.
4
+ *
5
+ * @package Theme Check
6
+ */
7
+
8
+ /**
9
+ * Checks for resources being loaded from CDNs.
10
+ *
11
+ * Checks for resources being loaded from CDNs. Usage of CDN is required to be removed.
12
+ */
13
+ class CDN_Check implements themecheck {
14
+ /**
15
+ * Error messages, warnings and info notices.
16
+ *
17
+ * @var array $error
18
+ */
19
+ protected $error = array();
20
+
21
+ /**
22
+ * Check that return true for good/okay/acceptable, false for bad/not-okay/unacceptable.
23
+ *
24
+ * @param array $php_files File paths and content for PHP files.
25
+ * @param array $css_files File paths and content for CSS files.
26
+ * @param array $other_files Folder names, file paths and content for other files.
27
+ */
28
+ public function check( $php_files, $css_files, $other_files ) {
29
+
30
+ $ret = true;
31
+ $php_code = implode( ' ', $php_files );
32
+ $css_code = implode( ' ', $css_files );
33
+ $all_code = $php_code . ' ' . $css_code;
34
+
35
+ checkcount();
36
+
37
+ $cdn_list = array(
38
+ 'bootstrap-maxcdn' => 'maxcdn.bootstrapcdn.com',
39
+ 'bootstrap-netdna' => 'netdna.bootstrapcdn.com',
40
+ 'bootstrap-stackpath' => 'stackpath.bootstrapcdn.com',
41
+ 'fontawesome' => 'kit.fontawesome.com',
42
+ 'googlecode' => 'googlecode.com/svn/',
43
+ 'oss.maxcdn' => 'oss.maxcdn.com',
44
+ 'jquery' => 'code.jquery.com/jquery-',
45
+ 'aspnetcdn' => 'aspnetcdn.com',
46
+ 'cloudflare' => 'cloudflare.com',
47
+ 'keycdn' => 'keycdn.com',
48
+ 'pxgcdn' => 'pxgcdn.com',
49
+ 'vimeocdn' => 'vimeocdn.com', // Usually in JS files.
50
+ );
51
+
52
+ foreach ( $cdn_list as $cdn_slug => $cdn_url ) {
53
+ if ( false !== strpos( $all_code, $cdn_url ) ) {
54
+ $this->error[] = sprintf(
55
+ '<span class="tc-lead tc-required">%s</span>: %s',
56
+ __( 'REQUIRED', 'theme-check' ),
57
+ sprintf(
58
+ __( 'Found the URL of a CDN in the code: %s. You should not load CSS or Javascript resources from a CDN, please bundle them with the theme.', 'theme-check' ),
59
+ '<code>' . esc_html( $cdn_url ) . '</code>'
60
+ )
61
+ );
62
+ $ret = false;
63
+ }
64
+ }
65
+
66
+ return $ret;
67
+ }
68
+
69
+ /**
70
+ * Get error messages from the checks.
71
+ *
72
+ * @return array Error message.
73
+ */
74
+ public function getError() {
75
+ return $this->error;
76
+ }
77
+ }
78
+
79
+ $themechecks[] = new CDN_Check();
checks/class-comment-pagination-check.php ADDED
@@ -0,0 +1,62 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Checks if comment pagination is included
4
+ *
5
+ * @package Theme Check
6
+ */
7
+
8
+ /**
9
+ * Checks if comment pagination is included.
10
+ *
11
+ * Checks if comment pagination is included. If not, recommend it.
12
+ */
13
+ class Comment_Pagination_Check implements themecheck {
14
+ /**
15
+ * Error messages, warnings and info notices.
16
+ *
17
+ * @var array $error
18
+ */
19
+ protected $error = array();
20
+
21
+ /**
22
+ * Check that return true for good/okay/acceptable, false for bad/not-okay/unacceptable.
23
+ *
24
+ * @param array $php_files File paths and content for PHP files.
25
+ * @param array $css_files File paths and content for CSS files.
26
+ * @param array $other_files Folder names, file paths and content for other files.
27
+ */
28
+ public function check( $php_files, $css_files, $other_files ) {
29
+
30
+ // Combine all the php files into one string to make it easier to search.
31
+ $php = implode( ' ', $php_files );
32
+
33
+ checkcount();
34
+
35
+ if (
36
+ strpos( $php, 'paginate_comments_links' ) === false &&
37
+ strpos( $php, 'the_comments_navigation' ) === false &&
38
+ strpos( $php, 'the_comments_pagination' ) === false &&
39
+ strpos( $php, 'next_comments_link' ) === false &&
40
+ strpos( $php, 'previous_comments_link' ) === false
41
+ ) {
42
+ $this->error[] = sprintf(
43
+ '<span class="tc-lead tc-recommended">%s</span>: %s',
44
+ __( 'RECOMMENDED', 'theme-check' ),
45
+ __( "The theme doesn't have comment pagination code in it. Use <strong>paginate_comments_links()</strong> or <strong>the_comments_navigation</strong> or <strong>the_comments_pagination</strong> or <strong>next_comments_link()</strong> and <strong>previous_comments_link()</strong> to add comment pagination.", 'theme-check' )
46
+ );
47
+ }
48
+
49
+ return true;
50
+ }
51
+
52
+ /**
53
+ * Get error messages from the checks.
54
+ *
55
+ * @return array Error message.
56
+ */
57
+ public function getError() {
58
+ return $this->error;
59
+ }
60
+ }
61
+
62
+ $themechecks[] = new Comment_Pagination_Check();
checks/class-comment-reply-check.php ADDED
@@ -0,0 +1,63 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Checks if the comment reply script is included in classic themes
4
+ *
5
+ * @package Theme Check
6
+ */
7
+
8
+ /**
9
+ * Checks if the comment reply script is included in classic themes.
10
+ *
11
+ * Checks if the comment reply script is included. If not, recommend it.
12
+ */
13
+ class Comment_Reply_Check implements themecheck {
14
+ /**
15
+ * Error messages, warnings and info notices.
16
+ *
17
+ * @var array $error
18
+ */
19
+ protected $error = array();
20
+
21
+ /**
22
+ * Check that return true for good/okay/acceptable, false for bad/not-okay/unacceptable.
23
+ *
24
+ * @param array $php_files File paths and content for PHP files.
25
+ * @param array $css_files File paths and content for CSS files.
26
+ * @param array $other_files Folder names, file paths and content for other files.
27
+ */
28
+ public function check( $php_files, $css_files, $other_files ) {
29
+
30
+ $php = implode( ' ', $php_files );
31
+
32
+ checkcount();
33
+
34
+ if ( ! preg_match( '/wp_enqueue_script\(\s?("|\')comment-reply("|\')/i', $php ) ) {
35
+ if ( ! preg_match( '/comment-reply/', $php ) ) {
36
+ $this->error[] = sprintf(
37
+ '<span class="tc-lead tc-recommended">%s</span>: %s',
38
+ __( 'RECOMMENDED', 'theme-check' ),
39
+ __( 'Could not find the <strong>comment-reply</strong> script enqueued.', 'theme-check' )
40
+ );
41
+ } else {
42
+ $this->error[] = sprintf(
43
+ '<span class="tc-lead tc-info">%s</span>: %s',
44
+ __( 'INFO', 'theme-check' ),
45
+ __( 'Could not find the <strong>comment-reply</strong> script enqueued, however a reference to \'comment-reply\' was found. Make sure that the comment-reply script is being enqueued properly on singular pages.', 'theme-check' )
46
+ );
47
+ }
48
+ }
49
+
50
+ return true;
51
+ }
52
+
53
+ /**
54
+ * Get error messages from the checks.
55
+ *
56
+ * @return array Error message.
57
+ */
58
+ public function getError() {
59
+ return $this->error;
60
+ }
61
+ }
62
+
63
+ $themechecks[] = new Comment_Reply_Check();
checks/class-comments-check.php ADDED
@@ -0,0 +1,67 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Checks if comment templates are included in classic themes
4
+ *
5
+ * @package Theme Check
6
+ */
7
+
8
+ /**
9
+ * Checks if comment templates are included in classic themes.
10
+ *
11
+ * Checks if comment templates are included. If not, recommend them.
12
+ */
13
+ class Comments_Check implements themecheck {
14
+ /**
15
+ * Error messages, warnings and info notices.
16
+ *
17
+ * @var array $error
18
+ */
19
+ protected $error = array();
20
+
21
+ /**
22
+ * Check that return true for good/okay/acceptable, false for bad/not-okay/unacceptable.
23
+ *
24
+ * @param array $php_files File paths and content for PHP files.
25
+ * @param array $css_files File paths and content for CSS files.
26
+ * @param array $other_files Folder names, file paths and content for other files.
27
+ */
28
+ public function check( $php_files, $css_files, $other_files ) {
29
+
30
+ $php = implode( ' ', $php_files );
31
+
32
+ $checks = array(
33
+ 'comments_template\s*\(' => __( 'See: <a href="https://developer.wordpress.org/reference/functions/comments_template/">comments_template</a><pre> &lt;?php comments_template( $file, $separate_comments ); ?&gt;</pre>', 'theme-check' ),
34
+ 'wp_list_comments\s*\(' => __( 'See: <a href="https://developer.wordpress.org/reference/functions/wp_list_comments/">wp_list_comments</a><pre> &lt;?php wp_list_comments( $args ); ?&gt;</pre>', 'theme-check' ),
35
+ 'comment_form\s*\(' => __( 'See: <a href="https://developer.wordpress.org/reference/functions/comment_form/">comment_form</a><pre> &lt;?php comment_form(); ?&gt;</pre>', 'theme-check' ),
36
+ );
37
+
38
+ foreach ( $checks as $key => $check ) {
39
+ checkcount();
40
+ if ( ! preg_match( '/' . $key . '/i', $php ) ) {
41
+ $key = str_replace( '\s*\(', '', $key );
42
+ $this->error[] = sprintf(
43
+ '<span class="tc-lead tc-recommended">%s</span>: %s',
44
+ __( 'RECOMMENDED', 'theme-check' ),
45
+ sprintf(
46
+ __( 'Could not find %1$s. %2$s', 'theme-check' ),
47
+ '<strong>' . $key . '</strong>',
48
+ $check
49
+ )
50
+ );
51
+ }
52
+ }
53
+
54
+ return true;
55
+ }
56
+
57
+ /**
58
+ * Get error messages from the checks.
59
+ *
60
+ * @return array Error message.
61
+ */
62
+ public function getError() {
63
+ return $this->error;
64
+ }
65
+ }
66
+
67
+ $themechecks[] = new Comments_Check();
checks/class-constants-check.php ADDED
@@ -0,0 +1,83 @@