Theme Check - Version 20200612.1

Version Description

Download this release

Release Info

Developer Otto42
Plugin Icon 128x128 Theme Check
Version 20200612.1
Comparing to
See all releases

Code changes from version 20190801.1 to 20200612.1

assets/style.css CHANGED
@@ -1,77 +1,83 @@
1
- .tc-box {
2
- padding:20px 0;
3
- border-top:1px solid #dfdfdf;
4
- }
5
- .tc-warning, .tc-required, .tc-fail {
6
- color:red;
7
- }
8
- .tc-recommended, .tc-pass {
9
- color: green;
10
- }
11
- .tc-info {
12
- color: blue;
13
- }
14
- .tc-grep span {
15
- background: yellow;
16
- }
17
- pre {
18
- white-space: pre-wrap;
19
- }
20
- .tc-success {
21
- margin:0 20px 20px 20px;
22
- background:#e6ffe2;
23
- border:1px solid #d1eecc;
24
- }
25
- form {
26
- margin:20px auto;
27
- }
28
- .theme-check {
29
- margin:20px auto;
30
- border:1px solid #dfdfdf;
31
- -moz-border-radius:5px;
32
- -khtml-border-radius:5px;
33
- -webkit-border-radius:5px;
34
- border-radius:5px;
35
- }
36
- .theme-check h2 {
37
- margin:0 0 20px 0;
38
- padding:0 20px;
39
- background:#dfdfdf url("gray-grad.png") repeat-x left top;
40
- font-size:20px;
41
- border-bottom:1px solid #ccc;
42
- }
43
- .theme-check p {
44
- padding:5px 20px;
45
- }
46
- .theme-check form {
47
- margin-left:20px;
48
- }
49
- .theme-check ul {
50
- margin-left:20px;
51
- }
52
- .theme-check h3 {
53
- margin:0 0 10px 20px;
54
- padding:0;
55
- }
56
- .theme-check ul {
57
- margin-bottom:10px;
58
- }
59
- .theme-info {
60
- padding:10px;
61
- border:1px solid #dfdfdf;
62
- margin:10px 20px 0 20px;
63
- }
64
- .theme-info p {
65
- padding:0;
66
- margin-bottom:10px;
67
- }
68
- .theme-info label {
69
- float:left;
70
- width:100px;
71
- font-weight:bold;
72
- display:block;
73
- }
74
- .theme-info span.info {
75
- margin-left:100px;
76
- display:block;
77
- }
 
 
 
 
 
 
1
+ .tc-box {
2
+ padding:20px 0;
3
+ border-top:1px solid #dfdfdf;
4
+ }
5
+ .tc-required, .tc-fail {
6
+ color:red;
7
+ }
8
+ .tc-warning {
9
+ color: orange;
10
+ }
11
+ .tc-recommended, .tc-pass {
12
+ color: green;
13
+ }
14
+ .tc-info {
15
+ color: blue;
16
+ }
17
+ .tc-grep span {
18
+ background: yellow;
19
+ }
20
+ pre {
21
+ white-space: pre-wrap;
22
+ }
23
+ .tc-success {
24
+ margin:0 20px 20px 20px;
25
+ background:#e6ffe2;
26
+ border:1px solid #d1eecc;
27
+ }
28
+ form {
29
+ margin: 1.5em auto;
30
+ }
31
+ .theme-check {
32
+ margin: 1em auto;
33
+ border:1px solid #dfdfdf;
34
+ -moz-border-radius:5px;
35
+ -khtml-border-radius:5px;
36
+ -webkit-border-radius:5px;
37
+ border-radius:5px;
38
+ }
39
+ .theme-check h2 {
40
+ margin: 0 0 1em 0;
41
+ padding: 1em;
42
+ background:#dfdfdf url("gray-grad.png") repeat-x left top;
43
+ font-size:20px;
44
+ border-bottom:1px solid #ccc;
45
+ }
46
+ .theme-check p {
47
+ padding:5px 20px;
48
+ }
49
+ .theme-check form {
50
+ margin-left: 1.5em;
51
+ }
52
+ .theme-check ul {
53
+ margin-left:20px;
54
+ }
55
+ .theme-check h3 {
56
+ margin:0 0 10px 20px;
57
+ padding:0;
58
+ }
59
+ .theme-check ul {
60
+ margin-bottom:10px;
61
+ }
62
+ .theme-info {
63
+ padding: 1em;
64
+ border:1px solid #dfdfdf;
65
+ margin: 1em 1em 0 1em;
66
+ }
67
+ .theme-info p {
68
+ padding:0;
69
+ margin-bottom:10px;
70
+ }
71
+ .theme-info label {
72
+ float:left;
73
+ width:100px;
74
+ font-weight:bold;
75
+ display:block;
76
+ }
77
+ .theme-info span.info {
78
+ margin-left:100px;
79
+ display:block;
80
+ }
81
+ .theme-check input[name="s_info"] {
82
+ margin-left: 0.5em;
83
+ }
changelog.txt CHANGED
@@ -1,3 +1,45 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  = 20140929.1 =
2
  * Added new checks and updates from Frank Klein at Automattic. Thanks Frank!
3
  * Updated deprecated function listings
@@ -48,11 +90,11 @@
48
  * Add check for wp_link_pages() + fix eval() check
49
 
50
  = 20110219.2 =
51
- * Merged new UI props Gua Bob [1](http://guabob.com/)
52
  * Last tested theme is always pre-selected in the themes list.
53
  * Fixed php error in admin_menu.php
54
 
55
- = 20110219.1 =
56
  * See [commit log](https://github.com/Pross/theme-check/commits/) for changes.
57
 
58
  = 20110201.2 =
1
+ = 20200612.1 =
2
+ * Release to WordPress.org plugins directory
3
+
4
+ = 20200611.1 =
5
+ * Added escaping checks
6
+ * Added tested up to and Requires PHP checks for the style.css
7
+ * Added register_block_type to plugin territory check
8
+ * Check for remove_action wp_head
9
+ * Changed some checks from errors to warnings
10
+ * Updated error messages
11
+ * Updated regex for non printable characters
12
+ * Fixed parse errors
13
+ * Removed unused functions
14
+
15
+ = 20200504.1 =
16
+ * Contributor and URI adjustments
17
+ * site_url checks
18
+ * smarter nav menu and favicon checks
19
+ * additional filename blacklist checks
20
+ * developer files added to github (phpcs, composer, attributes, gitignore, etc)
21
+ * improvements to existing checks, move some warnings to required to reflect updated guidelines
22
+ * check for themes being copies of underscores
23
+ * check for non-gpl-compatible sites used for images
24
+ * Add warnings for demo content
25
+ * Update links in messages to point to new development and documentation locations
26
+ * disallow dashboard widgets in themes
27
+
28
+ = 20190801.1 =
29
+ * Fix missing nonce and nonce check on admin page. props Steven Stern for reporting the issue to the plugins team. Though this is technically a CSRF, there is no vulnerability arising from it, as the only thing that could be done with the form is to scan a theme.
30
+
31
+ = 20190208.1 =
32
+ * Add new styles for the block editor. See https://meta.trac.wordpress.org/ticket/3921
33
+
34
+ = 20160523.1 =
35
+ * Fix for theme-names with dashes in them
36
+ * Comments stripping changes
37
+ * Many changes by the theme review team and others. See Github for full change list.
38
+
39
+ = 20151211.1 =
40
+ * Full sync with Github and all the changes that have happened there.
41
+ * Release for 4.4 deprecated functions.
42
+
43
  = 20140929.1 =
44
  * Added new checks and updates from Frank Klein at Automattic. Thanks Frank!
45
  * Updated deprecated function listings
90
  * Add check for wp_link_pages() + fix eval() check
91
 
92
  = 20110219.2 =
93
+ * Merged new UI props Gua Bob [1](http://guabob.com/)
94
  * Last tested theme is always pre-selected in the themes list.
95
  * Fixed php error in admin_menu.php
96
 
97
+ = 20110219.1 =
98
  * See [commit log](https://github.com/Pross/theme-check/commits/) for changes.
99
 
100
  = 20110201.2 =
checkbase.php CHANGED
@@ -124,22 +124,6 @@ function tc_preg( $preg, $file ) {
124
  return str_replace( $error, '<span class="tc-grep">' . $error . '</span>', $bad_lines );
125
  }
126
 
127
- function tc_strxchr($haystack, $needle, $l_inclusive = 0, $r_inclusive = 0){
128
- if(strrpos($haystack, $needle)){
129
- //Everything before last $needle in $haystack.
130
- $left = substr($haystack, 0, strrpos($haystack, $needle) + $l_inclusive);
131
- //Switch value of $r_inclusive from 0 to 1 and viceversa.
132
- $r_inclusive = ($r_inclusive == 0) ? 1 : 0;
133
- //Everything after last $needle in $haystack.
134
- $right = substr(strrchr($haystack, $needle), $r_inclusive);
135
- //Return $left and $right into an array.
136
- return array($left, $right);
137
- } else {
138
- if(strrchr($haystack, $needle)) return array('', substr(strrchr($haystack, $needle), $r_inclusive));
139
- else return false;
140
- }
141
- }
142
-
143
  function tc_filename( $file ) {
144
  $filename = ( preg_match( '/themes\/[a-z0-9-]*\/(.*)/', $file, $out ) ) ? $out[1] : basename( $file );
145
  return $filename;
@@ -170,37 +154,6 @@ function listdir( $dir ) {
170
  return $files;
171
  }
172
 
173
- function old_listdir( $start_dir='.' ) {
174
- $files = array();
175
- if ( is_dir( $start_dir ) ) {
176
- $fh = opendir( $start_dir );
177
- while ( ( $file = readdir( $fh ) ) !== false ) {
178
- # loop through the files, skipping . and .., and recursing if necessary
179
- if ( strcmp( $file, '.' )==0 || strcmp( $file, '..' )==0 ) continue;
180
- $filepath = $start_dir . '/' . $file;
181
- if ( is_dir( $filepath ) )
182
- $files = array_merge( $files, listdir( $filepath ) );
183
- else
184
- array_push( $files, $filepath );
185
- }
186
- closedir( $fh );
187
-
188
- } else {
189
-
190
- # false if the function was called with an invalid non-directory argument
191
- $files = false;
192
- }
193
- return $files;
194
- }
195
-
196
- function tc_print_r( $data ) {
197
- $out = "\n<pre class='html-print-r'";
198
- $out .= " style='border: 1px solid #ccc; padding: 7px;'>\n";
199
- $out .= esc_html( print_r( $data, TRUE ) );
200
- $out .= "\n</pre>\n";
201
- echo $out;
202
- }
203
-
204
  function get_theme_data_from_contents( $theme_data ) {
205
  $themes_allowed_tags = array(
206
  'a' => array(
124
  return str_replace( $error, '<span class="tc-grep">' . $error . '</span>', $bad_lines );
125
  }
126
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
127
  function tc_filename( $file ) {
128
  $filename = ( preg_match( '/themes\/[a-z0-9-]*\/(.*)/', $file, $out ) ) ? $out[1] : basename( $file );
129
  return $filename;
154
  return $files;
155
  }
156
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
157
  function get_theme_data_from_contents( $theme_data ) {
158
  $themes_allowed_tags = array(
159
  'a' => array(
checks/admin_menu.php CHANGED
@@ -10,8 +10,8 @@ class AdminMenu implements themecheck {
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://codex.wordpress.org/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://codex.wordpress.org/Roles_and_Capabilities">Roles_and_Capabilities</a>', 'theme-check' )
15
  );
16
 
17
  foreach ( $php_files as $php_key => $phpfile ) {
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 ) {
checks/adminbar.php CHANGED
@@ -1,41 +1,55 @@
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
- checkcount();
11
- $php_regex = "/(add_filter(\s*)\((\s*)(\"|')show_admin_bar(\"|')(\s*)(.*))|(([^\S])show_admin_bar(\s*)\((.*))/";
12
- $css_regex = "/(#wpadminbar)/";
13
 
14
- //Check php files for filter show_admin_bar and show_admin_bar()
15
- foreach ( $php_files as $file_path => $file_content ) {
16
 
17
- $filename = tc_filename( $file_path );
 
 
18
 
19
- if ( preg_match( $php_regex, $file_content, $matches ) ) {
20
- $this->error[] = sprintf( '<span class="tc-lead tc-required">' . __( 'REQUIRED', 'theme-check').'</span>: ' . __( 'You are not allowed to hide the admin bar.', 'theme-check' ),
21
- '<strong>' . $filename . '</strong>');
22
- $ret = false;
23
- }
24
- }
25
 
26
- //Check CSS Files for #wpadminbar
27
- foreach ( $css_files as $file_path => $file_content ) {
28
 
29
- $filename = tc_filename( $file_path );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
30
 
31
- if ( preg_match( $css_regex, $file_content, $matches ) ) {
32
- $this->error[] = sprintf( '<span class="tc-lead tc-warning">' . __( 'WARNING', 'theme-check').'</span>: ' . __( 'The theme is using `#wpadminbar`. Hiding the admin bar is not allowed.', 'theme-check' ),
33
- '<strong>' . $filename . '</strong>');
34
- }
35
  }
 
 
36
  return $ret;
37
  }
38
 
39
  function getError() { return $this->error; }
40
  }
41
- $themechecks[] = new NoHiddenAdminBar;
 
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 CHANGED
@@ -26,7 +26,7 @@ class Bad_Checks implements themecheck {
26
  $filename = tc_filename( $php_key );
27
  $error = ltrim( trim( $matches[0], '(' ) );
28
  $grep = tc_grep( $error, $php_key );
29
- $this->error[] = sprintf('<span class="tc-lead tc-warning">'. __( 'WARNING', '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 );
30
  $ret = false;
31
  }
32
  }
@@ -45,7 +45,7 @@ class Bad_Checks implements themecheck {
45
  $filename = tc_filename( $php_key );
46
  $error = ltrim( rtrim( $matches[0],'(' ) );
47
  $grep = tc_grep( $error, $php_key );
48
- $this->error[] = sprintf(__('<span class="tc-lead tc-warning">WARNING</span>: Found <strong>%1$s</strong> in the file <strong>%2$s</strong>. %3$s.%4$s', 'theme-check'), $error, $filename, $check, $grep);
49
  $ret = false;
50
  }
51
  }
26
  $filename = tc_filename( $php_key );
27
  $error = ltrim( trim( $matches[0], '(' ) );
28
  $grep = tc_grep( $error, $php_key );
29
+ $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 );
30
  $ret = false;
31
  }
32
  }
45
  $filename = tc_filename( $php_key );
46
  $error = ltrim( rtrim( $matches[0],'(' ) );
47
  $grep = tc_grep( $error, $php_key );
48
+ $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);
49
  $ret = false;
50
  }
51
  }
checks/basic.php CHANGED
@@ -12,17 +12,18 @@ class Basic_Checks implements themecheck {
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_footer\s*\(' => __( 'See: <a href="https://codex.wordpress.org/Function_Reference/wp_footer">wp_footer</a><pre> &lt;?php wp_footer(); ?&gt;</pre>', 'theme-check' ),
16
- 'wp_head\s*\(' => __( 'See: <a href="https://codex.wordpress.org/Function_Reference/wp_head">wp_head</a><pre> &lt;?php wp_head(); ?&gt;</pre>', 'theme-check' ),
17
- 'language_attributes' => __( 'See: <a href="https://codex.wordpress.org/Function_Reference/language_attributes">language_attributes</a><pre>&lt;html &lt;?php language_attributes(); ?&gt;</pre>', 'theme-check' ),
 
18
  'charset' => __( 'There must be a charset defined in the Content-Type or the meta charset tag in the head.', 'theme-check' ),
19
- 'add_theme_support\s*\(\s?("|\')automatic-feed-links("|\')\s?\)' => __( 'See: <a href="https://codex.wordpress.org/Function_Reference/add_theme_support">add_theme_support</a><pre> &lt;?php add_theme_support( $feature ); ?&gt;</pre>', 'theme-check' ),
20
- 'comments_template\s*\(' => __( 'See: <a href="https://codex.wordpress.org/Template_Tags/comments_template">comments_template</a><pre> &lt;?php comments_template( $file, $separate_comments ); ?&gt;</pre>', 'theme-check' ),
21
- 'wp_list_comments\s*\(' => __( 'See: <a href="https://codex.wordpress.org/Template_Tags/wp_list_comments">wp_list_comments</a><pre> &lt;?php wp_list_comments( $args ); ?&gt;</pre>', 'theme-check' ),
22
- 'comment_form\s*\(' => __( 'See: <a href="https://codex.wordpress.org/Template_Tags/comment_form">comment_form</a><pre> &lt;?php comment_form(); ?&gt;</pre>', 'theme-check' ),
23
- 'body_class\s*\(' => __( 'See: <a href="https://codex.wordpress.org/Template_Tags/body_class">body_class</a><pre> &lt;?php body_class( $class ); ?&gt;</pre>', 'theme-check' ),
24
- 'wp_link_pages\s*\(' => __( 'See: <a href="https://codex.wordpress.org/Function_Reference/wp_link_pages">wp_link_pages</a><pre> &lt;?php wp_link_pages( $args ); ?&gt;</pre>', 'theme-check' ),
25
- 'post_class\s*\(' => __( 'See: <a href="https://codex.wordpress.org/Template_Tags/post_class">post_class</a><pre> &lt;div id="post-&lt;?php the_ID(); ?&gt;" &lt;?php post_class(); ?&gt;&gt;</pre>', 'theme-check' )
26
  );
27
 
28
  foreach ($checks as $key => $check) {
@@ -30,6 +31,7 @@ class Basic_Checks implements themecheck {
30
  if ( !preg_match( '/' . $key . '/i', $php ) ) {
31
  if ( $key === 'add_theme_support\s*\(\s?("|\')automatic-feed-links("|\')\s?\)' ) $key = __( 'add_theme_support( \'automatic-feed-links\' )', 'theme-check');
32
  if ( $key === 'body_class\s*\(' ) $key = __( 'body_class call in body tag', 'theme-check');
 
33
  $key = str_replace( '\s*\(', '', $key );
34
  $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 );
35
  $ret = false;
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) {
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;
checks/cdn.php CHANGED
@@ -1,5 +1,4 @@
1
  <?php
2
-
3
  /**
4
  * Checks for resources being loaded from CDNs.
5
  */
@@ -17,22 +16,24 @@ class CDNCheck implements themecheck {
17
  checkcount();
18
 
19
  $cdn_list = array(
20
- 'bootstrap-maxcdn' => 'maxcdn.bootstrapcdn.com/bootstrap',
21
- 'bootstrap-netdna' => 'netdna.bootstrapcdn.com/bootstrap',
22
- 'bootswatch-maxcdn' => 'maxcdn.bootstrapcdn.com/bootswatch',
23
- 'bootswatch-netdna' => 'netdna.bootstrapcdn.com/bootswatch',
24
- 'font-awesome-maxcdn' => 'maxcdn.bootstrapcdn.com/font-awesome',
25
- 'font-awesome-netdna' => 'netdna.bootstrapcdn.com/font-awesome',
26
- 'html5shiv-google' => 'html5shiv.googlecode.com/svn/trunk/html5.js',
27
- 'html5shiv-maxcdn' => 'oss.maxcdn.com/libs/html5shiv',
28
  'jquery' => 'code.jquery.com/jquery-',
29
- 'respond-js' => 'oss.maxcdn.com/libs/respond.js',
 
 
 
 
30
  );
31
 
32
  foreach( $cdn_list as $cdn_slug => $cdn_url ) {
33
  if ( false !== strpos( $all_code, $cdn_url ) ) {
34
- $this->error[] = '<span class="tc-lead tc-recommended">' . __('RECOMMENDED','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>' );
35
- //$ret = false;
36
  }
37
  }
38
 
1
  <?php
 
2
  /**
3
  * Checks for resources being loaded from CDNs.
4
  */
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
 
checks/comment_reply.php CHANGED
@@ -1,27 +1,27 @@
1
- <?php
2
- class Comment_Reply implements themecheck {
3
- protected $error = array();
4
-
5
- function check( $php_files, $css_files, $other_files) {
6
-
7
- $php = implode( ' ', $php_files );
8
- $ret = true;
9
-
10
- checkcount();
11
-
12
- if ( ! preg_match( '/wp_enqueue_script\(\s?("|\')comment-reply("|\')/i', $php ) ) {
13
- if ( ! preg_match( '/comment-reply/', $php ) ) {
14
- $check = __( 'See: <a href="https://codex.wordpress.org/Migrating_Plugins_and_Themes_to_2.7/Enhanced_Comment_Display">Migrating Plugins and Themes to 2.7/Enhanced Comment Display</a><pre> &lt;?php if ( is_singular() ) wp_enqueue_script( "comment-reply" ); ?&gt;</pre>', 'theme-check' );
15
- $this->error[] = sprintf('<span class="tc-lead tc-required">'.__('REQUIRED','theme-check').'</span>: '.__('Could not find the <strong>comment-reply</strong> script enqueued. %1$s', 'theme-check'), $check);
16
- $ret = false;
17
- } else {
18
- $this->error[] = '<span class="tc-lead tc-info">'.__('INFO','theme-check').'</span>: '.__('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');
19
- }
20
- }
21
- return $ret;
22
- }
23
-
24
- function getError() { return $this->error; }
25
- }
26
-
27
- $themechecks[] = new Comment_Reply;
1
+ <?php
2
+ class Comment_Reply implements themecheck {
3
+ protected $error = array();
4
+
5
+ function check( $php_files, $css_files, $other_files) {
6
+
7
+ $php = implode( ' ', $php_files );
8
+ $ret = true;
9
+
10
+ checkcount();
11
+
12
+ if ( ! preg_match( '/wp_enqueue_script\(\s?("|\')comment-reply("|\')/i', $php ) ) {
13
+ if ( ! preg_match( '/comment-reply/', $php ) ) {
14
+ $check = __( 'See: <a href="https://codex.wordpress.org/Migrating_Plugins_and_Themes_to_2.7/Enhanced_Comment_Display">Migrating Plugins and Themes to 2.7/Enhanced Comment Display</a><pre> &lt;?php if ( is_singular() ) wp_enqueue_script( "comment-reply" ); ?&gt;</pre>', 'theme-check' );
15
+ $this->error[] = sprintf('<span class="tc-lead tc-required">'.__('REQUIRED','theme-check').'</span>: '.__('Could not find the <strong>comment-reply</strong> script enqueued. %1$s', 'theme-check'), $check);
16
+ $ret = false;
17
+ } else {
18
+ $this->error[] = '<span class="tc-lead tc-info">'.__('INFO','theme-check').'</span>: '.__('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');
19
+ }
20
+ }
21
+ return $ret;
22
+ }
23
+
24
+ function getError() { return $this->error; }
25
+ }
26
+
27
+ $themechecks[] = new Comment_Reply;
checks/customizer.php CHANGED
@@ -1,5 +1,4 @@
1
  <?php
2
-
3
  /**
4
  * Checks for the Customizer.
5
  */
@@ -7,7 +6,7 @@
7
  class CustomizerCheck implements themecheck {
8
  protected $error = array();
9
 
10
- function check( $php_files, $css_files, $other_files) {
11
 
12
  $ret = true;
13
 
@@ -17,18 +16,33 @@ class CustomizerCheck implements themecheck {
17
  * Check whether every Customizer setting has a sanitization callback set.
18
  */
19
  foreach ( $php_files as $file_path => $file_content ) {
20
- // Get the arguments passed to the add_setting method
21
  if ( preg_match_all( '/\$wp_customize->add_setting\(([^;]+)/', $file_content, $matches ) ) {
22
- // The full match is in [0], the match group in [1]
23
  foreach ( $matches[1] as $match ) {
24
- // Check if we have sanitize_callback or sanitize_js_callback
25
  if ( false === strpos( $match, 'sanitize_callback' ) && false === strpos( $match, 'sanitize_js_callback' ) ) {
26
- $this->error[] = '<span class="tc-lead tc-required">' . __('REQUIRED','theme-check') . '</span>: ' . __( 'Found a Customizer setting that did not have a sanitization callback function. Every call to the <strong>add_setting()</strong> method needs to have a sanitization callback function passed.', 'theme-check' );
 
 
 
 
 
 
 
 
27
  $ret = false;
28
  } else {
29
  // There's a callback, check that no empty parameter is passed.
30
  if ( preg_match( '/[\'"](?:sanitize_callback|sanitize_js_callback)[\'"]\s*=>\s*[\'"]\s*[\'"]/', $match ) ) {
31
- $this->error[] = '<span class="tc-lead tc-required">' . __('REQUIRED','theme-check') . '</span>: ' . __( 'Found a Customizer setting that had an empty value passed as sanitization callback. You need to pass a function name as sanitization callback.', 'theme-check' );
 
 
 
 
 
 
 
32
  $ret = false;
33
  }
34
  }
@@ -41,4 +55,5 @@ class CustomizerCheck implements themecheck {
41
 
42
  function getError() { return $this->error; }
43
  }
44
- $themechecks[] = new CustomizerCheck;
 
1
  <?php
 
2
  /**
3
  * Checks for the Customizer.
4
  */
6
  class CustomizerCheck implements themecheck {
7
  protected $error = array();
8
 
9
+ function check( $php_files, $css_files, $other_files ) {
10
 
11
  $ret = true;
12
 
16
  * Check whether every Customizer setting has a sanitization callback set.
17
  */
18
  foreach ( $php_files as $file_path => $file_content ) {
19
+ // Get the arguments passed to the add_setting method.
20
  if ( preg_match_all( '/\$wp_customize->add_setting\(([^;]+)/', $file_content, $matches ) ) {
21
+ // The full match is in [0], the match group in [1].
22
  foreach ( $matches[1] as $match ) {
23
+ // Check if we have sanitize_callback or sanitize_js_callback.
24
  if ( false === strpos( $match, 'sanitize_callback' ) && false === strpos( $match, 'sanitize_js_callback' ) ) {
25
+ /* Clean up our match to be able to present the results better. */
26
+ $match = preg_split( '/,/', $match );
27
+ $filename = tc_filename( $file_path );
28
+ $grep = tc_preg( $match[0], $file_path );
29
+ $grep = preg_split( '/,/', $grep );
30
+ $this->error[] = sprintf( '<span class="tc-lead tc-required">' . __( 'REQUIRED', 'theme-check' ) . '</span>: ' . __( 'Found a Customizer setting called %1$s in %2$s that did not have a sanitization callback function. ', 'theme-check' ) . __( 'Every call to the <strong>add_setting()</strong> method needs to have a sanitization callback function passed.', 'theme-check' ),
31
+ '<strong>' . $match[0] . '</strong>',
32
+ '<strong>' . $filename . '</strong>'
33
+ ) . $grep[0];
34
  $ret = false;
35
  } else {
36
  // There's a callback, check that no empty parameter is passed.
37
  if ( preg_match( '/[\'"](?:sanitize_callback|sanitize_js_callback)[\'"]\s*=>\s*[\'"]\s*[\'"]/', $match ) ) {
38
+ $match = preg_split( '/,/', $match );
39
+ $filename = tc_filename( $file_path );
40
+ $grep = tc_preg( '/[\'"](?:sanitize_callback|sanitize_js_callback)[\'"]\s*=>\s*[\'"]\s*[\'"]/', $file_path );
41
+ $grep = preg_split( '/,/', $grep );
42
+ $this->error[] = sprintf( '<span class="tc-lead tc-required">' . __( 'REQUIRED', 'theme-check' ) . '</span>: ' . __( 'Found a Customizer setting called %1$s in %2$s that had an empty value passed as sanitization callback. You need to pass a function name as sanitization callback.', 'theme-check' ),
43
+ '<strong>' . $match[0] . '</strong>',
44
+ '<strong>' . $filename . '</strong>'
45
+ ) . $grep[0];
46
  $ret = false;
47
  }
48
  }
55
 
56
  function getError() { return $this->error; }
57
  }
58
+
59
+ $themechecks[] = new CustomizerCheck();
checks/deprecated.php CHANGED
@@ -254,7 +254,13 @@ class Deprecated implements themecheck {
254
  array( 'prepreview_added_widget_instance' => 'customize_dynamic_setting_args', '4.2' ),
255
  array( 'remove_prepreview_filters' => 'customize_dynamic_setting_args', '4.2' ),
256
 
 
 
 
 
257
  array( 'wp_get_http' => 'WP_Http', '4.4' ),
 
 
258
 
259
  array( 'is_comments_popup' => '', '4.5' ),
260
  array( 'add_object_page' => 'add_menu_page', '4.5' ),
@@ -264,6 +270,38 @@ class Deprecated implements themecheck {
264
  array( 'popuplinks' => '', '4.5' ),
265
  array( 'get_currentuserinfo' => 'wp_get_current_user', '4.5' ),
266
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
267
  );
268
  foreach ( $php_files as $php_key => $phpfile ) {
269
  foreach ( $checks as $alt => $check ) {
254
  array( 'prepreview_added_widget_instance' => 'customize_dynamic_setting_args', '4.2' ),
255
  array( 'remove_prepreview_filters' => 'customize_dynamic_setting_args', '4.2' ),
256
 
257
+ array( 'wp_htmledit_pre' => 'format_for_editor', '4.3' ),
258
+ array( 'wp_richedit_pre' => 'format_for_editor', '4.3' ),
259
+ array( 'preview_theme' => '', '4.3' ),
260
+
261
  array( 'wp_get_http' => 'WP_Http', '4.4' ),
262
+ array( 'post_permalink' => 'get_permalink', '4.4' ),
263
+ array( 'force_ssl_login' => 'force_ssl_admin', '4.4' ),
264
 
265
  array( 'is_comments_popup' => '', '4.5' ),
266
  array( 'add_object_page' => 'add_menu_page', '4.5' ),
270
  array( 'popuplinks' => '', '4.5' ),
271
  array( 'get_currentuserinfo' => 'wp_get_current_user', '4.5' ),
272
 
273
+ array( 'wp_embed_handler_googlevideo' => '', '4.6' ),
274
+ array( 'wp_get_sites' => 'get_sites', '4.6' ),
275
+ array( 'post_form_autocomplete_off' => '', '4.6' ),
276
+
277
+ array( 'wp_die_handler' => '', '4.7' ),
278
+ array( 'wp_redirect_status' => '', '4.7' ),
279
+ array( 'customize_preview_override_404_status' => '', '4.7' ),
280
+ array( 'customize_preview_base' => '', '4.7' ),
281
+ array( 'customize_preview_html5' => '', '4.7' ),
282
+ array( 'customize_preview_signature' => '', '4.7' ),
283
+ array( 'remove_preview_signature' => '', '4.7' ),
284
+ array( '_cmp_priority' => 'wp_list_sort', '4.7' ),
285
+ array( 'reinit' => 'WP_Roles::for_site()', '4.7' ),
286
+ array( 'get_paged_template' => '', '4.7' ),
287
+ array( 'wp_kses_js_entities' => '', '4.7' ),
288
+ array( 'wp_get_network' => 'get_network()', '4.7' ),
289
+ array( '_sort_menus_by_orderby' => 'wp_list_sort', '4.7' ),
290
+
291
+ array( 'wp_dashboard_plugins_output' => '', '4.8' ),
292
+
293
+ array( '_init' => 'WP_Roles::for_site()', '4.9' ),
294
+ array( '_init_caps' => 'WP_User::for_site()', '4.9' ),
295
+ array( 'for_blog' => 'WP_User::for_site()', '4.9' ),
296
+ array( 'get_shortcut_link' => '', '4.9' ),
297
+ array( 'wp_ajax_press_this_save_post' => '', '4.9' ),
298
+ array( 'wp_ajax_press_this_add_category' => '', '4.9' ),
299
+ array( 'is_user_option_local' => '', '4.9' ),
300
+ array( 'maybe_log_events_response' => '', '4.9' ),
301
+
302
+ array( 'insert_blog' => 'wp_insert_site()', '5.1' ),
303
+ array( 'install_blog' => '', '5.1' ),
304
+
305
  );
306
  foreach ( $php_files as $php_key => $phpfile ) {
307
  foreach ( $checks as $alt => $check ) {
checks/deregister.php CHANGED
@@ -17,8 +17,7 @@ class DeregisterCheck implements themecheck {
17
  $grep = tc_preg( $error, $file_path );
18
 
19
  $this->error[] = sprintf( '<span class="tc-lead tc-warning">' . __('WARNING','theme-check') . '</span>: ' . __( 'Found wp_deregister_script in %1$s. Themes must not deregister core scripts.', 'theme-check' ),
20
- '<strong>' . $filename . '</strong>') . $grep;
21
- $ret = false;
22
  }
23
  }
24
  return $ret;
@@ -27,4 +26,4 @@ class DeregisterCheck implements themecheck {
27
 
28
  function getError() { return $this->error; }
29
  }
30
- $themechecks[] = new DeregisterCheck;
17
  $grep = tc_preg( $error, $file_path );
18
 
19
  $this->error[] = sprintf( '<span class="tc-lead tc-warning">' . __('WARNING','theme-check') . '</span>: ' . __( 'Found wp_deregister_script in %1$s. Themes must not deregister core scripts.', 'theme-check' ),
20
+ '<strong>' . $filename . '</strong>') . $grep;
 
21
  }
22
  }
23
  return $ret;
26
 
27
  function getError() { return $this->error; }
28
  }
29
+ $themechecks[] = new DeregisterCheck;
checks/escaping.php ADDED
@@ -0,0 +1,105 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php // phpcs:ignore WordPress.Files.FileName
2
+ /**
3
+ * Checks for common escaping issues.
4
+ *
5
+ * @link https://make.wordpress.org/themes/handbook/review/required/#code
6
+ */
7
+
8
+ /**
9
+ * Checks for common escaping issues.
10
+ */
11
+ class EscapingCheck 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
+ $ret = true;
29
+
30
+ $warnings = array(
31
+ '/="<\?php esc_html_e/' => __( 'Use esc_attr_e() inside HTML attributes, and esc_url() for link attributes', 'theme-check' ),
32
+ '/="<\?php echo esc_html__/' => __( 'Use esc_attr__() inside HTML attributes, and esc_url() for link attributes', 'theme-check' ),
33
+ '/="<\?php esc_html\(/' => __( 'Use esc_attr() inside HTML attributes, and esc_url() for link attributes', 'theme-check' ),
34
+ '/><\?php echo esc_attr\(/' => __( 'Only use esc_attr() inside HTML attributes. Use esc_html() between HTML tags', 'theme-check' ),
35
+ '/><\?php echo esc_attr__/' => __( 'Only use esc_attr__() inside HTML attributes. Use esc_html__() between HTML tags', 'theme-check' ),
36
+ '/><\?php esc_attr_e/' => __( 'Only use esc_attr_e() inside HTML attributes. Use esc_html_e() between HTML tags', 'theme-check' ),
37
+ );
38
+
39
+ $required = array (
40
+ '/echo home_url/' => __( 'home_url() must be escaped. Use esc_url() for link attributes', 'theme-check' ),
41
+ '/echo get_template_directory_uri/' => __( 'get_template_directory_uri() must be escaped when output as part of a link or image source. Use esc_url() for link attributes', 'theme-check' ),
42
+ );
43
+
44
+ foreach ( $php_files as $php_key => $phpfile ) {
45
+
46
+ checkcount();
47
+ if ( false !== strpos( $phpfile, 'echo get_theme_mod' ) ) {
48
+ $filename = tc_filename( $php_key );
49
+ $error = 'echo get_theme_mod';
50
+ $grep = tc_grep( $error, $php_key );
51
+ $this->error[] = sprintf(
52
+ '<span class="tc-lead tc-warning">' . __( 'WARNING', 'theme-check' ) . '</span>: ' . __( 'Found %1$s in %2$s. <a href="%3$s" target="_blank">Theme options must be escaped (Opens in a new window).</a>. ', 'theme-check' ),
53
+ '<code>' . esc_html( $error ) . '</code>',
54
+ '<strong>' . $filename . '</strong>',
55
+ 'https://developer.wordpress.org/themes/theme-security/data-sanitization-escaping/#escaping-securing-output'
56
+ ) . $grep;
57
+
58
+ }
59
+
60
+ foreach ( $warnings as $key => $check ) {
61
+ checkcount();
62
+ if ( preg_match( $key, $phpfile, $matches ) ) {
63
+ $filename = tc_filename( $php_key );
64
+ $error = $matches[0];
65
+ $grep = tc_grep( $error, $php_key );
66
+ $this->error[] = sprintf(
67
+ '<span class="tc-lead tc-warning">' . __( 'WARNING', 'theme-check' ) . '</span>: ' . __( 'Found %1$s in %2$s. %3$s. A manual review is needed.', 'theme-check' ),
68
+ '<code>' . esc_html( $error ) . '</code>',
69
+ '<strong>' . $filename . '</strong>',
70
+ $check
71
+ ) . $grep;
72
+ }
73
+ }
74
+
75
+ foreach ( $required as $key => $check ) {
76
+ checkcount();
77
+ if ( preg_match( $key, $phpfile, $matches ) ) {
78
+ $filename = tc_filename( $php_key );
79
+ $error = $matches[0];
80
+ $grep = tc_grep( $error, $php_key );
81
+ $this->error[] = sprintf(
82
+ '<span class="tc-lead tc-required">' . __( 'REQUIRED', 'theme-check' ) . '</span>: ' . __( 'Found %1$s in %2$s. %3$s. A manual review is needed.', 'theme-check' ),
83
+ '<code>' . esc_html( $error ) . '</code>',
84
+ '<strong>' . $filename . '</strong>',
85
+ $check
86
+ ) . $grep;
87
+
88
+ $ret = false;
89
+ }
90
+ }
91
+ }
92
+ return $ret;
93
+ }
94
+
95
+ /**
96
+ * Get error messages from the checks.
97
+ *
98
+ * @return array Error message.
99
+ */
100
+ public function getError() {
101
+ return $this->error;
102
+ }
103
+ }
104
+
105
+ $themechecks[] = new EscapingCheck();
checks/favicon.php CHANGED
@@ -1,4 +1,8 @@
1
  <?php
 
 
 
 
2
 
3
  class FaviconCheck implements themecheck {
4
  protected $error = array();
@@ -6,16 +10,18 @@ class FaviconCheck implements themecheck {
6
  function check( $php_files, $css_files, $other_files ) {
7
 
8
  $ret = true;
9
-
10
  checkcount();
11
 
12
  foreach ( $php_files as $file_path => $file_content ) {
13
 
14
  $filename = tc_filename( $file_path );
15
 
16
- if ( preg_match( '/(<link rel=[\'"]icon[\'"])|(<link rel=[\'"]apple-touch-icon-precomposed[\'"])|(<meta name=[\'"]msapplication-TileImage[\'"])/', $file_content, $matches ) ) {
17
- $this->error[] = sprintf( '<span class="tc-lead tc-info">' . __('INFO','theme-check') . '</span>: ' . __( 'Possible Favicon found in %1$s. Favicons are handled by the Site Icon setting in the customizer since version 4.3.', 'theme-check' ),
18
- '<strong>' . $filename . '</strong>');
 
 
19
  }
20
  }
21
  return $ret;
@@ -23,4 +29,5 @@ class FaviconCheck implements themecheck {
23
 
24
  function getError() { return $this->error; }
25
  }
26
- $themechecks[] = new FaviconCheck;
 
1
  <?php
2
+ /**
3
+ * Checks for favicons.
4
+ * Note that the check for the icon file is in filenames.php.
5
+ */
6
 
7
  class FaviconCheck implements themecheck {
8
  protected $error = array();
10
  function check( $php_files, $css_files, $other_files ) {
11
 
12
  $ret = true;
13
+
14
  checkcount();
15
 
16
  foreach ( $php_files as $file_path => $file_content ) {
17
 
18
  $filename = tc_filename( $file_path );
19
 
20
+ if ( preg_match( '/(<link rel=[\'"]icon[\'"])|(<link rel=[\'"]shortcut icon[\'"])|(<link rel=[\'"]apple-touch-icon.*[\'"])|(<meta name=[\'"]msapplication-TileImage[\'"])/i', $file_content, $matches ) ) {
21
+ $this->error[] = sprintf( '<span class="tc-lead tc-required">' . __( 'REQUIRED', 'theme-check' ) . '</span>: ' . __( 'Possible Favicon found in %1$s. Favicons are handled by the Site Icon setting in the customizer since version 4.3.', 'theme-check' ),
22
+ '<strong>' . $filename . '</strong>'
23
+ );
24
+ $ret = false;
25
  }
26
  }
27
  return $ret;
29
 
30
  function getError() { return $this->error; }
31
  }
32
+
33
+ $themechecks[] = new FaviconCheck();
checks/filenames.php CHANGED
@@ -17,45 +17,63 @@ class File_Checks implements themecheck {
17
  foreach ( $css_files as $php_key => $phpfile ) {
18
  array_push( $filenames, strtolower( basename( $php_key ) ) );
19
  }
 
 
 
20
  $blacklist = array(
21
- 'thumbs.db' => __( 'Windows thumbnail store', 'theme-check' ),
22
- 'desktop.ini' => __( 'windows system file', 'theme-check' ),
23
- 'project.properties' => __( 'NetBeans Project File', 'theme-check' ),
24
- 'project.xml' => __( 'NetBeans Project File', 'theme-check' ),
25
- '\.kpf' => __( 'Komodo Project File', 'theme-check' ),
26
- '^\.+[a-zA-Z0-9]' => __( 'Hidden Files or Folders', 'theme-check' ),
27
- 'php.ini' => __( 'PHP server settings file', 'theme-check' ),
28
- 'dwsync.xml' => __( 'Dreamweaver project file', 'theme-check' ),
29
- 'error_log' => __( 'PHP error log', 'theme-check' ),
30
- 'web.config' => __( 'Server settings file', 'theme-check' ),
31
- '\.sql' => __( 'SQL dump file', 'theme-check' ),
32
- '__MACOSX' => __( 'OSX system file', 'theme-check' ),
33
- '\.lubith' => __( 'Lubith theme generator file', 'theme-check' ),
34
- );
 
 
 
 
 
 
 
 
 
 
 
 
35
 
36
- $musthave = array( 'index.php', 'style.css' );
37
- $rechave = array( 'readme.txt' => __( 'Please see <a href="https://codex.wordpress.org/Theme_Review#Theme_Documentation">Theme_Documentation</a> for more information.', 'theme-check' ) );
38
 
39
  checkcount();
40
 
41
- foreach( $blacklist as $file => $reason ) {
42
- if ( $filename = preg_grep( '/' . $file . '/', $filenames ) ) {
43
- $error = implode( array_unique( $filename ), ' ' );
44
- $this->error[] = sprintf('<span class="tc-lead tc-warning">'.__('WARNING','theme-check').'</span>: '.__('%1$s %2$s found.', 'theme-check'), '<strong>' . $error . '</strong>', $reason) ;
45
- $ret = false;
 
 
 
46
  }
47
  }
48
 
49
- foreach( $musthave as $file ) {
50
- if ( !in_array( $file, $filenames ) ) {
51
- $this->error[] = sprintf('<span class="tc-lead tc-warning">'.__('WARNING','theme-check').'</span>: '.__('Could not find the file %s in the theme.', 'theme-check'), '<strong>' . $file . '</strong>' );
52
- $ret = false;
53
  }
54
  }
55
 
56
- foreach( $rechave as $file => $reason ) {
57
- if ( !in_array( $file, $filenames ) ) {
58
- $this->error[] = sprintf('<span class="tc-lead tc-recommended">'.__('RECOMMENDED','theme-check').'</span>: '.__('Could not find the file %1$s in the theme. %2$s', 'theme-check'), '<strong>' . $file . '</strong>', $reason );
59
  }
60
  }
61
 
@@ -64,4 +82,5 @@ class File_Checks implements themecheck {
64
 
65
  function getError() { return $this->error; }
66
  }
67
- $themechecks[] = new File_Checks;
 
17
  foreach ( $css_files as $php_key => $phpfile ) {
18
  array_push( $filenames, strtolower( basename( $php_key ) ) );
19
  }
20
+
21
+ $whitelist = 'wpml-config.xml';
22
+
23
  $blacklist = array(
24
+ 'thumbs\.db' => __( 'Windows thumbnail store', 'theme-check' ),
25
+ 'desktop\.ini' => __( 'windows system file', 'theme-check' ),
26
+ 'project\.properties' => __( 'NetBeans Project File', 'theme-check' ),
27
+ 'project\.xml' => __( 'NetBeans Project File', 'theme-check' ),
28
+ '\.kpf' => __( 'Komodo Project File', 'theme-check' ),
29
+ '^\.+[a-zA-Z0-9]' => __( 'Hidden Files or Folders', 'theme-check' ),
30
+ 'php\.ini' => __( 'PHP server settings file', 'theme-check' ),
31
+ 'dwsync\.xml' => __( 'Dreamweaver project file', 'theme-check' ),
32
+ 'error_log' => __( 'PHP error log', 'theme-check' ),
33
+ 'web\.config' => __( 'Server settings file', 'theme-check' ),
34
+ '\.sql' => __( 'SQL dump file', 'theme-check' ),
35
+ '__MACOSX' => __( 'OSX system file', 'theme-check' ),
36
+ '\.lubith' => __( 'Lubith theme generator file', 'theme-check' ),
37
+ '\.wie' => __( 'Widget import file', 'theme-check' ),
38
+ '\.dat' => __( 'Customizer import file', 'theme-check' ),
39
+ 'phpcs\.xml\.dist' => __( 'PHPCS file', 'theme-check' ),
40
+ 'phpcs\.xml' => __( 'PHPCS file', 'theme-check' ),
41
+ '\.xml' => __( 'XML file', 'theme-check' ),
42
+ '\.sh' => __( 'Shell script file', 'theme-check' ),
43
+ 'postcss\.config\.js' => __( 'PostCSS config file', 'theme-check' ),
44
+ '\.editorconfig.' => __( 'Editor config file', 'theme-check' ),
45
+ '\.stylelintrc\.json' => __( 'Stylelint config file', 'theme-check' ),
46
+ '\.map' => __( 'Map file', 'theme-check' ),
47
+ '\.eslintrc' => __( 'ES lint config file', 'theme-check' ),
48
+ 'favicon\.ico' => __( 'Favicon', 'theme-check' ),
49
+ );
50
 
51
+ $musthave = array( 'index.php', 'style.css', 'readme.txt' );
52
+ $rechave = array();
53
 
54
  checkcount();
55
 
56
+ foreach ( $blacklist as $file => $reason ) {
57
+ if ( $filename = preg_grep( '/' . $file . '/', $filenames ) ) {
58
+ $error = implode( ' ', array_unique( $filename ) );
59
+ if ( $error === $whitelist ) {
60
+ continue;
61
+ }
62
+ $this->error[] = sprintf( '<span class="tc-lead tc-required">' . __( 'REQUIRED', 'theme-check' ) . '</span>: ' . __( '%1$s %2$s found. This file must not be in a theme.', 'theme-check' ), '<strong>' . $error . '</strong>', $reason );
63
+ $ret = false;
64
  }
65
  }
66
 
67
+ foreach ( $musthave as $file ) {
68
+ if ( ! in_array( $file, $filenames ) ) {
69
+ $this->error[] = sprintf( '<span class="tc-lead tc-required">' . __( 'REQUIRED', 'theme-check' ) . '</span>: ' . __( 'Could not find the file %s in the theme.', 'theme-check' ), '<strong>' . $file . '</strong>' );
70
+ $ret = false;
71
  }
72
  }
73
 
74
+ foreach ( $rechave as $file => $reason ) {
75
+ if ( ! in_array( $file, $filenames ) ) {
76
+ $this->error[] = sprintf( '<span class="tc-lead tc-recommended">' . __( 'RECOMMENDED', 'theme-check' ) . '</span>: ' . __( 'Could not find the file %1$s in the theme. %2$s', 'theme-check' ), '<strong>' . $file . '</strong>', $reason );
77
  }
78
  }
79
 
82
 
83
  function getError() { return $this->error; }
84
  }
85
+
86
+ $themechecks[] = new File_Checks();
checks/generated.php CHANGED
@@ -30,7 +30,7 @@ class GeneratedCheck implements themecheck {
30
  //wpthemegenerator
31
  || strpos ( $php, "wptg_") !== false
32
  ) {
33
- $this->error[] = "<span class='tc-lead tc-warning'>" . __('WARNING', 'theme-check' ). "</span>: " . __( 'This theme appears to have been auto-generated. Generated themes are not allowed in the themes directory.', 'theme-check' );
34
  $ret = false;
35
  }
36
 
@@ -39,4 +39,4 @@ class GeneratedCheck implements themecheck {
39
 
40
  function getError() { return $this->error; }
41
  }
42
- $themechecks[] = new GeneratedCheck;
30
  //wpthemegenerator
31
  || strpos ( $php, "wptg_") !== false
32
  ) {
33
+ $this->error[] = "<span class='tc-lead tc-required'>" . __('REQUIRED', 'theme-check' ). "</span>: " . __( 'This theme appears to have been auto-generated. Generated themes are not allowed in the themes directory.', 'theme-check' );
34
  $ret = false;
35
  }
36
 
39
 
40
  function getError() { return $this->error; }
41
  }
42
+ $themechecks[] = new GeneratedCheck;
checks/i18n.php CHANGED
@@ -1,70 +1,71 @@
1
- <?php
2
-
3
- // check for various I18N errors
4
-
5
- class I18NCheck implements themecheck {
6
- protected $error = array();
7
-
8
- function check( $php_files, $css_files, $other_files ) {
9
- $ret = true;
10
- $error = '';
11
- checkcount();
12
-
13
- // make sure the tokenizer is available
14
- if ( !function_exists( 'token_get_all' ) ) return true;
15
-
16
- foreach ( $php_files as $php_key => $phpfile ) {
17
- $error='';
18
-
19
- $stmts = array();
20
- foreach ( array('_e(', '__(', '_e (', '__ (') as $finder) {
21
- $search = $phpfile;
22
- while ( ( $pos = strpos($search, $finder) ) !== false ) {
23
- $search = substr($search,$pos);
24
- $open=1;
25
- $i=strpos($search,'(')+1;
26
- while( $open>0 ) {
27
- switch($search[$i]) {
28
- case '(':
29
- $open++; break;
30
- case ')':
31
- $open--; break;
32
- }
33
- $i++;
34
- }
35
- $stmts[] = substr($search,0,$i);
36
- $search = substr($search,$i);
37
- }
38
- }
39
-
40
- foreach ( $stmts as $match ) {
41
- $tokens = @token_get_all('<?php '.$match.';');
42
- if (!empty($tokens)) {
43
- foreach ($tokens as $token) {
44
- if (is_array($token) && in_array( $token[0], array( T_VARIABLE ) ) ) {
45
- $filename = tc_filename( $php_key );
46
- $grep = tc_grep( ltrim( $match ), $php_key );
47
- preg_match( '/[^\s]*\s[0-9]+/', $grep, $line);
48
- $error = '';
49
- if ( isset( $line[0] ) ) {
50
- $error = ( !strpos( $error, $line[0] ) ) ? $grep : '';
51
- }
52
- $this->error[] = sprintf('<span class="tc-lead tc-recommended">'.__('RECOMMENDED','theme-check').'</span>: '.__('Possible variable %1$s found in translation function in %2$s. Translation function calls must NOT contain PHP variables. %3$s','theme-check'),
53
- '<strong>' . $token[1] . '</strong>',
54
- '<strong>' . $filename . '</strong>',
55
- $error
56
- );
57
- break; // stop looking at the tokens on this line once a variable is found
58
- }
59
- }
60
- }
61
- }
62
-
63
-
64
- }
65
- return $ret;
66
- }
67
-
68
- function getError() { return $this->error; }
69
- }
 
70
  $themechecks[] = new I18NCheck;
1
+ <?php
2
+
3
+ // check for various I18N errors
4
+
5
+ class I18NCheck implements themecheck {
6
+ protected $error = array();
7
+
8
+ function check( $php_files, $css_files, $other_files ) {
9
+
10
+ $ret = true;
11
+ $error = '';
12
+ checkcount();
13
+
14
+ // make sure the tokenizer is available
15
+ if ( !function_exists( 'token_get_all' ) ) return true;
16
+
17
+ foreach ( $php_files as $php_key => $phpfile ) {
18
+ $error='';
19
+
20
+ $stmts = array();
21
+ foreach ( array('_e(', '__(', '_e (', '__ (') as $finder) {
22
+ $search = $phpfile;
23
+ while ( ( $pos = strpos($search, $finder) ) !== false ) {
24
+ $search = substr($search,$pos);
25
+ $open=1;
26
+ $i=strpos($search,'(')+1;
27
+ while( $open>0 ) {
28
+ switch($search[$i]) {
29
+ case '(':
30
+ $open++; break;
31
+ case ')':
32
+ $open--; break;
33
+ }
34
+ $i++;
35
+ }
36
+ $stmts[] = substr($search,0,$i);
37
+ $search = substr($search,$i);
38
+ }
39
+ }
40
+
41
+ foreach ( $stmts as $match ) {
42
+ $tokens = @token_get_all('<?php '.$match.';');
43
+ if (!empty($tokens)) {
44
+ foreach ($tokens as $token) {
45
+ if (is_array($token) && in_array( $token[0], array( T_VARIABLE ) ) ) {
46
+ $filename = tc_filename( $php_key );
47
+ $grep = tc_grep( ltrim( $match ), $php_key );
48
+ preg_match( '/[^\s]*\s[0-9]+/', $grep, $line);
49
+ $error = '';
50
+ if ( isset( $line[0] ) ) {
51
+ $error = ( !strpos( $error, $line[0] ) ) ? $grep : '';
52
+ }
53
+ $this->error[] = sprintf('<span class="tc-lead tc-recommended">'.__('RECOMMENDED','theme-check').'</span>: '.__('Possible variable %1$s found in translation function in %2$s. Translation function calls must NOT contain PHP variables. %3$s','theme-check'),
54
+ '<strong>' . $token[1] . '</strong>',
55
+ '<strong>' . $filename . '</strong>',
56
+ $error
57
+ );
58
+ break; // stop looking at the tokens on this line once a variable is found
59
+ }
60
+ }
61
+ }
62
+ }
63
+
64
+
65
+ }
66
+ return $ret;
67
+ }
68
+
69
+ function getError() { return $this->error; }
70
+ }
71
  $themechecks[] = new I18NCheck;
checks/included-plugins.php CHANGED
@@ -19,7 +19,7 @@ class IncludedPlugins implements themecheck {
19
 
20
  foreach ( $blacklist as $file => $reason ) {
21
  if ( $filename = preg_grep( '/' . $file . '/', $filenames ) ) {
22
- $error = implode( array_unique( $filename ), ' ' );
23
  $this->error[] = sprintf( '<span class="tc-lead tc-required">' . __( 'REQUIRED','theme-check' ) . '</span>: ' . __( '<strong>Zip file found.</strong> Plugins are not allowed in themes. The zip file found was <em>%s</em>.', 'theme-check' ), $error );
24
  $ret = false;
25
  }
19
 
20
  foreach ( $blacklist as $file => $reason ) {
21
  if ( $filename = preg_grep( '/' . $file . '/', $filenames ) ) {
22
+ $error = implode( ' ', array_unique( $filename ) );
23
  $this->error[] = sprintf( '<span class="tc-lead tc-required">' . __( 'REQUIRED','theme-check' ) . '</span>: ' . __( '<strong>Zip file found.</strong> Plugins are not allowed in themes. The zip file found was <em>%s</em>.', 'theme-check' ), $error );
24
  $ret = false;
25
  }
checks/lineendings.php CHANGED
@@ -8,7 +8,7 @@ class LineEndingsCheck implements themecheck {
8
  if (preg_match("/\r\n/",$phpfile)) {
9
  if (preg_match("/[^\r]\n/",$phpfile)) {
10
  $filename = tc_filename( $php_key );
11
- $this->error[] = sprintf('<span class="tc-lead tc-warning">'.__('WARNING','theme-check').'</span>: '.__('Both DOS and UNIX style line endings were found in the file %1$s. This causes a problem with SVN repositories and must be corrected before the theme can be accepted. Please change the file to use only one style of line endings.', 'theme-check'), '<strong>' . $filename . '</strong>' );
12
  $ret = false;
13
  }
14
  }
@@ -17,7 +17,7 @@ class LineEndingsCheck implements themecheck {
17
  if (preg_match("/\r\n/",$cssfile)) {
18
  if (preg_match("/[^\r]\n/",$cssfile)) {
19
  $filename = tc_filename( $css_key );
20
- $this->error[] = sprintf('<span class="tc-lead tc-warning">'.__('WARNING','theme-check').'</span>: '.__('Both DOS and UNIX style line endings were found in the file %1$s. This causes a problem with SVN repositories and must be corrected before the theme can be accepted. Please change the file to use only one style of line endings.', 'theme-check'), '<strong>' . $filename . '</strong>' );
21
  $ret = false;
22
  }
23
  }
@@ -28,7 +28,7 @@ class LineEndingsCheck implements themecheck {
28
  if (preg_match("/\r\n/",$othfile)) {
29
  if (preg_match("/[^\r]\n/",$othfile)) {
30
  $filename = tc_filename( $oth_key );
31
- $this->error[] = sprintf('<span class="tc-lead tc-warning">'.__('WARNING','theme-check').'</span>: '.__('Both DOS and UNIX style line endings were found in the file %1$s. This causes a problem with SVN repositories and must be corrected before the theme can be accepted. Please change the file to use only one style of line endings.', 'theme-check'), '<strong>' . $filename . '</strong>' );
32
  $ret = false;
33
  }
34
  }
8
  if (preg_match("/\r\n/",$phpfile)) {
9
  if (preg_match("/[^\r]\n/",$phpfile)) {
10
  $filename = tc_filename( $php_key );
11
+ $this->error[] = sprintf('<span class="tc-lead tc-required">'.__('REQUIRED','theme-check').'</span>: '.__('Both DOS and UNIX style line endings were found in the file %1$s. This causes a problem with SVN repositories and must be corrected before the theme can be accepted. Please change the file to use only one style of line endings.', 'theme-check'), '<strong>' . $filename . '</strong>' );
12
  $ret = false;
13
  }
14
  }
17
  if (preg_match("/\r\n/",$cssfile)) {
18
  if (preg_match("/[^\r]\n/",$cssfile)) {
19
  $filename = tc_filename( $css_key );
20
+ $this->error[] = sprintf('<span class="tc-lead tc-required">'.__('REQUIRED','theme-check').'</span>: '.__('Both DOS and UNIX style line endings were found in the file %1$s. This causes a problem with SVN repositories and must be corrected before the theme can be accepted. Please change the file to use only one style of line endings.', 'theme-check'), '<strong>' . $filename . '</strong>' );
21
  $ret = false;
22
  }
23
  }
28
  if (preg_match("/\r\n/",$othfile)) {
29
  if (preg_match("/[^\r]\n/",$othfile)) {
30
  $filename = tc_filename( $oth_key );
31
+ $this->error[] = sprintf('<span class="tc-lead tc-required">'.__('REQUIRED','theme-check').'</span>: '.__('Both DOS and UNIX style line endings were found in the file %1$s. This causes a problem with SVN repositories and must be corrected before the theme can be accepted. Please change the file to use only one style of line endings.', 'theme-check'), '<strong>' . $filename . '</strong>' );
32
  $ret = false;
33
  }
34
  }
checks/navmenu.php CHANGED
@@ -5,21 +5,63 @@ class NavMenuCheck implements themecheck {
5
 
6
  function check( $php_files, $css_files, $other_files ) {
7
 
8
- $ret = true;
 
 
 
9
 
10
- // combine all the php files into one string to make it easier to search
11
- $php = implode( ' ', $php_files );
12
  checkcount();
13
  if ( strpos( $php, 'nav_menu' ) === false ) {
14
- $this->error[] = '<span class="tc-lead tc-recommended">'.__('RECOMMENDED','theme-check').'</span>: '.__("No reference to nav_menu's was found in the theme. Note that if your theme has a menu bar, it is required to use the WordPress nav_menu functionality for it.", 'theme-check' );
15
  }
16
 
17
  // Look for add_theme_support( 'menus' ).
18
  checkcount();
19
  if ( preg_match( '/add_theme_support\s*\(\s?("|\')menus("|\')\s?\)/', $php ) ) {
20
  /* translators: 1: function found, 2: function to be used */
21
- $this->error[] = '<span class="tc-lead tc-required">' . __( 'REQUIRED', 'theme-check') . '</span>: ' . sprintf( __( 'Reference to %1$s was found in the theme. This should be removed and %2$s used instead.', 'theme-check' ), '<strong>add_theme_support( "menus" )</strong>', '<a href="https://developer.wordpress.org/reference/functions/register_nav_menus/">register_nav_menus()</a>' );
22
- $ret = false;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
23
  }
24
 
25
  return $ret;
@@ -28,4 +70,4 @@ class NavMenuCheck implements themecheck {
28
  function getError() { return $this->error; }
29
  }
30
 
31
- $themechecks[] = new NavMenuCheck;
5
 
6
  function check( $php_files, $css_files, $other_files ) {
7
 
8
+ $ret = true;
9
+ $name_check = false;
10
+
11
+ $php = implode( ' ', $php_files );
12
 
 
 
13
  checkcount();
14
  if ( strpos( $php, 'nav_menu' ) === false ) {
15
+ $this->error[] = '<span class="tc-lead tc-recommended">' . __( 'RECOMMENDED', 'theme-check' ) . '</span>: ' . __( "No reference to nav_menu's was found in the theme. Note that if your theme has a menu bar, it is required to use the WordPress nav_menu functionality for it.", 'theme-check' );
16
  }
17
 
18
  // Look for add_theme_support( 'menus' ).
19
  checkcount();
20
  if ( preg_match( '/add_theme_support\s*\(\s?("|\')menus("|\')\s?\)/', $php ) ) {
21
  /* translators: 1: function found, 2: function to be used */
22
+ $this->error[] = '<span class="tc-lead tc-required">' . __( 'REQUIRED', 'theme-check' ) . '</span>: ' . sprintf( __( 'Reference to %1$s was found in the theme. This should be removed and %2$s used instead.', 'theme-check' ), '<strong>add_theme_support( "menus" )</strong>', '<a href="https://developer.wordpress.org/reference/functions/register_nav_menus/">register_nav_menus()</a>' );
23
+ $ret = false;
24
+ }
25
+
26
+ foreach ( $php_files as $file_path => $file_content ) {
27
+ $filename = tc_filename( $file_path );
28
+
29
+ // We are checking for wp_nav_menu( specifically, to allow wp_nav_menu and wp_nav_menu_item in filters etc.
30
+ if ( strpos( $file_content, 'wp_nav_menu(' ) !== false ) {
31
+ $menu_part = explode( 'wp_nav_menu(', $file_content );
32
+ $menu_part = explode( ';', $menu_part[1] );
33
+
34
+ // If there is a menu, check for a theme location, which is required.
35
+ // Check if the arguments are placed outside wp_nav_menu.
36
+ checkcount();
37
+ if ( strpos( $menu_part[0], '$' ) !== false && strpos( $menu_part[0], 'theme_location' ) === false ) {
38
+ $menu_args = explode( '$', $menu_part[0], 1 );
39
+ $name = explode( ')', $menu_args[0] );
40
+ $this->error[] = '<span class="tc-lead tc-warning">' . __( 'WARNING', 'theme-check' ) . '</span>: ' . sprintf( __( 'A menu without a theme_location was found in %1$s. %2$s is used inside wp_nav_menu(). You must manually check if the theme_location is included.', 'theme-check' ),
41
+ '<strong>' . $filename . '</strong>',
42
+ '<code>' . $name[0] . '</code>'
43
+ );
44
+ $name_check = true;
45
+ } else {
46
+ checkcount();
47
+ if ( strpos( $menu_part[0], 'theme_location' ) === false ) {
48
+ $this->error[] = '<span class="tc-lead tc-required">' . __( 'REQUIRED', 'theme-check' ) . '</span>: ' . sprintf( __( 'A menu without a theme_location was found in %1$s.', 'theme-check' ),
49
+ '<strong>' . $filename . '</strong>'
50
+ );
51
+ $ret = false;
52
+ $name_check = true;
53
+ }
54
+ }
55
+
56
+ // We only need to warn for the menu name if theme location is not set.
57
+ checkcount();
58
+ if ( $name_check === true && preg_match( '/("|\')menu("|\').*?=>/', $menu_part[0] ) ) {
59
+ $this->error[] = '<span class="tc-lead tc-required">' . __( 'REQUIRED', 'theme-check' ) . '</span>: ' . sprintf( __( 'A menu name is being used for a menu in %1$s. By using menu name, the menu would be required to have the exact same name in the WordPress admin area. Use a theme_location instead.', 'theme-check' ),
60
+ '<strong>' . $filename . '</strong>'
61
+ );
62
+ $ret = false;
63
+ }
64
+ }
65
  }
66
 
67
  return $ret;
70
  function getError() { return $this->error; }
71
  }
72
 
73
+ $themechecks[] = new NavMenuCheck();
checks/nongplsites.php ADDED
@@ -0,0 +1,46 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Checks if the theme includes resoruces from websites that does not use a GPL compatible license.
4
+ */
5
+ class NonGPLCheck implements themecheck {
6
+ protected $error = array();
7
+
8
+ function check( $php_files, $css_files, $other_files ) {
9
+
10
+ $ret = true;
11
+ $code = implode( ' ', $other_files ); // The references are usually in the readme.
12
+
13
+ checkcount();
14
+
15
+ $link_list = array(
16
+ 'unsplash' => 'https://unsplash.com/license',
17
+ 'pixabay' => 'https://pixabay.com/service/license/',
18
+ 'freeimages' => 'https://www.freeimages.com/license',
19
+ 'photopin' => 'http://photopin.com/faq',
20
+ 'splitshire' => 'https://www.splitshire.com/licence/',
21
+ 'freepik' => 'https://www.freepikcompany.com/legal',
22
+ 'flaticon' => 'https://www.freepikcompany.com/legal',
23
+ 'pikwizard' => 'https://pikwizard.com/standard-license',
24
+ 'stock.adobe' => 'https://stock.adobe.com/license-terms',
25
+ 'elements.envato' => 'https://elements.envato.com/license-terms',
26
+ 'undraw.co' => 'https://undraw.co/licenses',
27
+ );
28
+
29
+ foreach ( $link_list as $link_slug => $link_url ) {
30
+ if ( false !== stripos( $code, $link_slug ) ) {
31
+ $this->error[] = '<span class="tc-lead tc-required">' . __( 'REQUIRED', 'theme-check' ) . '</span>: ' .
32
+ sprintf(
33
+ __( 'Found a reference to %s. Images from this website does not use a license that is compatible with GPL.', 'theme-check' ),
34
+ '<code>' . esc_html( $link_slug ) . '</code>'
35
+ )
36
+ . ' <a href="' . esc_url( $link_url ) . '" target="_blank">' . __( 'View license (opens in a new window).', 'theme-check' ) . '</a>';
37
+ }
38
+ }
39
+
40
+ return $ret;
41
+ }
42
+
43
+ function getError() { return $this->error; }
44
+ }
45
+
46
+ $themechecks[] = new NonGPLCheck;
checks/nonprintable.php CHANGED
@@ -10,10 +10,10 @@ class NonPrintableCheck implements themecheck {
10
  // 09 = tab
11
  // 0A = line feed
12
  // 0D = new line
13
- if ( preg_match('/[\x00-\x08\x0B-\x0C\x0E-\x1F\x80-\xFF]/', $content, $matches ) ) {
14
  $filename = tc_filename( $name );
15
- $non_print = tc_preg( '/[\x00-\x08\x0B-\x0C\x0E-\x1F\x80-\xFF]/', $name );
16
- $this->error[] = sprintf('<span class="tc-lead tc-info">'.__('INFO','theme-check').'</span>: '.__('Non-printable characters were found in the %1$s file. You may want to check this file for errors.%2$s', 'theme-check'), '<strong>' . $filename . '</strong>', $non_print);
17
  }
18
  }
19
 
@@ -24,4 +24,4 @@ class NonPrintableCheck implements themecheck {
24
  function getError() { return $this->error; }
25
  }
26
 
27
- $themechecks[] = new NonPrintableCheck;
10
  // 09 = tab
11
  // 0A = line feed
12
  // 0D = new line
13
+ if ( preg_match('/[\x00-\x08\x0B-\x0C\x0E-\x1F]/', $content, $matches ) ) {
14
  $filename = tc_filename( $name );
15
+ $non_print = tc_preg( '/[\x00-\x08\x0B-\x0C\x0E-\x1F]/', $name );
16
+ $this->error[] = sprintf('<span class="tc-lead tc-warning">' . __( 'WARNING', 'theme-check' ) . '</span>: ' . __( 'Non-printable characters were found in the %1$s file. You may want to check this file for errors.%2$s', 'theme-check' ), '<strong>' . $filename . '</strong>', $non_print);
17
  }
18
  }
19
 
24
  function getError() { return $this->error; }
25
  }
26
 
27
+ $themechecks[] = new NonPrintableCheck;
checks/phpshort.php CHANGED
@@ -12,7 +12,6 @@ class PHPShortTagsCheck implements themecheck {
12
  $filename = tc_filename( $php_key );
13
  $grep = tc_preg( '/<\?(\=?)(?!php|xml)/', $php_key );
14
  $this->error[] = sprintf('<span class="tc-lead tc-warning">'.__('WARNING','theme-check').'</span>: '.__('Found PHP short tags in file %1$s.%2$s', 'theme-check'), '<strong>' . $filename . '</strong>', $grep);
15
- $ret = false;
16
  }
17
  }
18
 
@@ -22,4 +21,4 @@ class PHPShortTagsCheck implements themecheck {
22
  function getError() { return $this->error; }
23
  }
24
 
25
- $themechecks[] = new PHPShortTagsCheck;
12
  $filename = tc_filename( $php_key );
13
  $grep = tc_preg( '/<\?(\=?)(?!php|xml)/', $php_key );
14
  $this->error[] = sprintf('<span class="tc-lead tc-warning">'.__('WARNING','theme-check').'</span>: '.__('Found PHP short tags in file %1$s.%2$s', 'theme-check'), '<strong>' . $filename . '</strong>', $grep);
 
15
  }
16
  }
17
 
21
  function getError() { return $this->error; }
22
  }
23
 
24
+ $themechecks[] = new PHPShortTagsCheck;
checks/plugin-territory.php CHANGED
@@ -1,14 +1,29 @@
1
- <?php
2
  /**
3
  * Checks for Plugin Territory Guidelines.
4
  *
5
- * See http://make.wordpress.org/themes/guidelines/guidelines-plugin-territory/
6
  */
7
 
 
 
 
8
  class Plugin_Territory implements themecheck {
 
 
 
 
 
9
  protected $error = array();
10
 
11
- function check( $php_files, $css_files, $other_files ) {
 
 
 
 
 
 
 
12
  $ret = true;
13
  $php = implode( ' ', $php_files );
14
 
@@ -16,26 +31,107 @@ class Plugin_Territory implements themecheck {
16
  $forbidden_functions = array(
17
  'register_post_type',
18
  'register_taxonomy',
 
 
19
  );
20
 
21
  foreach ( $forbidden_functions as $function ) {
22
  checkcount();
23
  if ( preg_match( '/[\s?]' . $function . '\s?\(/', $php ) ) {
24
- $this->error[] = '<span class="tc-lead tc-required">' . __( 'REQUIRED', 'theme-check').'</span>: ' . sprintf( __( 'The theme uses the %s function, which is plugin-territory functionality.', 'theme-check' ), '<strong>' . esc_html( $function ) . '()</strong>' ) ;
25
- $ret = false;
26
  }
27
  }
28
 
29
  // Shortcodes can't be used in the post content, so warn about them.
30
- if ( false !== strpos( $php, 'add_shortcode' ) ) {
31
  checkcount();
32
- $this->error[] = '<span class="tc-lead tc-warning">' . __( 'WARNING', 'theme-check').'</span>: ' . sprintf( __( 'The theme uses the %s function. Custom post-content shortcodes are plugin-territory functionality.', 'theme-check' ), '<strong>add_shortcode()</strong>' ) ;
33
- $ret = false;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
34
  }
35
 
36
  return $ret;
37
  }
38
 
39
- function getError() { return $this->error; }
 
 
 
 
 
 
 
40
  }
41
- $themechecks[] = new Plugin_Territory;
 
1
+ <?php // phpcs:ignore WordPress.Files.FileName
2
  /**
3
  * Checks for Plugin Territory Guidelines.
4
  *
5
+ * @link https://make.wordpress.org/themes/handbook/review/required/#presentation-vs-functionality
6
  */
7
 
8
+ /**
9
+ * Checks for Plugin Territory
10
+ */
11
  class Plugin_Territory 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
  $ret = true;
28
  $php = implode( ' ', $php_files );
29
 
31
  $forbidden_functions = array(
32
  'register_post_type',
33
  'register_taxonomy',
34
+ 'wp_add_dashboard_widget',
35
+ 'register_block_type',
36
  );
37
 
38
  foreach ( $forbidden_functions as $function ) {
39
  checkcount();
40
  if ( preg_match( '/[\s?]' . $function . '\s?\(/', $php ) ) {
41
+ $this->error[] = '<span class="tc-lead tc-required">' . __( 'REQUIRED', 'theme-check' ) . '</span>: ' . sprintf( __( 'The theme uses the %s function, which is plugin-territory functionality.', 'theme-check' ), '<strong>' . esc_html( $function ) . '()</strong>' );
42
+ $ret = false;
43
  }
44
  }
45
 
46
  // Shortcodes can't be used in the post content, so warn about them.
47
+ if ( false !== strpos( $php, 'add_shortcode(' ) ) {
48
  checkcount();
49
+ $this->error[] = '<span class="tc-lead tc-required">' . __( 'REQUIRED', 'theme-check' ) . '</span>: ' . sprintf( __( 'The theme uses the %s function. Custom post-content shortcodes are plugin-territory functionality.', 'theme-check' ), '<strong>add_shortcode()</strong>' );
50
+ $ret = false;
51
+ }
52
+
53
+ // Hooks (actions & filters) that are required to be removed from the theme.
54
+ $forbidden_hooks = array(
55
+ 'filter' => array(
56
+ 'mime_types',
57
+ 'upload_mimes',
58
+ 'user_contactmethods',
59
+ ),
60
+ 'action' => array(
61
+ 'wp_dashboard_setup',
62
+ ),
63
+ );
64
+
65
+ foreach ( $forbidden_hooks as $type => $hooks ) {
66
+ foreach ( $hooks as $hook ) {
67
+ checkcount();
68
+ if ( preg_match( '/[\s?]add_' . $type . '\s*\(\s*([\'"])' . $hook . '([\'"])\s*,/', $php ) ) {
69
+ $this->error[] = '<span class="tc-lead tc-required">' . __( 'REQUIRED', 'theme-check' ) . '</span>: ' . sprintf( __( 'The theme uses the %1$s %2$s, which is plugin-territory functionality.', 'theme-check' ), '<strong>' . esc_html( $hook ) . '</strong>', esc_html( $type ) );
70
+ $ret = false;
71
+ }
72
+ }
73
+ }
74
+
75
+ /**
76
+ * Check for removal of non presentational hooks.
77
+ * Removing emojis is also not allowed.
78
+ */
79
+ $blacklist = array(
80
+ 'wp_head' => array(
81
+ 'wp_generator', // @link https://developer.wordpress.org/reference/functions/wp_generator/
82
+ 'feed_links', // @link https://developer.wordpress.org/reference/functions/feed_links/
83
+ 'feed_links_extra', // @link https://developer.wordpress.org/reference/functions/feed_links_extra/
84
+ 'print_emoji_detection_script', // @link https://developer.wordpress.org/reference/functions/print_emoji_detection_script/
85
+ 'wp_resource_hints', // @link https://developer.wordpress.org/reference/functions/wp_resource_hints/
86
+ 'adjacent_posts_rel_link_wp_head', // @link https://developer.wordpress.org/reference/functions/adjacent_posts_rel_link_wp_head/
87
+ 'wp_shortlink_wp_head', // @link https://developer.wordpress.org/reference/functions/wp_shortlink_wp_head/
88
+ '_admin_bar_bump_cb', // @link https://developer.wordpress.org/reference/functions/_admin_bar_bump_cb/
89
+ 'rsd_link', // @link https://developer.wordpress.org/reference/functions/rsd_link/
90
+ 'rest_output_link_wp_head', // @link https://developer.wordpress.org/reference/functions/rest_output_link_wp_head/
91
+ 'wp_oembed_add_discovery_links', // @link https://developer.wordpress.org/reference/functions/wp_oembed_add_discovery_links/
92
+ 'wp_oembed_add_host_js', // @link https://developer.wordpress.org/reference/functions/wp_oembed_add_host_js/
93
+ 'rel_canonical', // @link https://developer.wordpress.org/reference/functions/rel_canonical/
94
+ ),
95
+ 'wp_print_styles' => array(
96
+ 'print_emoji_styles', // @link https://developer.wordpress.org/reference/functions/print_emoji_styles/
97
+ ),
98
+ 'admin_print_scripts' => array(
99
+ 'print_emoji_detection_script', //@link https://developer.wordpress.org/reference/functions/print_emoji_detection_script/
100
+ ),
101
+ 'admin_print_styles' => array(
102
+ 'print_emoji_styles', // @link https://developer.wordpress.org/reference/functions/print_emoji_styles/
103
+ ),
104
+ 'template_redirect' => array(
105
+ 'rest_output_link_header', // @link https://developer.wordpress.org/reference/functions/rest_output_link_header/
106
+ 'wp_shortlink_header', // @link https://developer.wordpress.org/reference/functions/wp_shortlink_header/
107
+ 'redirect_canonical', // @link https://developer.wordpress.org/reference/functions/redirect_canonical/
108
+ ),
109
+ );
110
+
111
+ foreach ( $blacklist as $hook => $functions ) {
112
+ foreach ( $functions as $function ) {
113
+ checkcount();
114
+ if ( preg_match( '/[\s?]remove_action\s*\(\s*([\'"])' . $hook . '([\'"])\s*,\s*([\'"])' . $function . '([\'"])/', $php ) ) {
115
+ $this->error[] = '<span class="tc-lead tc-required">' . __( 'REQUIRED', 'theme-check' ) . '</span>: ' . sprintf( __( 'The theme uses <strong>remove_action %1$s %2$s</strong>, which is plugin-territory functionality.', 'theme-check' ),
116
+ esc_html( $hook ),
117
+ esc_html( $function )
118
+ );
119
+ $ret = false;
120
+ }
121
+ }
122
  }
123
 
124
  return $ret;
125
  }
126
 
127
+ /**
128
+ * Get error messages from the checks.
129
+ *
130
+ * @return array Error message.
131
+ */
132
+ public function getError() {
133
+ return $this->error;
134
+ }
135
  }
136
+
137
+ $themechecks[] = new Plugin_Territory();
checks/screenshot.php CHANGED
@@ -18,13 +18,15 @@ class Screenshot_Checks implements themecheck {
18
  foreach ( $other_files as $other_key => $otherfile ) {
19
 
20
  if ( ( basename( $other_key ) === 'screenshot.png' || basename( $other_key ) === 'screenshot.jpg' ) && preg_match( '/.*themes\/[^\/]*\/screenshot\.(png|jpg)/', $other_key ) ) {
21
- // we have or screenshot!
22
  $image = getimagesize( $other_key );
23
  if ( $image[0] > 1200 || $image[1] > 900 ) {
24
- $this->error[] = sprintf('<span class="tc-lead tc-recommended">'. __( 'RECOMMENDED','theme-check' ) . '</span>: ' . __( 'Screenshot is wrong size! Detected: %1$sx%2$spx. Maximum allowed size is 1200x900px.', 'theme-check' ), '<strong>' . $image[0], $image[1] . '</strong>' );
 
25
  }
26
  if ( $image[1] / $image[0] != 0.75 ) {
27
- $this->error[] = '<span class="tc-lead tc-recommended">'.__('RECOMMENDED','theme-check').'</span>: '.__('Screenshot dimensions are wrong! Ratio of width to height should be 4:3.', 'theme-check');
 
28
  }
29
  if ( $image[0] != 1200 || $image[1] != 900 ) {
30
  $this->error[] = '<span class="tc-lead tc-recommended">'.__('RECOMMENDED','theme-check').'</span>: '.__('Screenshot size should be 1200x900, to account for HiDPI displays. Any 4:3 image size is acceptable, but 1200x900 is preferred.', 'theme-check');
@@ -32,7 +34,7 @@ class Screenshot_Checks implements themecheck {
32
  }
33
  }
34
  } else {
35
- $this->error[] = '<span class="tc-lead tc-warning">'.__('WARNING','theme-check').'</span>: '.__('No screenshot detected! Please include a screenshot.png or screenshot.jpg.', 'theme-check' );
36
  $ret = false;
37
  }
38
  return $ret;
18
  foreach ( $other_files as $other_key => $otherfile ) {
19
 
20
  if ( ( basename( $other_key ) === 'screenshot.png' || basename( $other_key ) === 'screenshot.jpg' ) && preg_match( '/.*themes\/[^\/]*\/screenshot\.(png|jpg)/', $other_key ) ) {
21
+ // we have our screenshot!
22
  $image = getimagesize( $other_key );
23
  if ( $image[0] > 1200 || $image[1] > 900 ) {
24
+ $this->error[] = sprintf('<span class="tc-lead tc-required">'. __( 'REQUIRED','theme-check' ) . '</span>: ' . __( 'Screenshot is wrong size! Detected: %1$sx%2$spx. Maximum allowed size is 1200x900px.', 'theme-check' ), '<strong>' . $image[0], $image[1] . '</strong>' );
25
+ $ret = false;
26
  }
27
  if ( $image[1] / $image[0] != 0.75 ) {
28
+ $this->error[] = '<span class="tc-lead tc-required">'.__('REQUIRED','theme-check').'</span>: '.__('Screenshot dimensions are wrong! Ratio of width to height should be 4:3.', 'theme-check');
29
+ $ret = false;
30
  }
31
  if ( $image[0] != 1200 || $image[1] != 900 ) {
32
  $this->error[] = '<span class="tc-lead tc-recommended">'.__('RECOMMENDED','theme-check').'</span>: '.__('Screenshot size should be 1200x900, to account for HiDPI displays. Any 4:3 image size is acceptable, but 1200x900 is preferred.', 'theme-check');
34
  }
35
  }
36
  } else {
37
+ $this->error[] = '<span class="tc-lead tc-required">'.__('REQUIRED','theme-check').'</span>: '.__('No screenshot detected! Please include a screenshot.png or screenshot.jpg.', 'theme-check' );
38
  $ret = false;
39
  }
40
  return $ret;
checks/siteurl.php ADDED
@@ -0,0 +1,54 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php // phpcs:ignore WordPress.Files.FileName
2
+ /**
3
+ * Checks if site_url is used, and adds an info.
4
+ *
5
+ * @link https://developer.wordpress.org/reference/functions/site_url/
6
+ */
7
+
8
+ /**
9
+ * Check for site_url
10
+ */
11
+ class SiteUrlCheck 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
+ $ret = true;
29
+
30
+ checkcount();
31
+ foreach ( $php_files as $file_path => $file_content ) {
32
+ $filename = tc_filename( $file_path );
33
+
34
+ if ( strpos( $file_content, 'site_url' ) !== false ) {
35
+ $this->error[] = sprintf(
36
+ '<span class="tc-lead tc-info">' . __( 'INFO', 'theme-check' ) . '</span>: ' . __( 'site_url() or get_site_url() was found in %1$s. site_url() references the URL where the WordPress files are located. Use home_url() if the intention is to point to the site address (home page), and in the search form.', 'theme-check' ),
37
+ '<strong>' . $filename . '</strong>'
38
+ );
39
+ }
40
+ }
41
+ return $ret;
42
+ }
43
+
44
+ /**
45
+ * Get error messages from the checks.
46
+ *
47
+ * @return array Error message.
48
+ */
49
+ public function getError() {
50
+ return $this->error;
51
+ }
52
+ }
53
+
54
+ $themechecks[] = new SiteUrlCheck();
checks/style_needed.php CHANGED
@@ -15,6 +15,8 @@ class Style_Needed implements themecheck {
15
  '[ \t\/*#]*License:' => __( '<strong>License:</strong> is missing from your style.css header.', 'theme-check' ),
16
  '[ \t\/*#]*License URI:' => __( '<strong>License URI:</strong> is missing from your style.css header.', 'theme-check' ),
17
  '[ \t\/*#]*Text Domain:' => __( '<strong>Text Domain:</strong> is missing from your style.css header.', 'theme-check' ),
 
 
18
  '\.sticky' => __( '<strong>.sticky</strong> css class is needed in your theme css.', 'theme-check' ),
19
  '\.bypostauthor' => __( '<strong>.bypostauthor</strong> css class is needed in your theme css.', 'theme-check' ),
20
  '\.alignleft' => __( '<strong>.alignleft</strong> css class is needed in your theme css.', 'theme-check' ),
15
  '[ \t\/*#]*License:' => __( '<strong>License:</strong> is missing from your style.css header.', 'theme-check' ),
16
  '[ \t\/*#]*License URI:' => __( '<strong>License URI:</strong> is missing from your style.css header.', 'theme-check' ),
17
  '[ \t\/*#]*Text Domain:' => __( '<strong>Text Domain:</strong> is missing from your style.css header.', 'theme-check' ),
18
+ '[ \t\/*#]*Tested up to:' => __( '<strong>Tested up to:</strong> is missing from your style.css header. Also, this should be numbers only, so <em>5.0</em> and not <em>WP 5.0</em>', 'theme-check' ),
19
+ '[ \t\/*#]*Requires PHP:' => __( '<strong>Requires PHP:</strong> is missing from your style.css header.', 'theme-check' ),
20
  '\.sticky' => __( '<strong>.sticky</strong> css class is needed in your theme css.', 'theme-check' ),
21
  '\.bypostauthor' => __( '<strong>.bypostauthor</strong> css class is needed in your theme css.', 'theme-check' ),
22
  '\.alignleft' => __( '<strong>.alignleft</strong> css class is needed in your theme css.', 'theme-check' ),
checks/style_tags.php CHANGED
@@ -9,51 +9,55 @@ class Style_Tags implements themecheck {
9
  $filenames = array();
10
 
11
  foreach( $css_files as $cssfile => $content ) {
12
- if ( basename( $cssfile ) === 'style.css' ) $data = get_theme_data_from_contents( $content );
13
- }
14
 
15
- if ( !$data[ 'Tags' ] ) {
16
- $this->error[] = '<span class="tc-lead tc-recommended">' . __('RECOMMENDED','theme-check') . '</span>: ' . __( '<strong>Tags:</strong> is either empty or missing in style.css header.', 'theme-check' );
17
- return $ret;
18
- }
19
- $deprecated_tags = array("flexible-width","fixed-width","black","blue","brown","gray","green","orange","pink","purple","red","silver","tan","white","yellow","dark","light","fixed-layout","fluid-layout","responsive-layout","blavatar","holiday","photoblogging","seasonal");
20
- $allowed_tags = array('grid-layout',"one-column","two-columns","three-columns","four-columns","left-sidebar","right-sidebar","wide-blocks","flexible-header",'footer-widgets',"accessibility-ready","block-styles","buddypress","custom-background","custom-colors","custom-header","custom-menu","custom-logo","editor-style","featured-image-header","featured-images","front-page-post-form","full-width-template","microformats","post-formats","rtl-language-support","sticky-post","theme-options","threaded-comments","translation-ready",'blog','e-commerce','education','entertainment','food-and-drink','holiday','news','photography','portfolio');
21
- $subject_tags = array('blog','e-commerce','education','entertainment','food-and-drink','holiday','news','photography','portfolio');
22
- $subject_tags_count = 0;
23
- $subject_tags_name = "";
 
24
 
25
- foreach( $data[ 'Tags' ] as $tag ) {
26
 
27
- if ( strpos( strtolower( $tag ), "accessibility-ready") !== false ) {
28
- $this->error[] = '<span class="tc-lead tc-info">'. __('INFO','theme-check'). '</span>: ' . __( 'Themes that use the tag accessibility-ready will need to undergo an accessibility review.','theme-check' ) . ' ' . __('See <a href="https://make.wordpress.org/themes/handbook/review/accessibility/">https://make.wordpress.org/themes/handbook/review/accessibility/</a>', 'theme-check' );
29
- }
30
 
31
- if ( ! in_array( strtolower( $tag ), $allowed_tags ) ) {
32
- if ( in_array( strtolower( $tag ), $deprecated_tags ) ) {
33
- $this->error[] = '<span class="tc-lead tc-warning">'. __('WARNING','theme-check'). '</span>: ' . sprintf( __('The tag %s has been deprecated, please remove it from your style.css header.', 'theme-check'), '<strong>' . $tag . '</strong>' );
34
- } else {
35
- $this->error[] = '<span class="tc-lead tc-warning">'. __('WARNING','theme-check'). '</span>: ' . sprintf( __('Found wrong tag, remove %s from your style.css header.', 'theme-check'), '<strong>' . $tag . '</strong>' );
36
- $ret = false;
37
- }
38
- }
 
39
 
40
- if ( in_array( strtolower( $tag ), $subject_tags ) ) {
41
- $subject_tags_name .= strtolower( $tag ) . ', ';
42
- $subject_tags_count++;
43
- }
 
 
 
 
 
 
 
 
44
 
45
- if ( in_array( strtolower( $tag ), $allowed_tags ) ) {
46
- if ( count( array_keys ($data[ 'Tags' ], $tag ) ) > 1) {
47
- $this->error[] = '<span class="tc-lead tc-required">'. __('REQUIRED','theme-check'). '</span>: ' . sprintf( __('The tag %s is being used more than once, please remove it from your style.css header.', 'theme-check'), '<strong>' . $tag . '</strong>' );
48
- $ret = false;
49
  }
50
  }
51
-
52
- }
53
-
54
- if ( $subject_tags_count > 3 ) {
55
- $this->error[] = '<span class="tc-lead tc-required">'. __('REQUIRED','theme-check'). '</span>: ' . sprintf( __('A maximum of 3 subject tags are allowed. The theme has %1$u subjects tags ( %2$s ). Please remove the subject tags, which do not directly apply to the theme.', 'theme-check'), $subject_tags_count, '<strong>' . rtrim( $subject_tags_name, ', ' ) . '</strong>' ) . ' ' . '<a target="_blank" href="https://make.wordpress.org/themes/handbook/review/required/theme-tags/">' . __( 'See Theme Tags', 'theme-check' ) . '</a>';
56
- $ret = false;
57
  }
58
 
59
  return $ret;
9
  $filenames = array();
10
 
11
  foreach( $css_files as $cssfile => $content ) {
12
+ if ( basename( $cssfile ) === 'style.css' ) {
13
+ $data = get_theme_data_from_contents( $content );
14
 
15
+ if ( !$data[ 'Tags' ] ) {
16
+ $this->error[] = '<span class="tc-lead tc-recommended">' . __('RECOMMENDED','theme-check') . '</span>: ' . __( '<strong>Tags:</strong> is either empty or missing in style.css header.', 'theme-check' )
17
+ . ' ('. basename( dirname( $cssfile)) . ')';
18
+ }
19
+ else {
20
+ $deprecated_tags = array("flexible-width","fixed-width","black","blue","brown","gray","green","orange","pink","purple","red","silver","tan","white","yellow","dark","light","fixed-layout","fluid-layout","responsive-layout","blavatar","holiday","photoblogging","seasonal");
21
+ $allowed_tags = array('grid-layout',"one-column","two-columns","three-columns","four-columns","left-sidebar","right-sidebar","wide-blocks","flexible-header",'footer-widgets',"accessibility-ready","block-styles","buddypress","custom-background","custom-colors","custom-header","custom-menu","custom-logo","editor-style","featured-image-header","featured-images","front-page-post-form","full-width-template","microformats","post-formats","rtl-language-support","sticky-post","theme-options","threaded-comments","translation-ready",'blog','e-commerce','education','entertainment','food-and-drink','holiday','news','photography','portfolio');
22
+ $subject_tags = array('blog','e-commerce','education','entertainment','food-and-drink','holiday','news','photography','portfolio');
23
+ $subject_tags_count = 0;
24
+ $subject_tags_name = "";
25
 
26
+ foreach( $data[ 'Tags' ] as $tag ) {
27
 
28
+ if ( strpos( strtolower( $tag ), "accessibility-ready") !== false ) {
29
+ $this->error[] = '<span class="tc-lead tc-info">'. __('INFO','theme-check'). '</span>: ' . __( 'Themes that use the tag accessibility-ready will need to undergo an accessibility review.','theme-check' ) . ' ' . __('See <a href="https://make.wordpress.org/themes/handbook/review/accessibility/">https://make.wordpress.org/themes/handbook/review/accessibility/</a>', 'theme-check' );
30
+ }
31
 
32
+ if ( ! in_array( strtolower( $tag ), $allowed_tags ) ) {
33
+ if ( in_array( strtolower( $tag ), $deprecated_tags ) ) {
34
+ $this->error[] = '<span class="tc-lead tc-required">'. __('REQUIRED','theme-check'). '</span>: ' . sprintf( __('The tag %s has been deprecated, please remove it from your style.css header.', 'theme-check'), '<strong>' . $tag . '</strong>' );
35
+ $ret = false;
36
+ } else {
37
+ $this->error[] = '<span class="tc-lead tc-required">'. __('REQUIRED','theme-check'). '</span>: ' . sprintf( __('Found wrong tag, remove %s from your style.css header.', 'theme-check'), '<strong>' . $tag . '</strong>' );
38
+ $ret = false;
39
+ }
40
+ }
41
 
42
+ if ( in_array( strtolower( $tag ), $subject_tags ) ) {
43
+ $subject_tags_name .= strtolower( $tag ) . ', ';
44
+ $subject_tags_count++;
45
+ }
46
+
47
+ if ( in_array( strtolower( $tag ), $allowed_tags ) ) {
48
+ if ( count( array_keys ($data[ 'Tags' ], $tag ) ) > 1) {
49
+ $this->error[] = '<span class="tc-lead tc-required">'. __('REQUIRED','theme-check'). '</span>: ' . sprintf( __('The tag %s is being used more than once, please remove it from your style.css header.', 'theme-check'), '<strong>' . $tag . '</strong>' );
50
+ $ret = false;
51
+ }
52
+ }
53
+ }
54
 
55
+ if ( $subject_tags_count > 3 ) {
56
+ $this->error[] = '<span class="tc-lead tc-required">'. __('REQUIRED','theme-check'). '</span>: ' . sprintf( __('A maximum of 3 subject tags are allowed. The theme has %1$u subjects tags ( %2$s ). Please remove the subject tags, which do not directly apply to the theme.', 'theme-check'), $subject_tags_count, '<strong>' . rtrim( $subject_tags_name, ', ' ) . '</strong>' ) . ' ' . '<a target="_blank" href="https://make.wordpress.org/themes/handbook/review/required/theme-tags/">' . __( 'See Theme Tags', 'theme-check' ) . '</a>';
57
+ $ret = false;
58
+ }
59
  }
60
  }
 
 
 
 
 
 
61
  }
62
 
63
  return $ret;
checks/textdomain.php CHANGED
@@ -140,7 +140,7 @@ class TextDomainCheck implements themecheck {
140
  }
141
 
142
  if ( $domainscount > 1 ) {
143
- $this->error[] = '<span class="tc-lead tc-warning">' . __( 'Warning', 'theme-check' ) . '</span>: '
144
  . __( 'More than one text-domain is being used in this theme. This means the theme will not be compatible with WordPress.org language packs.', 'theme-check' )
145
  . '<br>'
146
  . sprintf( __( 'The domains found are %s', 'theme-check'), '<strong>' . $domainlist . '</strong>' );
140
  }
141
 
142
  if ( $domainscount > 1 ) {
143
+ $this->error[] = '<span class="tc-lead tc-warning">' . __( 'WARNING', 'theme-check' ) . '</span>: '
144
  . __( 'More than one text-domain is being used in this theme. This means the theme will not be compatible with WordPress.org language packs.', 'theme-check' )
145
  . '<br>'
146
  . sprintf( __( 'The domains found are %s', 'theme-check'), '<strong>' . $domainlist . '</strong>' );
checks/title.php CHANGED
@@ -5,49 +5,59 @@
5
  * Is there a call to wp_title()?
6
  * There can't be any hardcoded text in the <title> tag.
7
  *
8
- * See: http://make.wordpress.org/themes/guidelines/guidelines-theme-check/
9
  */
10
  class Title_Checks implements themecheck {
11
- protected $error = array();
12
 
13
  function check( $php_files, $css_files, $other_files ) {
14
  $ret = true;
15
  $php = implode( ' ', $php_files );
16
 
17
- // Look for add_theme_support( 'title-tag' ) first
18
  $titletag = true;
19
  if ( ! preg_match( '#add_theme_support\s?\(\s?[\'|"]title-tag#', $php ) ) {
20
- $this->error[] = '<span class="tc-lead tc-required">'.__('REQUIRED','theme-check').'</span>: '.__('No reference to <strong>add_theme_support( "title-tag" )</strong> was found in the theme.', 'theme-check' );
21
- $titletag = false;
22
- $ret = false;
23
  }
24
 
25
- // Look for <title> and </title> tags.
26
- checkcount();
27
- if ( ( 0 <= strpos( $php, '<title>' ) || 0 <= strpos( $php, '</title>' ) ) && !$titletag ) {
28
- $this->error[] = '<span class="tc-lead tc-required">' . __( 'REQUIRED', 'theme-check').'</span>: ' . __( 'The theme must not used the <strong>&lt;title&gt;</strong> tags.', 'theme-check' );
29
- $ret = false;
30
- }
31
 
32
- // Check whether there is a call to wp_title()
33
- checkcount();
34
- if ( 0 <= strpos( $php, 'wp_title(' ) && !$titletag ) {
35
- $this->error[] = '<span class="tc-lead tc-required">' . __( 'REQUIRED', 'theme-check').'</span>: ' . __( 'The theme must not call to <strong>wp_title()</strong>.', 'theme-check' );
36
- $ret = false;
37
- }
38
 
39
- //Check whether the the <title> tag contains something besides a call to wp_title()
40
- checkcount();
 
 
 
 
 
 
41
 
42
- foreach ( $php_files as $file_path => $file_content ) {
43
- // Look for anything that looks like <svg>...</svg> and exclude it (inline svg's have titles too)
44
- $file_content = preg_replace('/<svg.*>.*<\/svg>/s', '', $file_content);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
45
 
46
- // First looks ahead to see of there's <title>...</title>
47
- // Then performs a negative look ahead for <title> wp_title(...); </title>
48
  if ( preg_match( '/(?=<title>(.*)<\/title>)(?!<title>\s*<\?php\s*wp_title\([^\)]*\);?\s*\?>\s*<\/title>)/s', $file_content ) ) {
49
- $this->error[] = '<span class="tc-lead tc-required">' . __( 'REQUIRED', 'theme-check').'</span>: ' . __( 'The <strong>&lt;title&gt;</strong> tags can only contain a call to <strong>wp_title()</strong>. Use the <strong>wp_title filter</strong> to modify the output', 'theme-check' );
50
- $ret = false;
 
 
51
  }
52
  }
53
 
@@ -57,4 +67,4 @@ class Title_Checks implements themecheck {
57
  function getError() { return $this->error; }
58
  }
59
 
60
- $themechecks[] = new Title_Checks;
5
  * Is there a call to wp_title()?
6
  * There can't be any hardcoded text in the <title> tag.
7
  *
8
+ * See: https://make.wordpress.org/themes/handbook/review/required/theme-check-plugin/
9
  */
10
  class Title_Checks implements themecheck {
11
+ protected $error = array();
12
 
13
  function check( $php_files, $css_files, $other_files ) {
14
  $ret = true;
15
  $php = implode( ' ', $php_files );
16
 
17
+ // Look for add_theme_support( 'title-tag' ) first.
18
  $titletag = true;
19
  if ( ! preg_match( '#add_theme_support\s?\(\s?[\'|"]title-tag#', $php ) ) {
20
+ $this->error[] = '<span class="tc-lead tc-required">' . __( 'REQUIRED', 'theme-check' ) . '</span>: ' . __( 'No reference to <strong>add_theme_support( "title-tag" )</strong> was found in the theme.', 'theme-check' );
21
+ $titletag = false;
22
+ $ret = false;
23
  }
24
 
25
+ foreach ( $php_files as $file_path => $file_content ) {
 
 
 
 
 
26
 
27
+ $filename = tc_filename( $file_path );
 
 
 
 
 
28
 
29
+ // Look for <title> and </title> tags.
30
+ checkcount();
31
+ if ( ( 0 <= strpos( $php, '<title>' ) || 0 <= strpos( $php, '</title>' ) ) && ! $titletag ) {
32
+ $this->error[] = '<span class="tc-lead tc-required">' . __( 'REQUIRED', 'theme-check' ) . '</span>: ' . sprintf( __( 'The theme must not use the <strong>&lt;title&gt;</strong> tags. Found the tag in %1$s.', 'theme-check' ),
33
+ '<strong>' . $filename . '</strong>'
34
+ );
35
+ $ret = false;
36
+ }
37
 
38
+ // Check whether there is a call to wp_title().
39
+ checkcount();
40
+ if ( 0 <= strpos( $php, 'wp_title(' ) && ! $titletag ) {
41
+ $this->error[] = '<span class="tc-lead tc-required">' . __( 'REQUIRED', 'theme-check' ) . '</span>: ' . sprintf( __( 'The theme must not call to <strong>wp_title()</strong>. Found wp_title() in %1$s.', 'theme-check' ),
42
+ '<strong>' . $filename . '</strong>'
43
+ );
44
+ $ret = false;
45
+ }
46
+
47
+ // Check whether the the <title> tag contains something besides a call to wp_title().
48
+ checkcount();
49
+ // Look for anything that looks like <svg>...</svg> and exclude it (inline svg's have titles too).
50
+ $file_content = preg_replace( '/<svg.*>.*<\/svg>/s', '', $file_content );
51
+ // First looks ahead to see of there's <title>...</title>.
52
+ // Then performs a negative look ahead for <title> wp_title(...); </title>.
53
+ $error = '/<title>/';
54
+ $grep = tc_preg( $error, $file_path );
55
 
 
 
56
  if ( preg_match( '/(?=<title>(.*)<\/title>)(?!<title>\s*<\?php\s*wp_title\([^\)]*\);?\s*\?>\s*<\/title>)/s', $file_content ) ) {
57
+ $this->error[] = '<span class="tc-lead tc-required">' . __( 'REQUIRED', 'theme-check').'</span>: ' . sprintf( __( '%1$s: The <strong>&lt;title&gt;</strong> tags can only contain a call to <strong>wp_title()</strong>. Use the <strong>wp_title filter</strong> to modify the output.', 'theme-check' ),
58
+ '<strong>' . $filename . '</strong>'
59
+ ) . $grep;
60
+ $ret = false;
61
  }
62
  }
63
 
67
  function getError() { return $this->error; }
68
  }
69
 
70
+ $themechecks[] = new Title_Checks();
checks/underscores.php ADDED
@@ -0,0 +1,57 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Check if:
4
+ * Theme or author URI refers to _s
5
+ * The readme is a copy of _s
6
+ * footer credit link refers to _s
7
+ */
8
+ class UnderscoresCheck implements themecheck {
9
+ protected $error = array();
10
+
11
+ function check( $php_files, $css_files, $other_files ) {
12
+
13
+ $ret = true;
14
+ global $data;
15
+
16
+ checkcount();
17
+ if ( ! empty( $data['AuthorURI'] ) || ! empty( $data['URI'] ) ) {
18
+
19
+ if ( stripos( $data['URI'], 'underscores.me' ) || stripos( $data['AuthorURI'], 'underscores.me' ) ) {
20
+ $this->error[] .= __( '<span class="tc-lead tc-required">' . __( 'REQUIRED', 'theme-check' ) . '</span>: ' . __( 'Using underscores.me as Theme URI or Autor URI is not allowed.', 'theme-check' ) );
21
+ $ret = false;
22
+ }
23
+ }
24
+
25
+ checkcount();
26
+ foreach ( $other_files as $file_path => $file_content ) {
27
+ $filename = tc_filename( $file_path );
28
+ if ( preg_match( "/Hi. I'm a starter theme called `_s`, or `underscores`, if you like./", $file_content ) || preg_match( "/Hi. I'm a starter theme called <code>_s<\/code>, or <em>underscores<\/em>, if/", $file_content ) ) {
29
+ $error = "/Hi. I'm a starter theme called/";
30
+ $grep = tc_preg( $error, $file_path );
31
+ $this->error[] = sprintf( '<span class="tc-lead tc-required">' . __( 'REQUIRED', 'theme-check' ) . '</span>: ' . __( 'Found a copy of Underscores. See %1$s. <a href="https://github.com/Automattic/_s" target="_new">Learn how to update the files for your own theme.</a>', 'theme-check' ),
32
+ '<strong>' . $filename . '</strong>' ) . $grep;
33
+ $ret = false;
34
+ }
35
+ }
36
+
37
+ /**
38
+ * This check is limited to footer.php, since we are looking for clones of underscores.
39
+ */
40
+ checkcount();
41
+ foreach ( $php_files as $file_path => $file_content ) {
42
+ $filename = tc_filename( $file_path );
43
+ if ( 'footer.php' === $filename && preg_match( '/Underscores.me/', $file_content ) ) {
44
+ $error = '/Underscores.me/';
45
+ $grep = tc_preg( $error, $file_path );
46
+ $this->error[] = sprintf( '<span class="tc-lead tc-required">' . __( 'REQUIRED', 'theme-check' ) . '</span>: ' . __( 'Found a copy of Underscores. See %1$s. Update the files for your own theme.', 'theme-check' ),
47
+ '<strong>' . $filename . '</strong>' ) . $grep;
48
+ $ret = false;
49
+ }
50
+ }
51
+
52
+ return $ret;
53
+ }
54
+
55
+ function getError() { return $this->error; }
56
+ }
57
+ $themechecks[] = new UnderscoresCheck();
checks/widgets.php CHANGED
@@ -18,12 +18,12 @@ class WidgetsCheck implements themecheck {
18
  }
19
 
20
  if ( strpos( $php, 'register_sidebar' ) !== false && strpos( $php, 'dynamic_sidebar' ) === false ) {
21
- $this->error[] = "<span class='tc-lead tc-required'>" . __( "REQUIRED", 'theme-check') . '</span>: '. __( "The theme appears to use <strong>register_sidebar()</strong> but no <strong>dynamic_sidebar()</strong> was found. See: <a href='https://codex.wordpress.org/Function_Reference/dynamic_sidebar'>dynamic_sidebar</a><pre> &lt;?php dynamic_sidebar( \$index ); ?&gt;</pre>", "theme-check" );
22
  $ret = false;
23
  }
24
 
25
  if ( strpos( $php, 'register_sidebar' ) === false && strpos( $php, 'dynamic_sidebar' ) !== false ) {
26
- $this->error[] = "<span class='tc-lead tc-required'>" . __( "REQUIRED", 'theme-check') . '</span>: '. __( "The theme appears to use <strong>dynamic_sidebars()</strong> but no <strong>register_sidebar()</strong> was found. See: <a href='https://codex.wordpress.org/Function_Reference/register_sidebar'>register_sidebar</a><pre> &lt;?php register_sidebar( \$args ); ?&gt;</pre>", "theme-check" );
27
  $ret = false;
28
  }
29
 
@@ -31,7 +31,7 @@ class WidgetsCheck implements themecheck {
31
  * There are widgets registered, is the widgets_init action present?
32
  */
33
  if ( strpos( $php, 'register_sidebar' ) !== false && preg_match( '/add_action\s*\(\s*("|\')widgets_init("|\')\s*,/', $php ) == false ) {
34
- $this->error[] = "<span class='tc-lead tc-required'>" . __( "REQUIRED", 'theme-check') . '</span>: '. sprintf( __( "Sidebars need to be registered in a custom function hooked to the <strong>widgets_init</strong> action. See: %s.", "theme-check" ), '<a href="https://codex.wordpress.org/Function_Reference/register_sidebar">register_sidebar()</a>' );
35
  $ret = false;
36
  }
37
  return $ret;
18
  }
19
 
20
  if ( strpos( $php, 'register_sidebar' ) !== false && strpos( $php, 'dynamic_sidebar' ) === false ) {
21
+ $this->error[] = "<span class='tc-lead tc-required'>" . __( "REQUIRED", 'theme-check') . '</span>: '. __( "The theme appears to use <strong>register_sidebar()</strong> but no <strong>dynamic_sidebar()</strong> was found. See: <a href='https://developer.wordpress.org/reference/functions/dynamic_sidebar/'>dynamic_sidebar</a><pre> &lt;?php dynamic_sidebar( \$index ); ?&gt;</pre>", "theme-check" );
22
  $ret = false;
23
  }
24
 
25
  if ( strpos( $php, 'register_sidebar' ) === false && strpos( $php, 'dynamic_sidebar' ) !== false ) {
26
+ $this->error[] = "<span class='tc-lead tc-required'>" . __( "REQUIRED", 'theme-check') . '</span>: '. __( "The theme appears to use <strong>dynamic_sidebars()</strong> but no <strong>register_sidebar()</strong> was found. See: <a href='https://developer.wordpress.org/reference/functions/register_sidebar/'>register_sidebar</a><pre> &lt;?php register_sidebar( \$args ); ?&gt;</pre>", "theme-check" );
27
  $ret = false;
28
  }
29
 
31
  * There are widgets registered, is the widgets_init action present?
32
  */
33
  if ( strpos( $php, 'register_sidebar' ) !== false && preg_match( '/add_action\s*\(\s*("|\')widgets_init("|\')\s*,/', $php ) == false ) {
34
+ $this->error[] = "<span class='tc-lead tc-required'>" . __( "REQUIRED", 'theme-check') . '</span>: '. sprintf( __( "Sidebars need to be registered in a custom function hooked to the <strong>widgets_init</strong> action. See: %s.", "theme-check" ), '<a href="https://developer.wordpress.org/reference/functions/register_sidebar/">register_sidebar()</a>' );
35
  $ret = false;
36
  }
37
  return $ret;
checks/worms.php CHANGED
@@ -20,7 +20,7 @@ class WormCheck implements themecheck {
20
  $filename = tc_filename( $php_key );
21
  $error = $matches[0];
22
  $grep = tc_grep( $error, $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
  }
20
  $filename = tc_filename( $php_key );
21
  $error = $matches[0];
22
  $grep = tc_grep( $error, $php_key );
23
+ $this->error[] = sprintf('<span class="tc-lead tc-required">'. __( 'REQUIRED', 'theme-check') . '</span>: <strong>%1$s</strong> %2$s%3$s', $filename, $check, $grep );
24
  $ret = false;
25
  }
26
  }
main.php CHANGED
@@ -52,7 +52,7 @@ function check_main( $theme ) {
52
  echo ( !empty( $data[ 'URI' ] ) ) ? '<p><label>' . __( 'Theme URI', 'theme-check' ) . '</label><span class="info"><a href="' . $data[ 'URI' ] . '">' . $data[ 'URI' ] . '</a>' . '</span></p>' : '';
53
  echo ( !empty( $data[ 'License' ] ) ) ? '<p><label>' . __( 'License', 'theme-check' ) . '</label><span class="info">' . $data[ 'License' ] . '</span></p>' : '';
54
  echo ( !empty( $data[ 'License URI' ] ) ) ? '<p><label>' . __( 'License URI', 'theme-check' ) . '</label><span class="info">' . $data[ 'License URI' ] . '</span></p>' : '';
55
- echo ( !empty( $data[ 'Tags' ] ) ) ? '<p><label>' . __( 'Tags', 'theme-check' ) . '</label><span class="info">' . implode( $data[ 'Tags' ], ', ') . '</span></p>' : '';
56
  echo ( !empty( $data[ 'Description' ] ) ) ? '<p><label>' . __( 'Description', 'theme-check' ) . '</label><span class="info">' . $data[ 'Description' ] . '</span></p>' : '';
57
 
58
  if ( $data[ 'Template' ] ) {
@@ -92,7 +92,7 @@ function check_main( $theme ) {
92
  echo '<h2>' . sprintf(__('%1$s passed the tests', 'theme-check'), $data[ 'Title' ] ) . '</h2>';
93
  tc_success();
94
  }
95
- if ( !defined( 'WP_DEBUG' ) || WP_DEBUG == false ) echo '<div class="updated"><span class="tc-fail">' . __('WARNING','theme-check') . '</span> ' . __( '<strong>WP_DEBUG is not enabled!</strong> Please test your theme with <a href="https://codex.wordpress.org/Editing_wp-config.php">debug enabled</a> before you upload!', 'theme-check' ) . '</div>';
96
  echo '<div class="tc-box">';
97
  echo '<ul class="tc-result">';
98
  echo $results;
@@ -134,7 +134,7 @@ function tc_intro() {
134
  '<a href="https://profiles.wordpress.org/pross/">Pross</a>'
135
  ); ?></p>
136
  <p><?php printf( __( 'If you have found a bug or would like to make a suggestion or contribution, please leave a post on the <a href="%1$s">WordPress forums</a>, or talk about it with the theme review team on <a href="%2$s">Make WordPress Themes</a> site.', 'theme-check' ), 'https://wordpress.org/tags/theme-check?forum_id=10', 'https://make.wordpress.org/themes/') ; ?></p>
137
- <p><?php printf( __( 'The code for Theme Check can be contributed to on <a href="%s">GitHub</a>.', 'theme-check' ), 'https://github.com/Otto42/theme-check'); ?></p>
138
  <h3><?php _e( 'Testers', 'theme-check' ); ?></h3>
139
  <p><a href="https://make.wordpress.org/themes/"><?php _e( 'The WordPress Theme Review Team', 'theme-check' ); ?></a></p>
140
  <?php
@@ -142,13 +142,13 @@ function tc_intro() {
142
 
143
  function tc_success() {
144
  ?>
145
- <div class="tc-success"><p><?php _e( 'Now your theme has passed the basic tests you need to check it properly using the test data before you upload to the WordPress Themes Directory.', 'theme-check' ); ?></p>
146
- <p><?php _e( 'Make sure to review the guidelines at <a href="https://codex.wordpress.org/Theme_Review">Theme Review</a> before uploading a Theme.', 'theme-check' ); ?></p>
147
- <h3><?php _e( 'Codex Links', 'theme-check' ); ?></h3>
148
  <ul>
149
- <li><a href="https://codex.wordpress.org/Theme_Development"><?php _e('Theme Development', 'theme-check' ); ?></a></li>
150
- <li><a href="https://wordpress.org/support/forum/5"><?php _e('Themes and Templates forum', 'theme-check' ); ?></a></li>
151
- <li><a href="https://codex.wordpress.org/Theme_Unit_Test"><?php _e('Theme Unit Tests', 'theme-check' ); ?></a></li>
152
  </ul></div>
153
  <?php
154
  }
52
  echo ( !empty( $data[ 'URI' ] ) ) ? '<p><label>' . __( 'Theme URI', 'theme-check' ) . '</label><span class="info"><a href="' . $data[ 'URI' ] . '">' . $data[ 'URI' ] . '</a>' . '</span></p>' : '';
53
  echo ( !empty( $data[ 'License' ] ) ) ? '<p><label>' . __( 'License', 'theme-check' ) . '</label><span class="info">' . $data[ 'License' ] . '</span></p>' : '';
54
  echo ( !empty( $data[ 'License URI' ] ) ) ? '<p><label>' . __( 'License URI', 'theme-check' ) . '</label><span class="info">' . $data[ 'License URI' ] . '</span></p>' : '';
55
+ echo ( !empty( $data[ 'Tags' ] ) ) ? '<p><label>' . __( 'Tags', 'theme-check' ) . '</label><span class="info">' . implode( ', ', $data[ 'Tags' ] ) . '</span></p>' : '';
56
  echo ( !empty( $data[ 'Description' ] ) ) ? '<p><label>' . __( 'Description', 'theme-check' ) . '</label><span class="info">' . $data[ 'Description' ] . '</span></p>' : '';
57
 
58
  if ( $data[ 'Template' ] ) {
92
  echo '<h2>' . sprintf(__('%1$s passed the tests', 'theme-check'), $data[ 'Title' ] ) . '</h2>';
93
  tc_success();
94
  }
95
+ if ( !defined( 'WP_DEBUG' ) || WP_DEBUG == false ) echo '<div class="updated"><span class="tc-fail">' . __('WARNING','theme-check') . '</span> ' . __( '<strong>WP_DEBUG is not enabled!</strong> Please test your theme with <a href="https://wordpress.org/support/article/editing-wp-config-php/">debug enabled</a> before you upload!', 'theme-check' ) . '</div>';
96
  echo '<div class="tc-box">';
97
  echo '<ul class="tc-result">';
98
  echo $results;
134
  '<a href="https://profiles.wordpress.org/pross/">Pross</a>'
135
  ); ?></p>
136
  <p><?php printf( __( 'If you have found a bug or would like to make a suggestion or contribution, please leave a post on the <a href="%1$s">WordPress forums</a>, or talk about it with the theme review team on <a href="%2$s">Make WordPress Themes</a> site.', 'theme-check' ), 'https://wordpress.org/tags/theme-check?forum_id=10', 'https://make.wordpress.org/themes/') ; ?></p>
137
+ <p><?php printf( __( 'The code for Theme Check can be contributed to on <a href="%s">GitHub</a>.', 'theme-check' ), 'https://github.com/WordPress/theme-check'); ?></p>
138
  <h3><?php _e( 'Testers', 'theme-check' ); ?></h3>
139
  <p><a href="https://make.wordpress.org/themes/"><?php _e( 'The WordPress Theme Review Team', 'theme-check' ); ?></a></p>
140
  <?php
142
 
143
  function tc_success() {
144
  ?>
145
+ <div class="tc-success"><p><?php _e( 'Now that your theme has passed the basic tests you need to check it properly using the test data before you upload it to the WordPress Themes Directory.', 'theme-check' ); ?></p>
146
+ <p><?php _e( 'Make sure to review the guidelines at <a href="https://make.wordpress.org/themes/handbook/review/required/">Theme Review</a> before uploading a Theme.', 'theme-check' ); ?></p>
147
+ <h3><?php _e( 'Useful Links', 'theme-check' ); ?></h3>
148
  <ul>
149
+ <li><a href="https://developer.wordpress.org/themes/"><?php _e( 'Theme Handbook', 'theme-check' ); ?></a></li>
150
+ <li><a href="https://wordpress.org/support/forum/wp-advanced/"><?php _e( 'Developing with WordPress Forum', 'theme-check' ); ?></a></li>
151
+ <li><a href="https://github.com/WPTRT/theme-unit-test"><?php _e( 'Theme Unit Tests', 'theme-check' ); ?></a></li>
152
  </ul></div>
153
  <?php
154
  }
readme.txt CHANGED
@@ -1,11 +1,9 @@
1
  === Theme Check ===
2
- Contributors: Otto42, pross
3
- Author URI: http://ottopress.com/
4
- Plugin URL: http://ottopress.com/wordpress-plugins/theme-check/
5
  Requires at Least: 3.7
6
- Tested Up To: 5.2
7
  Tags: template, theme, check, checker, tool, wordpress, wordpress.org, upload, uploader, test, guideline, review
8
- Stable tag: 20190801.1
9
 
10
  A simple and easy way to test your theme for all the latest WordPress standards and practices. A great theme development tool!
11
 
@@ -54,138 +52,5 @@ comments, or feedback:[[br]]
54
  If **either** of these two vars are defined a new trac tickbox will appear next to the *Check it!* button.
55
 
56
  == Changelog ==
57
- = 20190801.1 =
58
- * Fix missing nonce and nonce check on admin page. props Steven Stern for reporting the issue to the plugins team. Though this is technically a CSRF, there is no vulnerability arising from it, as the only thing that could be done with the form is to scan a theme.
59
-
60
- = 20190208.1 =
61
- * Add new styles for the block editor. See https://meta.trac.wordpress.org/ticket/3921
62
-
63
- = 20160523.1 =
64
- * Fix for theme-names with dashes in them
65
- * Comments stripping changes
66
- * Many changes by the theme review team and others. See Github for full change list.
67
-
68
- = 20151211.1 =
69
- * Full sync with Github and all the changes that have happened there.
70
- * Release for 4.4 deprecated functions.
71
-
72
- = 20140929.1 =
73
- * Added new checks and updates from Frank Klein at Automattic. Thanks Frank!
74
- * Updated deprecated function listings
75
- * Customizer check: All add_settings must use sanitization callbacks, for security
76
- * Plugin territory checks: Themes must not register post types or taxonomies or add shortcodes for post content
77
- * Widgets: Calls to register_sidebar must be called from the widgets_init action hook
78
- * Title: <title> tags must exist and not have anything in them other than a call to wp_title()
79
- * CDN: Checks for use of common CDNs (recommended only)
80
- * Note: Changed plugin and author URIs due to old URIs being invalid. These may change again in the future, the URIs to my own site are temporarily only.
81
-
82
- = 20131213.1 =
83
- * Corrected errors not being displayed by the plugin and it incorrectly giving a "pass" result to everything.
84
-
85
- = 20131212.1 =
86
- * Updated for 3.8
87
- * Most files have changed for better I18N support, so the language files were removed temporarily until translation can be redone.
88
-
89
- = 20121211.1 =
90
- * Updated for 3.5
91
- * Remove Paypal button.
92
-
93
- = 20110805.1 =
94
- * TimThumb checks removed.
95
- * Proper i18n loading. Fixes http://bit.ly/ouD5Ke.
96
- * Screenshot now previewed in results, with filesize and dimensions.
97
-
98
- = 20110602.2 =
99
- * New file list functions hidden folders now detectable.
100
- * Better fopen checks.
101
- * TimThumb version bump
102
-
103
- = 20110602.1 =
104
- * DOS/UNIX line ending style checks are now a requirement for proper theme uploading.
105
- * Timthumb version bump
106
- * Several fixes reported by GaryJ
107
- * 3.2 deprecated functions added
108
-
109
- = 20110412.1 =
110
- * Fix regex's
111
- * Added check for latest footer injection hack.
112
- * Fix tags check to use new content function correctly
113
- * Sync of all changes made for wporg uploader theme-check.
114
- * Updated checks post 3.1. added screenshot check to svn.
115
- * Fix links check to not return a false failure in some cases
116
- * rm one of the checks that causes problems on wporg uploader (and which is also unnecessary)
117
- * Move unneeded functions out of checkbase into main.php.
118
- * Minor formatting changes only (spacing and such)
119
- * Add check for wp_link_pages() + fix eval() check
120
-
121
- = 20110219.2 =
122
- * Merged new UI props Gua Bob [1](http://guabob.com/)
123
- * Last tested theme is always pre-selected in the themes list.
124
- * Fixed php error in admin_menu.php
125
-
126
- = 20110219.1 =
127
- * See [commit log](https://github.com/Pross/theme-check/commits/) for changes.
128
-
129
- = 20110201.2 =
130
- * UI bug fixes [forum post](http://bit.ly/ff7amN) props Mamaduka.
131
- * Textdomain checks for twentyten and no domain.
132
- * Fix div not closing props Mamaduka.
133
-
134
- = 20110201.1 =
135
- * i18n working
136
- * sr_RS de_DE ro_RO langs props Daniel Tara and Emil Uzelac.
137
- * Child theme support added, checks made against parent AND child at runtime.
138
- * Trac formatting button added for reviewers.
139
-
140
- = 20101228.3 =
141
- * Last revision for 3.1 (hopefully)
142
- * Chips suggestion of checking for inclusion of searchform.php ( not
143
- perfect yet, need more examples to look for ).
144
- * add_theme_page is required, all others flagged and displayed with line
145
- numbers.
146
- * <?= detected properly, short tags outputted with line umbers.
147
- * Mostly internationalized, needs translations now.
148
- * Bug fixes.
149
-
150
- = 20101228.2 =
151
- * Added menu checking.
152
- * ThemeURI AuthourURI added to results.
153
- * Lots of small fixes.
154
- * Started translation.
155
-
156
- = 20101228.1 =
157
- * Fix embed_defaults filter check and stylesheet file data check.
158
-
159
- = 20101226.1 =
160
- * Whole system redesign to allow easier synching with WordPress.org uploader. Many other additions/subtractions/changes as well.
161
- * WordPress 3.1 guidelines added, to help theme authors ensure compatibility for upcoming release.
162
-
163
- = 20101110.7 =
164
- * Re-added malware.php checks for fopen and file_get_contents (INFO)
165
- * fixed a couple of undefined index errors.
166
-
167
- = 20101110.4_r2 =
168
- * Fixed Warning: Wrong parameter count for stristr()
169
-
170
- = 20101110.4_r1 =
171
- * Added `echo` to suggested.php
172
-
173
- = 20101110.4 =
174
- * Fixed deprecated function call to get_plugins()
175
-
176
- = 20101110.3 =
177
- * Fixed undefined index.
178
-
179
- = 20101110.2 =
180
- * Missing `<` in main.php
181
- * Added conditional checks for licence.txt OR Licence tags in style.css
182
- * UI improvements.
183
-
184
- = 20101110.1 =
185
- * Date fix!
186
-
187
- = 10112010_r1 =
188
- * Fixed hardcoded links check. Added FAQ
189
-
190
- = 10112010 =
191
- * First release.
1
  === Theme Check ===
2
+ Contributors: Otto42, pross, poena, dingo-d, acosmin, joyously
 
 
3
  Requires at Least: 3.7
4
+ Tested Up To: 5.4
5
  Tags: template, theme, check, checker, tool, wordpress, wordpress.org, upload, uploader, test, guideline, review
6
+ Stable tag: 20200612.1
7
 
8
  A simple and easy way to test your theme for all the latest WordPress standards and practices. A great theme development tool!
9
 
52
  If **either** of these two vars are defined a new trac tickbox will appear next to the *Check it!* button.
53
 
54
  == Changelog ==
55
+ = 20200504.1 =
56
+ * Changes can be found in the changelog.txt file.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
theme-check.php CHANGED
@@ -1,11 +1,10 @@
1
  <?php
2
  /*
3
  Plugin Name: Theme Check
4
- Plugin URI: http://ottopress.com/wordpress-plugins/theme-check/
5
  Description: A simple and easy way to test your theme for all the latest WordPress standards and practices. A great theme development tool!
6
- Author: Otto42, pross
7
- Author URI: http://ottopress.com
8
- Version: 20190801.1
9
  Text Domain: theme-check
10
  License: GPLv2
11
  License URI: https://www.gnu.org/licenses/gpl-2.0.html
1
  <?php
2
  /*
3
  Plugin Name: Theme Check
4
+ Plugin URI: https://github.com/WordPress/theme-check/
5
  Description: A simple and easy way to test your theme for all the latest WordPress standards and practices. A great theme development tool!
6
+ Author: Theme Review Team
7
+ Version: 20200612.1
 
8
  Text Domain: theme-check
9
  License: GPLv2
10
  License URI: https://www.gnu.org/licenses/gpl-2.0.html