Version Description
Download this release
Release Info
Developer | Otto42 |
Plugin | Theme Check |
Version | 20200922.1 |
Comparing to | |
See all releases |
Code changes from version 20200731.1 to 20200922.1
- changelog.txt +6 -0
- checkbase.php +132 -105
- checks/badthings.php +4 -1
- checks/postthumb.php +2 -2
- checks/style_tags.php +104 -14
- main.php +175 -91
- readme.txt +2 -1
- theme-check.php +23 -23
changelog.txt
CHANGED
@@ -1,3 +1,9 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
= 20200731.1 =
|
2 |
* Added add_menu_page & add_submenu_page to the allowed functions list
|
3 |
* Added loco.xml to the allowed files list and extend the allowlist check functionality to support an array of (possible) filenames.
|
1 |
+
= 20200922.1 =
|
2 |
+
* Reformatting of main.php and checkbase.php
|
3 |
+
* Additions to malware checks in badthings.php
|
4 |
+
* Spacing fix in postthumb.php
|
5 |
+
* Improved check for tags in styletags.php
|
6 |
+
|
7 |
= 20200731.1 =
|
8 |
* Added add_menu_page & add_submenu_page to the allowed functions list
|
9 |
* Added loco.xml to the allowed files list and extend the allowlist check functionality to support an array of (possible) filenames.
|
checkbase.php
CHANGED
@@ -7,30 +7,30 @@ $themechecks = array();
|
|
7 |
global $checkcount;
|
8 |
$checkcount = 0;
|
9 |
|
10 |
-
// interface that all checks should implement
|
11 |
-
interface themecheck
|
12 |
-
|
13 |
-
// should return true for good/okay/acceptable, false for bad/not-okay/unacceptable
|
14 |
public function check( $php_files, $css_files, $other_files );
|
15 |
|
16 |
-
// should return an array of strings explaining any problems found
|
17 |
public function getError();
|
18 |
}
|
19 |
|
20 |
-
// load all the checks in the checks directory
|
21 |
$dir = 'checks';
|
22 |
-
foreach (glob(dirname(__FILE__). "/{$dir}/*.php") as $file) {
|
23 |
include $file;
|
24 |
}
|
25 |
|
26 |
-
do_action('themecheck_checks_loaded');
|
27 |
|
28 |
-
function run_themechecks($php, $css, $other) {
|
29 |
global $themechecks;
|
30 |
$pass = true;
|
31 |
-
foreach($themechecks as $check) {
|
32 |
-
if ($check instanceof themecheck) {
|
33 |
-
$pass = $pass & $check->check($php, $css, $other);
|
34 |
}
|
35 |
}
|
36 |
return $pass;
|
@@ -40,32 +40,36 @@ function display_themechecks() {
|
|
40 |
$results = '';
|
41 |
global $themechecks;
|
42 |
$errors = array();
|
43 |
-
foreach ($themechecks as $check) {
|
44 |
-
if ($check instanceof themecheck) {
|
45 |
$error = $check->getError();
|
46 |
$error = (array) $error;
|
47 |
-
if (!empty($error)) {
|
48 |
$errors = array_unique( array_merge( $error, $errors ) );
|
49 |
}
|
50 |
}
|
51 |
}
|
52 |
-
if (!empty($errors)) {
|
53 |
-
rsort($errors);
|
54 |
-
foreach ($errors as $e) {
|
55 |
-
|
56 |
-
|
57 |
-
|
58 |
-
|
59 |
-
|
60 |
}
|
61 |
}
|
62 |
}
|
63 |
|
64 |
if ( defined( 'TC_TRAC' ) ) {
|
65 |
|
66 |
-
if ( defined( 'TC_PRE' ) )
|
67 |
-
|
68 |
-
|
|
|
|
|
|
|
|
|
69 |
$results .= '</textarea>';
|
70 |
}
|
71 |
return $results;
|
@@ -76,22 +80,23 @@ function checkcount() {
|
|
76 |
$checkcount++;
|
77 |
}
|
78 |
|
79 |
-
// some functions theme checks use
|
80 |
function tc_grep( $error, $file ) {
|
81 |
if ( ! file_exists( $file ) ) {
|
82 |
return '';
|
83 |
}
|
84 |
-
$lines
|
85 |
$line_index = 0;
|
86 |
-
$bad_lines
|
87 |
-
foreach( $lines as $this_line )
|
88 |
-
if ( stristr
|
89 |
-
$error
|
90 |
-
$this_line
|
91 |
-
$error
|
92 |
-
|
93 |
-
|
94 |
-
$
|
|
|
95 |
}
|
96 |
$line_index++;
|
97 |
}
|
@@ -102,21 +107,22 @@ function tc_preg( $preg, $file ) {
|
|
102 |
if ( ! file_exists( $file ) ) {
|
103 |
return '';
|
104 |
}
|
105 |
-
$lines
|
106 |
$line_index = 0;
|
107 |
-
$bad_lines
|
108 |
-
$error
|
109 |
-
foreach( $lines as $this_line ) {
|
110 |
if ( preg_match( $preg, $this_line, $matches ) ) {
|
111 |
-
$error
|
112 |
$this_line = str_replace( '"', "'", $this_line );
|
113 |
-
$error
|
114 |
-
$pre
|
115 |
-
if ( !empty( $error ) ) {
|
116 |
-
$
|
|
|
117 |
}
|
118 |
-
$pre
|
119 |
-
$bad_lines .= "<pre class='tc-grep'>" . __(
|
120 |
}
|
121 |
$line_index++;
|
122 |
|
@@ -130,10 +136,10 @@ function tc_filename( $file ) {
|
|
130 |
}
|
131 |
|
132 |
function tc_trac( $e ) {
|
133 |
-
$trac_left
|
134 |
-
$trac_right= array( "'''", "'''" );
|
135 |
-
$html_link
|
136 |
-
$html_new
|
137 |
if ( defined( 'TC_TRAC' ) ) {
|
138 |
$e = preg_replace( $html_link, $html_new, $e );
|
139 |
$e = str_replace( $trac_left, $trac_right, $e );
|
@@ -144,61 +150,67 @@ function tc_trac( $e ) {
|
|
144 |
}
|
145 |
|
146 |
function listdir( $dir ) {
|
147 |
-
$files
|
148 |
$dir_iterator = new RecursiveDirectoryIterator( $dir );
|
149 |
-
$iterator
|
150 |
|
151 |
-
foreach ($iterator as $file) {
|
152 |
-
|
153 |
}
|
154 |
return $files;
|
155 |
}
|
156 |
|
157 |
function get_theme_data_from_contents( $theme_data ) {
|
158 |
$themes_allowed_tags = array(
|
159 |
-
'a'
|
160 |
-
'href'
|
161 |
-
),
|
162 |
-
|
163 |
-
|
164 |
-
),
|
|
|
165 |
'acronym' => array(
|
166 |
-
'title' => array()
|
167 |
-
|
168 |
-
'code'
|
169 |
-
'em'
|
170 |
-
'strong'
|
171 |
);
|
172 |
|
173 |
-
$theme_data = str_replace
|
174 |
preg_match( '|^[ \t\/*#@]*Theme Name:(.*)$|mi', $theme_data, $theme_name );
|
175 |
preg_match( '|^[ \t\/*#@]*Theme URI:(.*)$|mi', $theme_data, $theme_uri );
|
176 |
preg_match( '|^[ \t\/*#@]*Description:(.*)$|mi', $theme_data, $description );
|
177 |
|
178 |
-
if ( preg_match( '|^[ \t\/*#@]*Author URI:(.*)$|mi', $theme_data, $author_uri ) )
|
179 |
-
$author_uri = esc_url( trim( $author_uri[1]) );
|
180 |
-
else
|
181 |
$author_uri = '';
|
|
|
182 |
|
183 |
-
if ( preg_match( '|^[ \t\/*#@]*Template:(.*)$|mi', $theme_data, $template ) )
|
184 |
$template = wp_kses( trim( $template[1] ), $themes_allowed_tags );
|
185 |
-
else
|
186 |
$template = '';
|
|
|
187 |
|
188 |
-
if ( preg_match( '|^[ \t\/*#@]*Version:(.*)|mi', $theme_data, $version ) )
|
189 |
$version = wp_kses( trim( $version[1] ), $themes_allowed_tags );
|
190 |
-
else
|
191 |
$version = '';
|
|
|
192 |
|
193 |
-
if ( preg_match('|^[ \t\/*#@]*Status:(.*)|mi', $theme_data, $status) )
|
194 |
$status = wp_kses( trim( $status[1] ), $themes_allowed_tags );
|
195 |
-
else
|
196 |
$status = 'publish';
|
|
|
197 |
|
198 |
-
if ( preg_match('|^[ \t\/*#@]*Tags:(.*)|mi', $theme_data, $tags) )
|
199 |
$tags = array_map( 'trim', explode( ',', wp_kses( trim( $tags[1] ), array() ) ) );
|
200 |
-
else
|
201 |
$tags = array();
|
|
|
202 |
|
203 |
$theme = ( isset( $theme_name[1] ) ) ? wp_kses( trim( $theme_name[1] ), $themes_allowed_tags ) : '';
|
204 |
|
@@ -210,13 +222,24 @@ function get_theme_data_from_contents( $theme_data ) {
|
|
210 |
if ( empty( $author_uri ) ) {
|
211 |
$author = wp_kses( trim( $author_name[1] ), $themes_allowed_tags );
|
212 |
} else {
|
213 |
-
$author = sprintf( '<a href="%1$s" title="%2$s">%3$s</a>', $author_uri, __( 'Visit author homepage' ), wp_kses( trim( $author_name[1] ), $themes_allowed_tags ) );
|
214 |
}
|
215 |
} else {
|
216 |
-
$author = __('Anonymous');
|
217 |
}
|
218 |
|
219 |
-
return array(
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
220 |
}
|
221 |
|
222 |
/*
|
@@ -225,22 +248,25 @@ function get_theme_data_from_contents( $theme_data ) {
|
|
225 |
*/
|
226 |
function tc_get_themes() {
|
227 |
|
228 |
-
if ( ! class_exists( 'WP_Theme' ) )
|
229 |
-
return
|
|
|
230 |
|
231 |
global $wp_themes;
|
232 |
-
if ( isset( $wp_themes ) )
|
233 |
return $wp_themes;
|
|
|
234 |
|
235 |
-
$themes
|
236 |
$wp_themes = array();
|
237 |
|
238 |
foreach ( $themes as $theme ) {
|
239 |
-
$name = $theme->get('Name');
|
240 |
-
if ( isset( $wp_themes[ $name ] ) )
|
241 |
$wp_themes[ $name . '/' . $theme->get_stylesheet() ] = $theme;
|
242 |
-
else
|
243 |
$wp_themes[ $name ] = $theme;
|
|
|
244 |
}
|
245 |
|
246 |
return $wp_themes;
|
@@ -248,26 +274,27 @@ function tc_get_themes() {
|
|
248 |
|
249 |
function tc_get_theme_data( $theme_file ) {
|
250 |
|
251 |
-
if ( ! class_exists( 'WP_Theme' ) )
|
252 |
-
return
|
|
|
253 |
|
254 |
$theme = new WP_Theme( basename( dirname( $theme_file ) ), dirname( dirname( $theme_file ) ) );
|
255 |
|
256 |
$theme_data = array(
|
257 |
-
'Name'
|
258 |
-
'URI'
|
259 |
-
'Description'
|
260 |
-
'Author'
|
261 |
-
'AuthorURI'
|
262 |
-
'Version'
|
263 |
-
'Template'
|
264 |
-
'Status'
|
265 |
-
'Tags'
|
266 |
-
'Title'
|
267 |
-
'AuthorName'
|
268 |
-
'License'
|
269 |
-
'License URI'
|
270 |
-
'Template Version'
|
271 |
);
|
272 |
return $theme_data;
|
273 |
}
|
7 |
global $checkcount;
|
8 |
$checkcount = 0;
|
9 |
|
10 |
+
// interface that all checks should implement.
|
11 |
+
interface themecheck {
|
12 |
+
|
13 |
+
// should return true for good/okay/acceptable, false for bad/not-okay/unacceptable.
|
14 |
public function check( $php_files, $css_files, $other_files );
|
15 |
|
16 |
+
// should return an array of strings explaining any problems found.
|
17 |
public function getError();
|
18 |
}
|
19 |
|
20 |
+
// load all the checks in the checks directory.
|
21 |
$dir = 'checks';
|
22 |
+
foreach ( glob( dirname( __FILE__ ) . "/{$dir}/*.php" ) as $file ) {
|
23 |
include $file;
|
24 |
}
|
25 |
|
26 |
+
do_action( 'themecheck_checks_loaded' );
|
27 |
|
28 |
+
function run_themechecks( $php, $css, $other ) {
|
29 |
global $themechecks;
|
30 |
$pass = true;
|
31 |
+
foreach ( $themechecks as $check ) {
|
32 |
+
if ( $check instanceof themecheck ) {
|
33 |
+
$pass = $pass & $check->check( $php, $css, $other );
|
34 |
}
|
35 |
}
|
36 |
return $pass;
|
40 |
$results = '';
|
41 |
global $themechecks;
|
42 |
$errors = array();
|
43 |
+
foreach ( $themechecks as $check ) {
|
44 |
+
if ( $check instanceof themecheck ) {
|
45 |
$error = $check->getError();
|
46 |
$error = (array) $error;
|
47 |
+
if ( ! empty( $error ) ) {
|
48 |
$errors = array_unique( array_merge( $error, $errors ) );
|
49 |
}
|
50 |
}
|
51 |
}
|
52 |
+
if ( ! empty( $errors ) ) {
|
53 |
+
rsort( $errors );
|
54 |
+
foreach ( $errors as $e ) {
|
55 |
+
|
56 |
+
if ( defined( 'TC_TRAC' ) ) {
|
57 |
+
$results .= ( isset( $_POST['s_info'] ) && preg_match( '/INFO/', $e ) ) ? '' : '* ' . tc_trac( $e ) . "\r\n";
|
58 |
+
} else {
|
59 |
+
$results .= ( isset( $_POST['s_info'] ) && preg_match( '/INFO/', $e ) ) ? '' : '<li>' . tc_trac( $e ) . '</li>';
|
60 |
}
|
61 |
}
|
62 |
}
|
63 |
|
64 |
if ( defined( 'TC_TRAC' ) ) {
|
65 |
|
66 |
+
if ( defined( 'TC_PRE' ) ) {
|
67 |
+
$results = TC_PRE . $results;
|
68 |
+
}
|
69 |
+
$results = '<textarea cols=140 rows=20>' . wp_strip_all_tags( $results );
|
70 |
+
if ( defined( 'TC_POST' ) ) {
|
71 |
+
$results = $results . TC_POST;
|
72 |
+
}
|
73 |
$results .= '</textarea>';
|
74 |
}
|
75 |
return $results;
|
80 |
$checkcount++;
|
81 |
}
|
82 |
|
83 |
+
// some functions theme checks use.
|
84 |
function tc_grep( $error, $file ) {
|
85 |
if ( ! file_exists( $file ) ) {
|
86 |
return '';
|
87 |
}
|
88 |
+
$lines = file( $file, FILE_IGNORE_NEW_LINES ); // Read the theme file into an array.
|
89 |
$line_index = 0;
|
90 |
+
$bad_lines = '';
|
91 |
+
foreach ( $lines as $this_line ) {
|
92 |
+
if ( stristr( $this_line, $error ) ) {
|
93 |
+
$error = str_replace( '"', "'", $error );
|
94 |
+
$this_line = str_replace( '"', "'", $this_line );
|
95 |
+
$error = ltrim( $error );
|
96 |
+
$pos = strpos( $this_line, $error );
|
97 |
+
$pre = ( false !== $pos ? substr( $this_line, 0, $pos ) : false );
|
98 |
+
$pre = ltrim( htmlspecialchars( $pre ) );
|
99 |
+
$bad_lines .= "<pre class='tc-grep'>" . __( 'Line ', 'theme-check' ) . ( $line_index + 1 ) . ': ' . $pre . htmlspecialchars( substr( stristr( $this_line, $error ), 0, 75 ) ) . '</pre>';
|
100 |
}
|
101 |
$line_index++;
|
102 |
}
|
107 |
if ( ! file_exists( $file ) ) {
|
108 |
return '';
|
109 |
}
|
110 |
+
$lines = file( $file, FILE_IGNORE_NEW_LINES ); // Read the theme file into an array.
|
111 |
$line_index = 0;
|
112 |
+
$bad_lines = '';
|
113 |
+
$error = '';
|
114 |
+
foreach ( $lines as $this_line ) {
|
115 |
if ( preg_match( $preg, $this_line, $matches ) ) {
|
116 |
+
$error = $matches[0];
|
117 |
$this_line = str_replace( '"', "'", $this_line );
|
118 |
+
$error = ltrim( $error );
|
119 |
+
$pre = '';
|
120 |
+
if ( ! empty( $error ) ) {
|
121 |
+
$pos = strpos( $this_line, $error );
|
122 |
+
$pre = ( false !== $pos ? substr( $this_line, 0, $pos ) : false );
|
123 |
}
|
124 |
+
$pre = ltrim( htmlspecialchars( $pre ) );
|
125 |
+
$bad_lines .= "<pre class='tc-grep'>" . __( 'Line ', 'theme-check' ) . ( $line_index + 1 ) . ': ' . $pre . htmlspecialchars( substr( stristr( $this_line, $error ), 0, 75 ) ) . '</pre>';
|
126 |
}
|
127 |
$line_index++;
|
128 |
|
136 |
}
|
137 |
|
138 |
function tc_trac( $e ) {
|
139 |
+
$trac_left = array( '<strong>', '</strong>' );
|
140 |
+
$trac_right = array( "'''", "'''" );
|
141 |
+
$html_link = '/<a\s?href\s?=\s?[\'|"]([^"|\']*)[\'|"]>([^<]*)<\/a>/i';
|
142 |
+
$html_new = '[$1 $2]';
|
143 |
if ( defined( 'TC_TRAC' ) ) {
|
144 |
$e = preg_replace( $html_link, $html_new, $e );
|
145 |
$e = str_replace( $trac_left, $trac_right, $e );
|
150 |
}
|
151 |
|
152 |
function listdir( $dir ) {
|
153 |
+
$files = array();
|
154 |
$dir_iterator = new RecursiveDirectoryIterator( $dir );
|
155 |
+
$iterator = new RecursiveIteratorIterator( $dir_iterator, RecursiveIteratorIterator::SELF_FIRST );
|
156 |
|
157 |
+
foreach ( $iterator as $file ) {
|
158 |
+
array_push( $files, $file->getPathname() );
|
159 |
}
|
160 |
return $files;
|
161 |
}
|
162 |
|
163 |
function get_theme_data_from_contents( $theme_data ) {
|
164 |
$themes_allowed_tags = array(
|
165 |
+
'a' => array(
|
166 |
+
'href' => array(),
|
167 |
+
'title' => array(),
|
168 |
+
),
|
169 |
+
'abbr' => array(
|
170 |
+
'title' => array(),
|
171 |
+
),
|
172 |
'acronym' => array(
|
173 |
+
'title' => array(),
|
174 |
+
),
|
175 |
+
'code' => array(),
|
176 |
+
'em' => array(),
|
177 |
+
'strong' => array(),
|
178 |
);
|
179 |
|
180 |
+
$theme_data = str_replace( '\r', '\n', $theme_data );
|
181 |
preg_match( '|^[ \t\/*#@]*Theme Name:(.*)$|mi', $theme_data, $theme_name );
|
182 |
preg_match( '|^[ \t\/*#@]*Theme URI:(.*)$|mi', $theme_data, $theme_uri );
|
183 |
preg_match( '|^[ \t\/*#@]*Description:(.*)$|mi', $theme_data, $description );
|
184 |
|
185 |
+
if ( preg_match( '|^[ \t\/*#@]*Author URI:(.*)$|mi', $theme_data, $author_uri ) ) {
|
186 |
+
$author_uri = esc_url( trim( $author_uri[1] ) );
|
187 |
+
} else {
|
188 |
$author_uri = '';
|
189 |
+
}
|
190 |
|
191 |
+
if ( preg_match( '|^[ \t\/*#@]*Template:(.*)$|mi', $theme_data, $template ) ) {
|
192 |
$template = wp_kses( trim( $template[1] ), $themes_allowed_tags );
|
193 |
+
} else {
|
194 |
$template = '';
|
195 |
+
}
|
196 |
|
197 |
+
if ( preg_match( '|^[ \t\/*#@]*Version:(.*)|mi', $theme_data, $version ) ) {
|
198 |
$version = wp_kses( trim( $version[1] ), $themes_allowed_tags );
|
199 |
+
} else {
|
200 |
$version = '';
|
201 |
+
}
|
202 |
|
203 |
+
if ( preg_match( '|^[ \t\/*#@]*Status:(.*)|mi', $theme_data, $status ) ) {
|
204 |
$status = wp_kses( trim( $status[1] ), $themes_allowed_tags );
|
205 |
+
} else {
|
206 |
$status = 'publish';
|
207 |
+
}
|
208 |
|
209 |
+
if ( preg_match( '|^[ \t\/*#@]*Tags:(.*)|mi', $theme_data, $tags ) ) {
|
210 |
$tags = array_map( 'trim', explode( ',', wp_kses( trim( $tags[1] ), array() ) ) );
|
211 |
+
} else {
|
212 |
$tags = array();
|
213 |
+
}
|
214 |
|
215 |
$theme = ( isset( $theme_name[1] ) ) ? wp_kses( trim( $theme_name[1] ), $themes_allowed_tags ) : '';
|
216 |
|
222 |
if ( empty( $author_uri ) ) {
|
223 |
$author = wp_kses( trim( $author_name[1] ), $themes_allowed_tags );
|
224 |
} else {
|
225 |
+
$author = sprintf( '<a href="%1$s" title="%2$s">%3$s</a>', $author_uri, __( 'Visit author homepage', 'theme-check' ), wp_kses( trim( $author_name[1] ), $themes_allowed_tags ) );
|
226 |
}
|
227 |
} else {
|
228 |
+
$author = __( 'Anonymous', 'theme-check' );
|
229 |
}
|
230 |
|
231 |
+
return array(
|
232 |
+
'Name' => $theme,
|
233 |
+
'Title' => $theme,
|
234 |
+
'URI' => $theme_uri,
|
235 |
+
'Description' => $description,
|
236 |
+
'Author' => $author,
|
237 |
+
'Author_URI' => $author_uri,
|
238 |
+
'Version' => $version,
|
239 |
+
'Template' => $template,
|
240 |
+
'Status' => $status,
|
241 |
+
'Tags' => $tags,
|
242 |
+
);
|
243 |
}
|
244 |
|
245 |
/*
|
248 |
*/
|
249 |
function tc_get_themes() {
|
250 |
|
251 |
+
if ( ! class_exists( 'WP_Theme' ) ) {
|
252 |
+
return wp_get_theme();
|
253 |
+
}
|
254 |
|
255 |
global $wp_themes;
|
256 |
+
if ( isset( $wp_themes ) ) {
|
257 |
return $wp_themes;
|
258 |
+
}
|
259 |
|
260 |
+
$themes = wp_get_themes();
|
261 |
$wp_themes = array();
|
262 |
|
263 |
foreach ( $themes as $theme ) {
|
264 |
+
$name = $theme->get( 'Name' );
|
265 |
+
if ( isset( $wp_themes[ $name ] ) ) {
|
266 |
$wp_themes[ $name . '/' . $theme->get_stylesheet() ] = $theme;
|
267 |
+
} else {
|
268 |
$wp_themes[ $name ] = $theme;
|
269 |
+
}
|
270 |
}
|
271 |
|
272 |
return $wp_themes;
|
274 |
|
275 |
function tc_get_theme_data( $theme_file ) {
|
276 |
|
277 |
+
if ( ! class_exists( 'WP_Theme' ) ) {
|
278 |
+
return wp_get_theme( $theme_file );
|
279 |
+
}
|
280 |
|
281 |
$theme = new WP_Theme( basename( dirname( $theme_file ) ), dirname( dirname( $theme_file ) ) );
|
282 |
|
283 |
$theme_data = array(
|
284 |
+
'Name' => $theme->get( 'Name' ),
|
285 |
+
'URI' => $theme->display( 'ThemeURI', true, false ),
|
286 |
+
'Description' => $theme->display( 'Description', true, false ),
|
287 |
+
'Author' => $theme->display( 'Author', true, false ),
|
288 |
+
'AuthorURI' => $theme->display( 'AuthorURI', true, false ),
|
289 |
+
'Version' => $theme->get( 'Version' ),
|
290 |
+
'Template' => $theme->get( 'Template' ),
|
291 |
+
'Status' => $theme->get( 'Status' ),
|
292 |
+
'Tags' => $theme->get( 'Tags' ),
|
293 |
+
'Title' => $theme->get( 'Name' ),
|
294 |
+
'AuthorName' => $theme->display( 'Author', false, false ),
|
295 |
+
'License' => $theme->display( 'License', false, false ),
|
296 |
+
'License URI' => $theme->display( 'License URI', false, false ),
|
297 |
+
'Template Version' => $theme->display( 'Template Version', false, false ),
|
298 |
);
|
299 |
return $theme_data;
|
300 |
}
|
checks/badthings.php
CHANGED
@@ -14,7 +14,10 @@ class Bad_Checks implements themecheck {
|
|
14 |
'/uudecode/ims' => __( 'uudecode() is not allowed', 'theme-check' ),
|
15 |
'/str_rot13/ims' => __( 'str_rot13() is not allowed', 'theme-check' ),
|
16 |
'/cx=[0-9]{21}:[a-z0-9]{10}/' => __( 'Google search code detected', 'theme-check' ),
|
17 |
-
'/pub-[0-9]{16}/i' => __( 'Google advertising code detected', 'theme-check' )
|
|
|
|
|
|
|
18 |
);
|
19 |
|
20 |
$grep = '';
|
14 |
'/uudecode/ims' => __( 'uudecode() is not allowed', 'theme-check' ),
|
15 |
'/str_rot13/ims' => __( 'str_rot13() is not allowed', 'theme-check' ),
|
16 |
'/cx=[0-9]{21}:[a-z0-9]{10}/' => __( 'Google search code detected', 'theme-check' ),
|
17 |
+
'/pub-[0-9]{16}/i' => __( 'Google advertising code detected', 'theme-check' ),
|
18 |
+
'/sharesale/i' => __( 'Sharesale affiliate link detected', 'theme-check' ),
|
19 |
+
'/affiliate_id/i' => __( 'Potential affiliate link detected', 'theme-check' ),
|
20 |
+
'/(elementor_partner_id)|(wpbeaverbuilder.*?fla)/i' => __( 'Potential affiliate link detected', 'theme-check' ),
|
21 |
);
|
22 |
|
23 |
$grep = '';
|
checks/postthumb.php
CHANGED
@@ -16,7 +16,7 @@ class PostThumbnailCheck implements themecheck {
|
|
16 |
}
|
17 |
|
18 |
if ( strpos( $php, 'post-thumbnails' ) === false ) {
|
19 |
-
$this->error[] = '<span class="tc-lead tc-recommended">'.__('RECOMMENDED','theme-check').'</span>: '.__('No reference to post-thumbnails was found in the theme. If the theme has a thumbnail like functionality, it should be implemented with <strong>add_theme_support( "post-thumbnails" )</strong>in the functions.php file.', 'theme-check' );
|
20 |
}
|
21 |
|
22 |
return $ret;
|
@@ -24,4 +24,4 @@ class PostThumbnailCheck implements themecheck {
|
|
24 |
|
25 |
function getError() { return $this->error; }
|
26 |
}
|
27 |
-
$themechecks[] = new PostThumbnailCheck;
|
16 |
}
|
17 |
|
18 |
if ( strpos( $php, 'post-thumbnails' ) === false ) {
|
19 |
+
$this->error[] = '<span class="tc-lead tc-recommended">'.__('RECOMMENDED','theme-check').'</span>: '.__('No reference to post-thumbnails was found in the theme. If the theme has a thumbnail like functionality, it should be implemented with <strong>add_theme_support( "post-thumbnails" )</strong> in the functions.php file.', 'theme-check' );
|
20 |
}
|
21 |
|
22 |
return $ret;
|
24 |
|
25 |
function getError() { return $this->error; }
|
26 |
}
|
27 |
+
$themechecks[] = new PostThumbnailCheck;
|
checks/style_tags.php
CHANGED
@@ -5,25 +5,24 @@ class Style_Tags implements themecheck {
|
|
5 |
function check( $php_files, $css_files, $other_files ) {
|
6 |
|
7 |
checkcount();
|
8 |
-
$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 (
|
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 |
-
|
20 |
-
$
|
21 |
-
$
|
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[
|
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' );
|
@@ -47,14 +46,14 @@ class Style_Tags implements themecheck {
|
|
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
|
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
|
58 |
}
|
59 |
}
|
60 |
}
|
@@ -64,5 +63,96 @@ class Style_Tags implements themecheck {
|
|
64 |
}
|
65 |
|
66 |
function getError() { return $this->error; }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
67 |
}
|
68 |
-
$themechecks[] = new Style_Tags;
|
5 |
function check( $php_files, $css_files, $other_files ) {
|
6 |
|
7 |
checkcount();
|
8 |
+
$ret = true;
|
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 |
+
} else {
|
19 |
+
$deprecated_tags = $this->get_deprecated_tags();
|
20 |
+
$allowed_tags = $this->get_allowed_tags();
|
21 |
+
$subject_tags = $this->get_subject_tags();
|
|
|
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' );
|
46 |
if ( in_array( strtolower( $tag ), $allowed_tags ) ) {
|
47 |
if ( count( array_keys ($data[ 'Tags' ], $tag ) ) > 1) {
|
48 |
$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>' );
|
49 |
+
$ret = false;
|
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 |
}
|
63 |
}
|
64 |
|
65 |
function getError() { return $this->error; }
|
66 |
+
|
67 |
+
/**
|
68 |
+
* Get full list of allowed tags - including subject tags.
|
69 |
+
*
|
70 |
+
* @return array
|
71 |
+
*/
|
72 |
+
private function get_allowed_tags() {
|
73 |
+
$allowed_tags = array(
|
74 |
+
'grid-layout',
|
75 |
+
'one-column',
|
76 |
+
'two-columns',
|
77 |
+
'three-columns',
|
78 |
+
'four-columns',
|
79 |
+
'left-sidebar',
|
80 |
+
'right-sidebar',
|
81 |
+
'wide-blocks',
|
82 |
+
'flexible-header',
|
83 |
+
'footer-widgets',
|
84 |
+
'accessibility-ready',
|
85 |
+
'block-patterns',
|
86 |
+
'block-styles',
|
87 |
+
'buddypress',
|
88 |
+
'custom-background',
|
89 |
+
'custom-colors',
|
90 |
+
'custom-header',
|
91 |
+
'custom-logo',
|
92 |
+
'custom-menu',
|
93 |
+
'editor-style',
|
94 |
+
'featured-image-header',
|
95 |
+
'featured-images',
|
96 |
+
'front-page-post-form',
|
97 |
+
'full-width-template',
|
98 |
+
'full-site-editing',
|
99 |
+
'microformats',
|
100 |
+
'post-formats',
|
101 |
+
'rtl-language-support',
|
102 |
+
'sticky-post',
|
103 |
+
'theme-options',
|
104 |
+
'threaded-comments',
|
105 |
+
'translation-ready',
|
106 |
+
);
|
107 |
+
return array_merge( $allowed_tags, self::get_subject_tags() );
|
108 |
+
}
|
109 |
+
|
110 |
+
/**
|
111 |
+
* Get the list of subject tags.
|
112 |
+
*
|
113 |
+
* @return array
|
114 |
+
*/
|
115 |
+
private function get_subject_tags() {
|
116 |
+
return array(
|
117 |
+
'blog',
|
118 |
+
'e-commerce',
|
119 |
+
'education',
|
120 |
+
'entertainment',
|
121 |
+
'food-and-drink',
|
122 |
+
'holiday',
|
123 |
+
'news',
|
124 |
+
'photography',
|
125 |
+
'portfolio',
|
126 |
+
);
|
127 |
+
}
|
128 |
+
|
129 |
+
private function get_deprecated_tags() {
|
130 |
+
return array(
|
131 |
+
'flexible-width',
|
132 |
+
'fixed-width',
|
133 |
+
'black',
|
134 |
+
'blue',
|
135 |
+
'brown',
|
136 |
+
'gray',
|
137 |
+
'green',
|
138 |
+
'orange',
|
139 |
+
'pink',
|
140 |
+
'purple',
|
141 |
+
'red',
|
142 |
+
'silver',
|
143 |
+
'tan',
|
144 |
+
'white',
|
145 |
+
'yellow',
|
146 |
+
'dark',
|
147 |
+
'light',
|
148 |
+
'fixed-layout',
|
149 |
+
'fluid-layout',
|
150 |
+
'responsive-layout',
|
151 |
+
'blavatar',
|
152 |
+
'holiday',
|
153 |
+
'photoblogging',
|
154 |
+
'seasonal',
|
155 |
+
);
|
156 |
+
}
|
157 |
}
|
158 |
+
$themechecks[] = new Style_Tags();
|
main.php
CHANGED
@@ -2,153 +2,209 @@
|
|
2 |
function check_main( $theme ) {
|
3 |
global $themechecks, $data, $themename;
|
4 |
$themename = $theme;
|
5 |
-
$theme
|
6 |
-
$files
|
7 |
-
$data
|
8 |
-
if ( $data[
|
9 |
// This is a child theme, so we need to pull files from the parent, which HAS to be installed.
|
10 |
-
$parent = get_theme_root( $data[
|
11 |
if ( ! tc_get_theme_data( $parent . '/style.css' ) ) { // This should never happen but we will check while were here!
|
12 |
-
echo '<h2>'
|
|
|
|
|
|
|
|
|
|
|
|
|
13 |
return;
|
14 |
}
|
15 |
$parent_data = tc_get_theme_data( $parent . '/style.css' );
|
16 |
-
$themename
|
17 |
-
$files
|
18 |
}
|
19 |
|
20 |
if ( $files ) {
|
21 |
-
foreach( $files as $key => $filename ) {
|
22 |
-
if ( substr( $filename, -4 )
|
23 |
-
$php[$filename] = file_get_contents( $filename );
|
24 |
-
$php[$filename] = tc_strip_comments( $php[$filename] );
|
25 |
-
}
|
26 |
-
|
27 |
-
|
28 |
-
|
29 |
-
|
30 |
-
|
|
|
|
|
|
|
|
|
|
|
31 |
}
|
32 |
}
|
33 |
|
34 |
-
//
|
35 |
-
$success = run_themechecks($php, $css, $other);
|
36 |
|
37 |
global $checkcount;
|
38 |
|
39 |
-
//
|
40 |
-
echo '<h2>' .
|
41 |
echo '<div class="theme-info">';
|
42 |
-
if (file_exists( trailingslashit( WP_CONTENT_DIR . '/themes' ) . trailingslashit( basename( $theme ) ) . 'screenshot.png' ) ) {
|
43 |
$image = getimagesize( $theme . '/screenshot.png' );
|
44 |
echo '<div style="float:right" class="theme-info"><img style="max-height:180px;" src="' . trailingslashit( WP_CONTENT_URL . '/themes' ) . trailingslashit( basename( $theme ) ) . 'screenshot.png" />';
|
45 |
-
echo '<br /><div style="text-align:center">' . $image[0] . 'x' . $image[1] . ' ' . round( filesize( $theme . '/screenshot.png' )/1024 ) . 'k</div></div>';
|
46 |
}
|
47 |
|
48 |
-
echo ( !empty( $data[
|
49 |
-
echo ( !empty( $data[
|
50 |
-
echo ( !empty( $data[
|
51 |
-
echo ( !empty( $data[
|
52 |
-
echo ( !empty( $data[
|
53 |
-
echo ( !empty( $data[
|
54 |
-
echo ( !empty( $data[
|
55 |
-
echo ( !empty( $data[
|
56 |
-
echo ( !empty( $data[
|
57 |
|
58 |
-
if ( $data[
|
59 |
-
|
60 |
-
|
61 |
-
|
62 |
-
|
63 |
-
|
64 |
-
|
65 |
-
|
66 |
-
|
67 |
echo '<p>' . sprintf(
|
68 |
-
|
69 |
-
'
|
|
|
70 |
) . '</p>';
|
71 |
if ( empty( $data['Template Version'] ) ) {
|
72 |
-
echo '<p>' .
|
73 |
} else {
|
74 |
-
echo ( $data['Template Version'] < $parent_data['Version'] ) ? '<p>' . sprintf(
|
75 |
}
|
76 |
-
|
77 |
echo '</div><!-- .theme-info-->';
|
78 |
|
79 |
$plugins = get_plugins( '/theme-check' );
|
80 |
$version = explode( '.', $plugins['theme-check.php']['Version'] );
|
81 |
echo '<p>' . sprintf(
|
82 |
-
|
83 |
-
'<strong>' . $checkcount . '</strong>',
|
84 |
-
'<strong>' . $data[
|
85 |
-
'<strong>' . $version[0] . '</strong>',
|
86 |
-
'<strong>' . $version[1] . '</strong>'
|
87 |
) . '</p>';
|
88 |
$results = display_themechecks();
|
89 |
-
if (
|
90 |
-
echo '<h2>' . sprintf(
|
91 |
} else {
|
92 |
-
echo '<h2>' . sprintf(__('%1$s passed the tests', 'theme-check'), $data[
|
93 |
tc_success();
|
94 |
}
|
95 |
-
if ( !defined( 'WP_DEBUG' ) || WP_DEBUG
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
96 |
echo '<div class="tc-box">';
|
97 |
echo '<ul class="tc-result">';
|
98 |
-
echo
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
99 |
echo '</ul></div>';
|
100 |
}
|
101 |
}
|
102 |
|
103 |
-
//
|
104 |
function tc_strip_comments( $code ) {
|
105 |
-
$strip
|
106 |
-
|
107 |
-
|
108 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
109 |
$return = '';
|
110 |
-
$token
|
111 |
-
while( $token ) {
|
112 |
-
if( !is_array($token) ) {
|
113 |
-
$return.= $token;
|
114 |
-
} elseif( !isset( $strip[ $token[0] ] ) ) {
|
115 |
-
$return.= $token[1];
|
116 |
} else {
|
117 |
-
for( $i = 0, $token_length = strlen($token[1]); $i < $token_length; ++$i )
|
118 |
-
|
119 |
-
|
|
|
|
|
120 |
}
|
121 |
-
$token = next($tokens);
|
122 |
}
|
123 |
return $return;
|
124 |
}
|
125 |
|
126 |
|
127 |
function tc_intro() {
|
128 |
-
?>
|
129 |
-
<h2><?php
|
130 |
-
<p><?php
|
131 |
-
<h2><?php
|
132 |
-
<p
|
|
|
|
|
|
|
133 |
'<a href="https://profiles.wordpress.org/otto42/">Otto42</a>',
|
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
|
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
|
139 |
-
<p><a href="https://make.wordpress.org/themes/"><?php
|
140 |
<?php
|
141 |
}
|
142 |
|
143 |
function tc_success() {
|
144 |
?>
|
145 |
-
<div class="tc-success"><p><?php
|
146 |
-
<p
|
147 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
148 |
<ul>
|
149 |
-
<li><a href="https://developer.wordpress.org/themes/"><?php
|
150 |
-
<li><a href="https://wordpress.org/support/forum/wp-advanced/"><?php
|
151 |
-
<li><a href="https://github.com/WPTRT/theme-unit-test"><?php
|
152 |
</ul></div>
|
153 |
<?php
|
154 |
}
|
@@ -157,7 +213,7 @@ function tc_form() {
|
|
157 |
$themes = tc_get_themes();
|
158 |
echo '<form action="themes.php?page=themecheck" method="post">';
|
159 |
echo '<select name="themename">';
|
160 |
-
foreach( $themes as $name => $location ) {
|
161 |
echo '<option ';
|
162 |
if ( isset( $_POST['themename'] ) ) {
|
163 |
echo ( $location['Stylesheet'] === $_POST['themename'] ) ? 'selected="selected" ' : '';
|
@@ -167,9 +223,37 @@ function tc_form() {
|
|
167 |
echo ( basename( STYLESHEETPATH ) === $location['Stylesheet'] ) ? 'value="' . $location['Stylesheet'] . '" style="font-weight:bold;">' . $name . '</option>' : 'value="' . $location['Stylesheet'] . '">' . $name . '</option>';
|
168 |
}
|
169 |
echo '</select>';
|
170 |
-
echo '<input class="button" type="submit" value="' .
|
171 |
-
if ( defined( 'TC_PRE' ) || defined( 'TC_POST' ) )
|
172 |
-
|
|
|
|
|
173 |
wp_nonce_field( 'themecheck-nonce' );
|
174 |
echo '</form>';
|
175 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2 |
function check_main( $theme ) {
|
3 |
global $themechecks, $data, $themename;
|
4 |
$themename = $theme;
|
5 |
+
$theme = get_theme_root( $theme ) . "/$theme";
|
6 |
+
$files = listdir( $theme );
|
7 |
+
$data = tc_get_theme_data( $theme . '/style.css' );
|
8 |
+
if ( $data['Template'] ) {
|
9 |
// This is a child theme, so we need to pull files from the parent, which HAS to be installed.
|
10 |
+
$parent = get_theme_root( $data['Template'] ) . '/' . $data['Template'];
|
11 |
if ( ! tc_get_theme_data( $parent . '/style.css' ) ) { // This should never happen but we will check while were here!
|
12 |
+
echo '<h2>';
|
13 |
+
printf(
|
14 |
+
/* translators: The parent theme name. */
|
15 |
+
esc_html__( 'Parent theme %1$s not found! You have to have parent AND child-theme installed!', 'theme-check' ),
|
16 |
+
'<strong>' . esc_html( $data['Template'] ) . '</strong>'
|
17 |
+
);
|
18 |
+
echo '</h2>';
|
19 |
return;
|
20 |
}
|
21 |
$parent_data = tc_get_theme_data( $parent . '/style.css' );
|
22 |
+
$themename = basename( $parent );
|
23 |
+
$files = array_merge( listdir( $parent ), $files );
|
24 |
}
|
25 |
|
26 |
if ( $files ) {
|
27 |
+
foreach ( $files as $key => $filename ) {
|
28 |
+
if ( substr( $filename, -4 ) === '.php' && ! is_dir( $filename ) ) {
|
29 |
+
$php[ $filename ] = file_get_contents( $filename );
|
30 |
+
$php[ $filename ] = tc_strip_comments( $php[ $filename ] );
|
31 |
+
} elseif ( substr( $filename, -4 ) === '.css' && ! is_dir( $filename ) ) {
|
32 |
+
$css[ $filename ] = file_get_contents( $filename );
|
33 |
+
} else {
|
34 |
+
// In local development it might be useful to skip other files
|
35 |
+
// (non .php or .css files) in dev directories.
|
36 |
+
if ( apply_filters( 'tc_skip_development_directories', false ) ) {
|
37 |
+
if ( tc_is_other_file_in_dev_directory( $filename ) ) {
|
38 |
+
continue;
|
39 |
+
}
|
40 |
+
}
|
41 |
+
$other[ $filename ] = ( ! is_dir( $filename ) ) ? file_get_contents( $filename ) : '';
|
42 |
}
|
43 |
}
|
44 |
|
45 |
+
// Run the checks.
|
46 |
+
$success = run_themechecks( $php, $css, $other );
|
47 |
|
48 |
global $checkcount;
|
49 |
|
50 |
+
// Second loop, to display the errors.
|
51 |
+
echo '<h2>' . esc_html__( 'Theme Info', 'theme-check' ) . ': </h2>';
|
52 |
echo '<div class="theme-info">';
|
53 |
+
if ( file_exists( trailingslashit( WP_CONTENT_DIR . '/themes' ) . trailingslashit( basename( $theme ) ) . 'screenshot.png' ) ) {
|
54 |
$image = getimagesize( $theme . '/screenshot.png' );
|
55 |
echo '<div style="float:right" class="theme-info"><img style="max-height:180px;" src="' . trailingslashit( WP_CONTENT_URL . '/themes' ) . trailingslashit( basename( $theme ) ) . 'screenshot.png" />';
|
56 |
+
echo '<br /><div style="text-align:center">' . $image[0] . 'x' . $image[1] . ' ' . round( filesize( $theme . '/screenshot.png' ) / 1024 ) . 'k</div></div>';
|
57 |
}
|
58 |
|
59 |
+
echo ( ! empty( $data['Title'] ) ) ? '<p><label>' . esc_html__( 'Title', 'theme-check' ) . '</label><span class="info">' . esc_html( $data['Title'] ) . '</span></p>' : '';
|
60 |
+
echo ( ! empty( $data['Version'] ) ) ? '<p><label>' . esc_html__( 'Version', 'theme-check' ) . '</label><span class="info">' . esc_html( $data['Version'] ) . '</span></p>' : '';
|
61 |
+
echo ( ! empty( $data['AuthorName'] ) ) ? '<p><label>' . esc_html__( 'Author', 'theme-check' ) . '</label><span class="info">' . esc_html( $data['AuthorName'] ) . '</span></p>' : '';
|
62 |
+
echo ( ! empty( $data['AuthorURI'] ) ) ? '<p><label>' . esc_html__( 'Author URI', 'theme-check' ) . '</label><span class="info"><a href="' . esc_attr( $data['AuthorURI'] ) . '">' . $data['AuthorURI'] . '</a></span></p>' : '';
|
63 |
+
echo ( ! empty( $data['URI'] ) ) ? '<p><label>' . esc_html__( 'Theme URI', 'theme-check' ) . '</label><span class="info"><a href="' . esc_attr( $data['URI'] ) . '">' . $data['URI'] . '</a></span></p>' : '';
|
64 |
+
echo ( ! empty( $data['License'] ) ) ? '<p><label>' . esc_html__( 'License', 'theme-check' ) . '</label><span class="info">' . esc_html( $data['License'] ) . '</span></p>' : '';
|
65 |
+
echo ( ! empty( $data['License URI'] ) ) ? '<p><label>' . esc_html__( 'License URI', 'theme-check' ) . '</label><span class="info">' . $data['License URI'] . '</span></p>' : '';
|
66 |
+
echo ( ! empty( $data['Tags'] ) ) ? '<p><label>' . esc_html__( 'Tags', 'theme-check' ) . '</label><span class="info">' . implode( ', ', $data['Tags'] ) . '</span></p>' : '';
|
67 |
+
echo ( ! empty( $data['Description'] ) ) ? '<p><label>' . esc_html__( 'Description', 'theme-check' ) . '</label><span class="info">' . $data['Description'] . '</span></p>' : '';
|
68 |
|
69 |
+
if ( $data['Template'] ) {
|
70 |
+
if ( $data['Template Version'] > $parent_data['Version'] ) {
|
71 |
+
echo '<p>' . sprintf(
|
72 |
+
esc_html__( 'This child theme requires at least version %1$s of theme %2$s to be installed. You only have %3$s please update the parent theme.', 'theme-check' ),
|
73 |
+
'<strong>' . esc_html( $data['Template Version'] ) . '</strong>',
|
74 |
+
'<strong>' . esc_html( $parent_data['Title'] ) . '</strong>',
|
75 |
+
'<strong>' . esc_html( $parent_data['Version'] ) . '</strong>'
|
76 |
+
) . '</p>';
|
77 |
+
}
|
78 |
echo '<p>' . sprintf(
|
79 |
+
/* translators: %s: Name of the parent theme. */
|
80 |
+
esc_html__( 'This is a child theme. The parent theme is: %s. These files have been included automatically!', 'theme-check' ),
|
81 |
+
'<strong>' . esc_html( $data['Template'] ) . '</strong>'
|
82 |
) . '</p>';
|
83 |
if ( empty( $data['Template Version'] ) ) {
|
84 |
+
echo '<p>' . esc_html__( 'Child theme does not have the <strong>Template Version</strong> tag in style.css.', 'theme-check' ) . '</p>';
|
85 |
} else {
|
86 |
+
echo ( $data['Template Version'] < $parent_data['Version'] ) ? '<p>' . sprintf( esc_html__( 'Child theme is only tested up to version %1$s of %2$s breakage may occur! %3$s installed version is %4$s', 'theme-check' ), esc_html( $data['Template Version'] ), esc_html( $parent_data['Title'] ), esc_html( $parent_data['Title'] ), esc_html( $parent_data['Version'] ) ) . '</p>' : '';
|
87 |
}
|
88 |
+
}
|
89 |
echo '</div><!-- .theme-info-->';
|
90 |
|
91 |
$plugins = get_plugins( '/theme-check' );
|
92 |
$version = explode( '.', $plugins['theme-check.php']['Version'] );
|
93 |
echo '<p>' . sprintf(
|
94 |
+
esc_html__( ' Running %1$s tests against %2$s using Guidelines Version: %3$s Plugin revision: %4$s', 'theme-check' ),
|
95 |
+
'<strong>' . esc_html( $checkcount ) . '</strong>',
|
96 |
+
'<strong>' . esc_html( $data['Title'] ) . '</strong>',
|
97 |
+
'<strong>' . esc_html( $version[0] ) . '</strong>',
|
98 |
+
'<strong>' . esc_html( $version[1] ) . '</strong>'
|
99 |
) . '</p>';
|
100 |
$results = display_themechecks();
|
101 |
+
if ( ! $success ) {
|
102 |
+
echo '<h2>' . sprintf( esc_html__( 'One or more errors were found for %1$s.', 'theme-check' ), esc_html( $data['Title'] ) ) . '</h2>';
|
103 |
} else {
|
104 |
+
echo '<h2>' . sprintf( __( '%1$s passed the tests', 'theme-check' ), esc_html( $data['Title'] ) ) . '</h2>';
|
105 |
tc_success();
|
106 |
}
|
107 |
+
if ( ! defined( 'WP_DEBUG' ) || WP_DEBUG === false ) {
|
108 |
+
echo '<div class="updated">';
|
109 |
+
echo '<span class="tc-fail">';
|
110 |
+
echo esc_html__( 'WARNING', 'theme-check' );
|
111 |
+
echo '</span> ';
|
112 |
+
echo '<strong>';
|
113 |
+
echo esc_html__( 'WP_DEBUG is not enabled!', 'theme-check' );
|
114 |
+
echo '</strong>';
|
115 |
+
printf(
|
116 |
+
/* translators: %1$s is an opening anchor tag. %2$s is the closing part of the tag. */
|
117 |
+
esc_html__( 'Please test your theme with %1$sdebug enabled%2$s before you upload!', 'theme-check' ),
|
118 |
+
'<a href="https://wordpress.org/support/article/editing-wp-config-php/">',
|
119 |
+
'</a>'
|
120 |
+
);
|
121 |
+
echo '</div>';
|
122 |
+
}
|
123 |
echo '<div class="tc-box">';
|
124 |
echo '<ul class="tc-result">';
|
125 |
+
echo wp_kses(
|
126 |
+
$results,
|
127 |
+
array(
|
128 |
+
'li' => array(),
|
129 |
+
'span' => array(
|
130 |
+
'class' => array(),
|
131 |
+
),
|
132 |
+
'strong' => array(),
|
133 |
+
)
|
134 |
+
);
|
135 |
echo '</ul></div>';
|
136 |
}
|
137 |
}
|
138 |
|
139 |
+
// Strip comments from a PHP file in a way that will not change the underlying structure of the file.
|
140 |
function tc_strip_comments( $code ) {
|
141 |
+
$strip = array(
|
142 |
+
T_COMMENT => true,
|
143 |
+
T_DOC_COMMENT => true,
|
144 |
+
);
|
145 |
+
$newlines = array(
|
146 |
+
"\n" => true,
|
147 |
+
"\r" => true,
|
148 |
+
);
|
149 |
+
$tokens = token_get_all( $code );
|
150 |
+
reset( $tokens );
|
151 |
$return = '';
|
152 |
+
$token = current( $tokens );
|
153 |
+
while ( $token ) {
|
154 |
+
if ( ! is_array( $token ) ) {
|
155 |
+
$return .= $token;
|
156 |
+
} elseif ( ! isset( $strip[ $token[0] ] ) ) {
|
157 |
+
$return .= $token[1];
|
158 |
} else {
|
159 |
+
for ( $i = 0, $token_length = strlen( $token[1] ); $i < $token_length; ++$i ) {
|
160 |
+
if ( isset( $newlines[ $token[1][ $i ] ] ) ) {
|
161 |
+
$return .= $token[1][ $i ];
|
162 |
+
}
|
163 |
+
}
|
164 |
}
|
165 |
+
$token = next( $tokens );
|
166 |
}
|
167 |
return $return;
|
168 |
}
|
169 |
|
170 |
|
171 |
function tc_intro() {
|
172 |
+
?>
|
173 |
+
<h2><?php esc_html_e( 'About', 'theme-check' ); ?></h2>
|
174 |
+
<p><?php esc_html_e( "The Theme Check plugin is an easy way to test your theme and make sure it's up to date with the latest theme review standards. With it, you can run all the same automated testing tools on your theme that WordPress.org uses for theme submissions.", 'theme-check' ); ?></p>
|
175 |
+
<h2><?php esc_html_e( 'Contact', 'theme-check' ); ?></h2>
|
176 |
+
<p>
|
177 |
+
<?php
|
178 |
+
printf(
|
179 |
+
esc_html__( 'Theme Check is maintained by %1$s and %2$s.', 'theme-check' ),
|
180 |
'<a href="https://profiles.wordpress.org/otto42/">Otto42</a>',
|
181 |
'<a href="https://profiles.wordpress.org/pross/">Pross</a>'
|
182 |
); ?></p>
|
183 |
+
<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 Themes 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>
|
184 |
+
<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>
|
185 |
+
<h3><?php esc_html_e( 'Testers', 'theme-check' ); ?></h3>
|
186 |
+
<p><a href="https://make.wordpress.org/themes/"><?php esc_html_e( 'The WordPress Themes Team', 'theme-check' ); ?></a></p>
|
187 |
<?php
|
188 |
}
|
189 |
|
190 |
function tc_success() {
|
191 |
?>
|
192 |
+
<div class="tc-success"><p><?php esc_html_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>
|
193 |
+
<p>
|
194 |
+
<?php
|
195 |
+
printf(
|
196 |
+
/* translators: %1$s is an opening anchor tag. %2$s is the closing part of the tag. */
|
197 |
+
esc_html__( 'Make sure to review the guidelines at %1$sTheme Review%2$s before uploading a Theme.', 'theme-check' ),
|
198 |
+
'<a href="https://make.wordpress.org/themes/handbook/review/required/">',
|
199 |
+
'</a>'
|
200 |
+
);
|
201 |
+
?>
|
202 |
+
</p>
|
203 |
+
<h3><?php esc_html_e( 'Useful Links', 'theme-check' ); ?></h3>
|
204 |
<ul>
|
205 |
+
<li><a href="https://developer.wordpress.org/themes/"><?php esc_html_e( 'Theme Handbook', 'theme-check' ); ?></a></li>
|
206 |
+
<li><a href="https://wordpress.org/support/forum/wp-advanced/"><?php esc_html_e( 'Developing with WordPress Forum', 'theme-check' ); ?></a></li>
|
207 |
+
<li><a href="https://github.com/WPTRT/theme-unit-test"><?php esc_html_e( 'Theme Unit Tests', 'theme-check' ); ?></a></li>
|
208 |
</ul></div>
|
209 |
<?php
|
210 |
}
|
213 |
$themes = tc_get_themes();
|
214 |
echo '<form action="themes.php?page=themecheck" method="post">';
|
215 |
echo '<select name="themename">';
|
216 |
+
foreach ( $themes as $name => $location ) {
|
217 |
echo '<option ';
|
218 |
if ( isset( $_POST['themename'] ) ) {
|
219 |
echo ( $location['Stylesheet'] === $_POST['themename'] ) ? 'selected="selected" ' : '';
|
223 |
echo ( basename( STYLESHEETPATH ) === $location['Stylesheet'] ) ? 'value="' . $location['Stylesheet'] . '" style="font-weight:bold;">' . $name . '</option>' : 'value="' . $location['Stylesheet'] . '">' . $name . '</option>';
|
224 |
}
|
225 |
echo '</select>';
|
226 |
+
echo '<input class="button" type="submit" value="' . esc_attr__( 'Check it!', 'theme-check' ) . '" />';
|
227 |
+
if ( defined( 'TC_PRE' ) || defined( 'TC_POST' ) ) {
|
228 |
+
echo ' <input name="trac" type="checkbox" /> ' . esc_html__( 'Output in Trac format.', 'theme-check' );
|
229 |
+
}
|
230 |
+
echo '<input name="s_info" type="checkbox" /> ' . esc_html__( 'Suppress INFO.', 'theme-check' );
|
231 |
wp_nonce_field( 'themecheck-nonce' );
|
232 |
echo '</form>';
|
233 |
}
|
234 |
+
|
235 |
+
/**
|
236 |
+
* Used to allow some directories to be skipped during development.
|
237 |
+
*
|
238 |
+
* @param string $filename a filename/path
|
239 |
+
* @return boolean
|
240 |
+
*/
|
241 |
+
function tc_is_other_file_in_dev_directory( $filename ) {
|
242 |
+
$skip = false;
|
243 |
+
// Filterable List of dirs that you may want to skip other files in during
|
244 |
+
// development.
|
245 |
+
$dev_dirs = apply_filters(
|
246 |
+
'tc_common_dev_directories',
|
247 |
+
array(
|
248 |
+
'node_modules',
|
249 |
+
'vendor',
|
250 |
+
)
|
251 |
+
);
|
252 |
+
foreach ( $dev_dirs as $dev_dir ) {
|
253 |
+
if ( strpos( $filename, $dev_dir ) ) {
|
254 |
+
$skip = true;
|
255 |
+
break;
|
256 |
+
}
|
257 |
+
}
|
258 |
+
return $skip;
|
259 |
+
}
|
readme.txt
CHANGED
@@ -3,7 +3,7 @@ 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.org, upload, uploader, test, guideline, review
|
6 |
-
Stable tag:
|
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,5 +52,6 @@ comments, or feedback:[[br]]
|
|
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.
|
3 |
Requires at Least: 3.7
|
4 |
Tested Up To: 5.4
|
5 |
Tags: template, theme, check, checker, tool, wordpress.org, upload, uploader, test, guideline, review
|
6 |
+
Stable tag: 20200922.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 |
+
|
56 |
= 20200504.1 =
|
57 |
* Changes can be found in the changelog.txt file.
|
theme-check.php
CHANGED
@@ -1,14 +1,14 @@
|
|
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:
|
7 |
-
Version:
|
8 |
-
Text Domain: theme-check
|
9 |
-
License: GPLv2
|
10 |
-
License URI: https://www.gnu.org/licenses/gpl-2.0.html
|
11 |
-
*/
|
12 |
|
13 |
class ThemeCheckMain {
|
14 |
function __construct() {
|
@@ -17,16 +17,16 @@ class ThemeCheckMain {
|
|
17 |
}
|
18 |
|
19 |
function tc_i18n() {
|
20 |
-
load_plugin_textdomain( 'theme-check', false, dirname( plugin_basename( __FILE__ ) ) . '/lang/'
|
21 |
}
|
22 |
|
23 |
function load_styles() {
|
24 |
-
wp_enqueue_style('style', plugins_url( 'assets/style.css', __FILE__ ), null, null, 'screen');
|
25 |
}
|
26 |
|
27 |
function themecheck_add_page() {
|
28 |
$page = add_theme_page( 'Theme Check', 'Theme Check', 'manage_options', 'themecheck', array( $this, 'themecheck_do_page' ) );
|
29 |
-
add_action('admin_print_styles-' . $page, array( $this, 'load_styles' ) );
|
30 |
}
|
31 |
|
32 |
function tc_add_headers( $extra_headers ) {
|
@@ -35,8 +35,8 @@ class ThemeCheckMain {
|
|
35 |
}
|
36 |
|
37 |
function themecheck_do_page() {
|
38 |
-
if ( !current_user_can( 'manage_options' ) )
|
39 |
-
|
40 |
}
|
41 |
|
42 |
add_filter( 'extra_theme_headers', array( $this, 'tc_add_headers' ) );
|
@@ -46,22 +46,22 @@ class ThemeCheckMain {
|
|
46 |
|
47 |
?>
|
48 |
<div id="theme-check" class="wrap">
|
49 |
-
<h1><?php
|
50 |
<div class="theme-check">
|
51 |
<?php
|
52 |
tc_form();
|
53 |
-
if ( !isset( $_POST[
|
54 |
tc_intro();
|
55 |
|
56 |
}
|
57 |
|
58 |
-
if ( isset( $_POST[
|
59 |
check_admin_referer( 'themecheck-nonce' );
|
60 |
-
if ( isset( $_POST[
|
61 |
-
|
62 |
-
@ini_set( 'memory_limit', WP_MAX_MEMORY_LIMIT );
|
63 |
}
|
64 |
-
|
|
|
65 |
}
|
66 |
?>
|
67 |
</div> <!-- .theme-check-->
|
@@ -69,4 +69,4 @@ class ThemeCheckMain {
|
|
69 |
<?php
|
70 |
}
|
71 |
}
|
72 |
-
new ThemeCheckMain;
|
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: 20200922.1
|
8 |
+
* Text Domain: theme-check
|
9 |
+
* License: GPLv2
|
10 |
+
* License URI: https://www.gnu.org/licenses/gpl-2.0.html
|
11 |
+
*/
|
12 |
|
13 |
class ThemeCheckMain {
|
14 |
function __construct() {
|
17 |
}
|
18 |
|
19 |
function tc_i18n() {
|
20 |
+
load_plugin_textdomain( 'theme-check', false, dirname( plugin_basename( __FILE__ ) ) . '/lang/' );
|
21 |
}
|
22 |
|
23 |
function load_styles() {
|
24 |
+
wp_enqueue_style( 'style', plugins_url( 'assets/style.css', __FILE__ ), null, null, 'screen' );
|
25 |
}
|
26 |
|
27 |
function themecheck_add_page() {
|
28 |
$page = add_theme_page( 'Theme Check', 'Theme Check', 'manage_options', 'themecheck', array( $this, 'themecheck_do_page' ) );
|
29 |
+
add_action( 'admin_print_styles-' . $page, array( $this, 'load_styles' ) );
|
30 |
}
|
31 |
|
32 |
function tc_add_headers( $extra_headers ) {
|
35 |
}
|
36 |
|
37 |
function themecheck_do_page() {
|
38 |
+
if ( ! current_user_can( 'manage_options' ) ) {
|
39 |
+
wp_die( esc_html__( 'You do not have sufficient permissions to access this page.', 'theme-check' ) );
|
40 |
}
|
41 |
|
42 |
add_filter( 'extra_theme_headers', array( $this, 'tc_add_headers' ) );
|
46 |
|
47 |
?>
|
48 |
<div id="theme-check" class="wrap">
|
49 |
+
<h1><?php echo esc_html_x( 'Theme Check', 'title of the main page', 'theme-check' ); ?></h1>
|
50 |
<div class="theme-check">
|
51 |
<?php
|
52 |
tc_form();
|
53 |
+
if ( ! isset( $_POST['themename'] ) ) {
|
54 |
tc_intro();
|
55 |
|
56 |
}
|
57 |
|
58 |
+
if ( isset( $_POST['themename'] ) ) {
|
59 |
check_admin_referer( 'themecheck-nonce' );
|
60 |
+
if ( isset( $_POST['trac'] ) ) {
|
61 |
+
define( 'TC_TRAC', true );
|
|
|
62 |
}
|
63 |
+
wp_raise_memory_limit();
|
64 |
+
check_main( $_POST['themename'] );
|
65 |
}
|
66 |
?>
|
67 |
</div> <!-- .theme-check-->
|
69 |
<?php
|
70 |
}
|
71 |
}
|
72 |
+
new ThemeCheckMain();
|