Theme Check - Version 20140929.1

Version Description

  • Added new checks and updates from Frank Klein at Automattic. Thanks Frank!
  • Updated deprecated function listings
  • Customizer check: All add_settings must use sanitization callbacks, for security
  • Plugin territory checks: Themes must not register post types or taxonomies or add shortcodes for post content
  • Widgets: Calls to register_sidebar must be called from the widgets_init action hook
  • Title: tags must exist and not have anything in them other than a call to wp_title()
  • CDN: Checks for use of common CDNs (recommended only)
  • 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.
Download this release

Release Info

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

Version 20140929.1

assets/gray-grad.png ADDED
Binary file
assets/style.css ADDED
@@ -0,0 +1,77 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
+ }
checkbase.php ADDED
@@ -0,0 +1,311 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ // main global to hold our checks
3
+ global $themechecks;
4
+ $themechecks = array();
5
+
6
+ // counter for the checks
7
+ global $checkcount;
8
+ $checkcount = 0;
9
+
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;
37
+ }
38
+
39
+ 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
+ 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' ) ) $results = TC_PRE . $results;
67
+ $results = '<textarea cols=140 rows=20>' . strip_tags( $results );
68
+ if ( defined( 'TC_POST' ) ) $results = $results . TC_POST;
69
+ $results .= '</textarea>';
70
+ }
71
+ return $results;
72
+ }
73
+
74
+ function checkcount() {
75
+ global $checkcount;
76
+ $checkcount++;
77
+ }
78
+
79
+ // some functions theme checks use
80
+ function tc_grep( $error, $file ) {
81
+ $lines = file( $file, FILE_IGNORE_NEW_LINES ); // Read the theme file into an array
82
+ $line_index = 0;
83
+ $bad_lines = '';
84
+ foreach( $lines as $this_line ) {
85
+ if ( stristr ( $this_line, $error ) ) {
86
+ $error = str_replace( '"', "'", $error );
87
+ $this_line = str_replace( '"', "'", $this_line );
88
+ $error = ltrim( $error );
89
+ $pre = ( FALSE !== ( $pos = strpos( $this_line, $error ) ) ? substr( $this_line, 0, $pos ) : FALSE );
90
+ $pre = ltrim( htmlspecialchars( $pre ) );
91
+ $bad_lines .= "<pre class='tc-grep'>". __("Line ", "theme-check") . ( $line_index+1 ) . ": " . $pre . htmlspecialchars( substr( stristr( $this_line, $error ), 0, 75 ) ) . "</pre>";
92
+ }
93
+ $line_index++;
94
+ }
95
+ return str_replace( $error, '<span class="tc-grep">' . $error . '</span>', $bad_lines );
96
+ }
97
+
98
+ function tc_preg( $preg, $file ) {
99
+ $lines = file( $file, FILE_IGNORE_NEW_LINES ); // Read the theme file into an array
100
+ $line_index = 0;
101
+ $bad_lines = '';
102
+ $error = '';
103
+ foreach( $lines as $this_line ) {
104
+ if ( preg_match( $preg, $this_line, $matches ) ) {
105
+ $error = $matches[0];
106
+ $this_line = str_replace( '"', "'", $this_line );
107
+ $error = ltrim( $error );
108
+ $pre = ( FALSE !== ( $pos = strpos( $this_line, $error ) ) ? substr( $this_line, 0, $pos ) : FALSE );
109
+ $pre = ltrim( htmlspecialchars( $pre ) );
110
+ $bad_lines .= "<pre class='tc-grep'>" . __("Line ", "theme-check") . ( $line_index+1 ) . ": " . $pre . htmlspecialchars( substr( stristr( $this_line, $error ), 0, 75 ) ) . "</pre>";
111
+ }
112
+ $line_index++;
113
+
114
+ }
115
+ return str_replace( $error, '<span class="tc-grep">' . $error . '</span>', $bad_lines );
116
+ }
117
+
118
+ function tc_strxchr($haystack, $needle, $l_inclusive = 0, $r_inclusive = 0){
119
+ if(strrpos($haystack, $needle)){
120
+ //Everything before last $needle in $haystack.
121
+ $left = substr($haystack, 0, strrpos($haystack, $needle) + $l_inclusive);
122
+ //Switch value of $r_inclusive from 0 to 1 and viceversa.
123
+ $r_inclusive = ($r_inclusive == 0) ? 1 : 0;
124
+ //Everything after last $needle in $haystack.
125
+ $right = substr(strrchr($haystack, $needle), $r_inclusive);
126
+ //Return $left and $right into an array.
127
+ return array($left, $right);
128
+ } else {
129
+ if(strrchr($haystack, $needle)) return array('', substr(strrchr($haystack, $needle), $r_inclusive));
130
+ else return false;
131
+ }
132
+ }
133
+
134
+ function tc_filename( $file ) {
135
+ $filename = ( preg_match( '/themes\/[a-z0-9]*\/(.*)/', $file, $out ) ) ? $out[1] : basename( $file );
136
+ return $filename;
137
+ }
138
+
139
+ function tc_trac( $e ) {
140
+ $trac_left = array( '<strong>', '</strong>' );
141
+ $trac_right= array( "'''", "'''" );
142
+ $html_link = '/<a\s?href\s?=\s?[\'|"]([^"|\']*)[\'|"]>([^<]*)<\/a>/i';
143
+ $html_new = '[$1 $2]';
144
+ if ( defined( 'TC_TRAC' ) ) {
145
+ $e = preg_replace( $html_link, $html_new, $e );
146
+ $e = str_replace( $trac_left, $trac_right, $e );
147
+ $e = preg_replace( '/<pre.*?>/', "\r\n{{{\r\n", $e );
148
+ $e = str_replace( '</pre>', "\r\n}}}\r\n", $e );
149
+ }
150
+ return $e;
151
+ }
152
+
153
+ function listdir( $dir ) {
154
+ $files = array();
155
+ $dir_iterator = new RecursiveDirectoryIterator( $dir );
156
+ $iterator = new RecursiveIteratorIterator($dir_iterator, RecursiveIteratorIterator::SELF_FIRST);
157
+
158
+ foreach ($iterator as $file) {
159
+ array_push( $files, $file->getPathname() );
160
+ }
161
+ return $files;
162
+ }
163
+
164
+ function old_listdir( $start_dir='.' ) {
165
+ $files = array();
166
+ if ( is_dir( $start_dir ) ) {
167
+ $fh = opendir( $start_dir );
168
+ while ( ( $file = readdir( $fh ) ) !== false ) {
169
+ # loop through the files, skipping . and .., and recursing if necessary
170
+ if ( strcmp( $file, '.' )==0 || strcmp( $file, '..' )==0 ) continue;
171
+ $filepath = $start_dir . '/' . $file;
172
+ if ( is_dir( $filepath ) )
173
+ $files = array_merge( $files, listdir( $filepath ) );
174
+ else
175
+ array_push( $files, $filepath );
176
+ }
177
+ closedir( $fh );
178
+
179
+ } else {
180
+
181
+ # false if the function was called with an invalid non-directory argument
182
+ $files = false;
183
+ }
184
+ return $files;
185
+ }
186
+
187
+ function tc_print_r( $data ) {
188
+ $out = "\n<pre class='html-print-r'";
189
+ $out .= " style='border: 1px solid #ccc; padding: 7px;'>\n";
190
+ $out .= esc_html( print_r( $data, TRUE ) );
191
+ $out .= "\n</pre>\n";
192
+ echo $out;
193
+ }
194
+
195
+ function get_theme_data_from_contents( $theme_data ) {
196
+ $themes_allowed_tags = array(
197
+ 'a' => array(
198
+ 'href' => array(),'title' => array()
199
+ ),
200
+ 'abbr' => array(
201
+ 'title' => array()
202
+ ),
203
+ 'acronym' => array(
204
+ 'title' => array()
205
+ ),
206
+ 'code' => array(),
207
+ 'em' => array(),
208
+ 'strong' => array()
209
+ );
210
+
211
+ $theme_data = str_replace ( '\r', '\n', $theme_data );
212
+ preg_match( '|Theme Name:(.*)$|mi', $theme_data, $theme_name );
213
+ preg_match( '|Theme URI:(.*)$|mi', $theme_data, $theme_uri );
214
+ preg_match( '|Description:(.*)$|mi', $theme_data, $description );
215
+
216
+ if ( preg_match( '|Author URI:(.*)$|mi', $theme_data, $author_uri ) )
217
+ $author_uri = esc_url( trim( $author_uri[1]) );
218
+ else
219
+ $author_uri = '';
220
+
221
+ if ( preg_match( '|Template:(.*)$|mi', $theme_data, $template ) )
222
+ $template = wp_kses( trim( $template[1] ), $themes_allowed_tags );
223
+ else
224
+ $template = '';
225
+
226
+ if ( preg_match( '|Version:(.*)|i', $theme_data, $version ) )
227
+ $version = wp_kses( trim( $version[1] ), $themes_allowed_tags );
228
+ else
229
+ $version = '';
230
+
231
+ if ( preg_match('|Status:(.*)|i', $theme_data, $status) )
232
+ $status = wp_kses( trim( $status[1] ), $themes_allowed_tags );
233
+ else
234
+ $status = 'publish';
235
+
236
+ if ( preg_match('|Tags:(.*)|i', $theme_data, $tags) )
237
+ $tags = array_map( 'trim', explode( ',', wp_kses( trim( $tags[1] ), array() ) ) );
238
+ else
239
+ $tags = array();
240
+
241
+ $theme = ( isset( $theme_name[1] ) ) ? wp_kses( trim( $theme_name[1] ), $themes_allowed_tags ) : '';
242
+
243
+ $theme_uri = ( isset( $theme_uri[1] ) ) ? esc_url( trim( $theme_uri[1] ) ) : '';
244
+
245
+ $description = ( isset( $description[1] ) ) ? wp_kses( trim( $description[1] ), $themes_allowed_tags ) : '';
246
+
247
+ if ( preg_match( '|Author:(.*)$|mi', $theme_data, $author_name ) ) {
248
+ if ( empty( $author_uri ) ) {
249
+ $author = wp_kses( trim( $author_name[1] ), $themes_allowed_tags );
250
+ } else {
251
+ $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 ) );
252
+ }
253
+ } else {
254
+ $author = __('Anonymous');
255
+ }
256
+
257
+ return array( 'Name' => $theme, 'Title' => $theme, 'URI' => $theme_uri, 'Description' => $description, 'Author' => $author, 'Author_URI' => $author_uri, 'Version' => $version, 'Template' => $template, 'Status' => $status, 'Tags' => $tags );
258
+ }
259
+
260
+ /*
261
+ * 3.3/3.4 compat
262
+ *
263
+ */
264
+ function tc_get_themes() {
265
+
266
+ if ( ! class_exists( 'WP_Theme' ) )
267
+ return get_themes();
268
+
269
+ global $wp_themes;
270
+ if ( isset( $wp_themes ) )
271
+ return $wp_themes;
272
+
273
+ $themes = wp_get_themes();
274
+ $wp_themes = array();
275
+
276
+ foreach ( $themes as $theme ) {
277
+ $name = $theme->get('Name');
278
+ if ( isset( $wp_themes[ $name ] ) )
279
+ $wp_themes[ $name . '/' . $theme->get_stylesheet() ] = $theme;
280
+ else
281
+ $wp_themes[ $name ] = $theme;
282
+ }
283
+
284
+ return $wp_themes;
285
+ }
286
+
287
+ function tc_get_theme_data( $theme_file ) {
288
+
289
+ if ( ! class_exists( 'WP_Theme' ) )
290
+ return get_theme_data( $theme_file );
291
+
292
+ $theme = new WP_Theme( basename( dirname( $theme_file ) ), dirname( dirname( $theme_file ) ) );
293
+
294
+ $theme_data = array(
295
+ 'Name' => $theme->get('Name'),
296
+ 'URI' => $theme->display('ThemeURI', true, false),
297
+ 'Description' => $theme->display('Description', true, false),
298
+ 'Author' => $theme->display('Author', true, false),
299
+ 'AuthorURI' => $theme->display('AuthorURI', true, false),
300
+ 'Version' => $theme->get('Version'),
301
+ 'Template' => $theme->get('Template'),
302
+ 'Status' => $theme->get('Status'),
303
+ 'Tags' => $theme->get('Tags'),
304
+ 'Title' => $theme->get('Name'),
305
+ 'AuthorName' => $theme->display('Author', false, false),
306
+ 'License' => $theme->display( 'License', false, false),
307
+ 'License URI' => $theme->display( 'License URI', false, false),
308
+ 'Template Version' => $theme->display( 'Template Version', false, false)
309
+ );
310
+ return $theme_data;
311
+ }
checks/admin_menu.php ADDED
@@ -0,0 +1,56 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ class AdminMenu implements themecheck {
3
+ protected $error = array();
4
+
5
+ function check( $php_files, $css_files, $other_files) {
6
+
7
+ $ret = true;
8
+
9
+
10
+ //check for levels deprecated in 2.0 in creating menus.
11
+
12
+ $checks = array(
13
+ '/([^_](add_(admin|submenu|menu|dashboard|posts|media|links|pages|comments|theme|plugins|users|management|options)_page)\s?\([^,]*,[^,]*,\s[\'|"]?(level_[0-9]|[0-9])[^;|\r|\r\n]*)/' => __( 'User levels were deprecated in <strong>2.0</strong>. Please see <a href="http://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="http://codex.wordpress.org/Roles_and_Capabilities">Roles_and_Capabilities</a>', 'theme-check' )
15
+ );
16
+
17
+ foreach ( $php_files as $php_key => $phpfile ) {
18
+ foreach ( $checks as $key => $check ) {
19
+ checkcount();
20
+ if ( preg_match( $key, $phpfile, $matches ) ) {
21
+ $filename = tc_filename( $php_key );
22
+ $grep = ( isset( $matches[2] ) ) ? tc_grep( $matches[2], $php_key ) : tc_grep( $matches[1], $php_key );
23
+ $this->error[] = sprintf('<span class="tc-lead tc-warning">'.__( 'WARNING', 'theme-check' ) . '</span>: <strong>%1$s</strong>. %2$s%3$s', $filename, $check, $grep );
24
+ $ret = false;
25
+ }
26
+ }
27
+ }
28
+
29
+
30
+ //check for add_admin_page
31
+
32
+ $checks = array(
33
+ '/([^_]add_(admin|submenu|menu|dashboard|posts|media|links|pages|comments|plugins|users|management|options)_page\()/' => __( 'Themes should use <strong>add_theme_page()</strong> for adding admin pages.', 'theme-check' )
34
+ );
35
+
36
+
37
+ foreach ( $php_files as $php_key => $phpfile ) {
38
+ foreach ( $checks as $key => $check ) {
39
+ checkcount();
40
+ if ( preg_match( $key, $phpfile, $matches ) ) {
41
+ $filename = tc_filename( $php_key );
42
+ $error = ltrim( rtrim( $matches[0], '(' ) );
43
+ $grep = tc_grep( $error, $php_key );
44
+ $this->error[] = sprintf('<span class="tc-lead tc-required">'.__( 'REQUIRED', 'theme-check' ) .'</span>: <strong>%1$s</strong>. %2$s%3$s', $filename, $check, $grep);
45
+ $ret = false;
46
+ }
47
+ }
48
+ }
49
+
50
+ return $ret;
51
+ }
52
+
53
+ function getError() { return $this->error; }
54
+ }
55
+
56
+ $themechecks[] = new AdminMenu;
checks/artisteer.php ADDED
@@ -0,0 +1,33 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class ArtisteerCheck implements themecheck {
4
+ protected $error = array();
5
+
6
+ function check( $php_files, $css_files, $other_files) {
7
+
8
+ // combine all the php files into one string to make it easier to search
9
+ $php = implode( ' ', $php_files );
10
+
11
+ checkcount();
12
+
13
+ $ret = true;
14
+ if (
15
+ strpos( $php, 'art_normalize_widget_style_tokens' ) !== false
16
+ || strpos( $php, 'art_include_lib' ) !== false
17
+ || strpos( $php, '_remove_last_slash($url) {' ) !== false
18
+ || strpos( $php, 'adi_normalize_widget_style_tokens' ) !== false
19
+ || strpos( $php, 'm_normalize_widget_style_tokens' ) !== false
20
+ || strpos ( $php, "bw = '<!--- BEGIN Widget --->';" ) !== false
21
+ || strpos ( $php, "ew = '<!-- end_widget -->';" ) !== false
22
+ || strpos ( $php, "end_widget' => '<!-- end_widget -->'") !== false
23
+ ) {
24
+ $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' );
25
+ $ret = false;
26
+ }
27
+
28
+ return $ret;
29
+ }
30
+
31
+ function getError() { return $this->error; }
32
+ }
33
+ $themechecks[] = new ArtisteerCheck;
checks/badthings.php ADDED
@@ -0,0 +1,57 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ class Bad_Checks implements themecheck {
3
+ protected $error = array();
4
+
5
+ function check( $php_files, $css_files, $other_files ) {
6
+ $ret = true;
7
+
8
+ $checks = array(
9
+ '/(?<![_|a-z0-9|\.])eval\s?\(/i' => __( 'eval() is not allowed.', 'theme-check' ),
10
+ '/[^a-z0-9](?<!_)(popen|proc_open|[^_]exec|shell_exec|system|passthru)\(/' => __( 'PHP system calls are often disabled by server admins and should not be in themes', 'theme-check' ),
11
+ '/\s?ini_set\(/' => __( 'Themes should not change server PHP settings', 'theme-check' ),
12
+ '/base64_decode/' => __( 'base64_decode() is not allowed', 'theme-check' ),
13
+ '/base64_encode/' => __( 'base64_encode() is not allowed', 'theme-check' ),
14
+ '/uudecode/ims' => __( 'uudecode() is not allowed', 'theme-check' ),
15
+ '/str_rot13/ims' => __( 'str_rot13() is not allowed', 'theme-check' ),
16
+ '/cx=[0-9]{21}:[a-z0-9]{10}/' => __( 'Google search code detected', 'theme-check' ),
17
+ '/pub-[0-9]{16}/i' => __( 'Google advertising code detected', 'theme-check' )
18
+ );
19
+
20
+ $grep = '';
21
+
22
+ foreach ( $php_files as $php_key => $phpfile ) {
23
+ foreach ( $checks as $key => $check ) {
24
+ checkcount();
25
+ if ( preg_match( $key, $phpfile, $matches ) ) {
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 <strong>%1$s</strong> in the file <strong>%2$s</strong>. %3$s. %4$s', $error, $filename, $check, $grep );
30
+ $ret = false;
31
+ }
32
+ }
33
+ }
34
+
35
+
36
+ $checks = array(
37
+ '/cx=[0-9]{21}:[a-z0-9]{10}/' => __( 'Google search code detected', 'theme-check' ),
38
+ '/pub-[0-9]{16}/' => __( 'Google advertising code detected', 'theme-check' )
39
+ );
40
+
41
+ foreach ( $other_files as $php_key => $phpfile ) {
42
+ foreach ( $checks as $key => $check ) {
43
+ checkcount();
44
+ if ( preg_match( $key, $phpfile, $matches ) ) {
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
+ }
52
+ }
53
+ return $ret;
54
+ }
55
+ function getError() { return $this->error; }
56
+ }
57
+ $themechecks[] = new Bad_Checks;
checks/basic.php ADDED
@@ -0,0 +1,47 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ // do some basic checks for strings
4
+ class Basic_Checks implements themecheck {
5
+ protected $error = array();
6
+
7
+ function check( $php_files, $css_files, $other_files) {
8
+
9
+ $php = implode( ' ', $php_files );
10
+ $grep = '';
11
+ $ret = true;
12
+
13
+ $checks = array(
14
+ 'DOCTYPE' => __( 'See: <a href="http://codex.wordpress.org/HTML_to_XHTML">http://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\(' => __( 'See: <a href="http://codex.wordpress.org/Function_Reference/wp_footer">wp_footer</a><pre> &lt;?php wp_footer(); ?&gt;</pre>', 'theme-check' ),
16
+ 'wp_head\(' => __( 'See: <a href="http://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="http://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?("|\')automatic-feed-links("|\')\s?\)' => __( 'See: <a href="http://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\(' => __( 'See: <a href="http://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\(' => __( 'See: <a href="http://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\(' => __( 'See: <a href="http://codex.wordpress.org/Template_Tags/comment_form">comment_form</a><pre> &lt;?php comment_form(); ?&gt;</pre>', 'theme-check' ),
23
+ 'body_class' => __( 'See: <a href="http://codex.wordpress.org/Template_Tags/body_class">body_class</a><pre> &lt;?php body_class( $class ); ?&gt;</pre>', 'theme-check' ),
24
+ 'wp_link_pages\(' => __( 'See: <a href="http://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\(' => __( 'See: <a href="http://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) {
29
+ checkcount();
30
+ if ( !preg_match( '/' . $key . '/i', $php ) ) {
31
+ if ( $key === 'add_theme_support\(\s?("|\')automatic-feed-links("|\')\s?\)' ) $key = __( 'add_theme_support( \'automatic-feed-links\' )', 'theme-check');
32
+ if ( $key === 'wp_enqueue_script\(\s?("|\')comment-reply("|\')' ) $key = __( 'wp_enqueue_script( \'comment-reply\' )', 'theme-check');
33
+ if ( $key === 'body_class' ) $key = __( 'body_class call in body tag', 'theme-check');
34
+ if ( $key === 'register_sidebar[s]?\(' ) $key = __( 'register_sidebar() or register_sidebars()', 'theme-check');
35
+ $key = ltrim( trim ( trim( $key, '(' ), '\\' ) );
36
+ $this->error[] = sprintf( '<span class="tc-lead tc-required">'.__('REQUIRED','theme-check').'</span>: '.__('Could not find <strong>%1$s</strong>. %2$s', 'theme-check' ), $key, $check );
37
+ $ret = false;
38
+ }
39
+ }
40
+
41
+ return $ret;
42
+ }
43
+
44
+ function getError() { return $this->error; }
45
+ }
46
+
47
+ $themechecks[] = new Basic_Checks;
checks/cdn.php ADDED
@@ -0,0 +1,42 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Checks for resources being loaded from CDNs.
5
+ */
6
+
7
+ class CDNCheck implements themecheck {
8
+ protected $error = array();
9
+
10
+ function check( $php_files, $css_files, $other_files) {
11
+
12
+ $ret = true;
13
+ $php_code = implode( ' ', $php_files );
14
+
15
+ checkcount();
16
+
17
+ $cdn_list = array(
18
+ 'bootstrap-maxcdn' => 'maxcdn.bootstrapcdn.com/bootstrap',
19
+ 'bootstrap-netdna' => 'netdna.bootstrapcdn.com/bootstrap',
20
+ 'bootswatch-maxcdn' => 'maxcdn.bootstrapcdn.com/bootswatch',
21
+ 'bootswatch-netdna' => 'netdna.bootstrapcdn.com/bootswatch',
22
+ 'font-awesome-maxcdn' => 'maxcdn.bootstrapcdn.com/font-awesome',
23
+ 'font-awesome-netdna' => 'netdna.bootstrapcdn.com/font-awesome',
24
+ 'html5shiv-google' => 'html5shiv.googlecode.com/svn/trunk/html5.js',
25
+ 'html5shiv-maxcdn' => 'oss.maxcdn.com/libs/html5shiv',
26
+ 'jquery' => 'code.jquery.com/jquery-',
27
+ 'respond-js' => 'oss.maxcdn.com/libs/respond.js',
28
+ );
29
+
30
+ foreach( $cdn_list as $cdn_slug => $cdn_url ) {
31
+ if ( false !== strpos( $php_code, $cdn_url ) ) {
32
+ $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>' );
33
+ //$ret = false;
34
+ }
35
+ }
36
+
37
+ return $ret;
38
+ }
39
+
40
+ function getError() { return $this->error; }
41
+ }
42
+ $themechecks[] = new CDNCheck;
checks/comment_reply.php ADDED
@@ -0,0 +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="http://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/commpage.php ADDED
@@ -0,0 +1,24 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class CommentPaginationCheck implements themecheck {
4
+ protected $error = array();
5
+
6
+ function check( $php_files, $css_files, $other_files ) {
7
+ $ret = true;
8
+
9
+ // combine all the php files into one string to make it easier to search
10
+ $php = implode( ' ', $php_files );
11
+ checkcount();
12
+ if (strpos( $php, 'paginate_comments_links' ) === false &&
13
+ (strpos( $php, 'next_comments_link' ) === false && strpos( $php, 'previous_comments_link' ) === false ) ) {
14
+
15
+ $this->error[] = '<span class="tc-lead tc-required">'.__('REQUIRED','theme-check').'</span>: '.__('The theme doesn\'t have comment pagination code in it. Use <strong>paginate_comments_links()</strong> or <strong>next_comments_link()</strong> and <strong>previous_comments_link()</strong> to add comment pagination.', 'theme-check' );
16
+ $ret = false;
17
+ }
18
+
19
+ return $ret;
20
+ }
21
+
22
+ function getError() { return $this->error; }
23
+ }
24
+ $themechecks[] = new CommentPaginationCheck;
checks/constants.php ADDED
@@ -0,0 +1,33 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class Constants implements themecheck {
4
+ protected $error = array();
5
+
6
+ function check( $php_files, $css_files, $other_files ) {
7
+
8
+ $ret = true;
9
+
10
+ $checks = array(
11
+ 'STYLESHEETPATH' => 'get_stylesheet_directory()',
12
+ 'TEMPLATEPATH' => 'get_template_directory()',
13
+ 'PLUGINDIR' => 'WP_PLUGIN_DIR',
14
+ 'MUPLUGINDIR' => 'WPMU_PLUGIN_DIR'
15
+ );
16
+
17
+ foreach ( $php_files as $php_key => $phpfile ) {
18
+ foreach ( $checks as $key => $check ) {
19
+ checkcount();
20
+ if ( preg_match( '/[\s|]' . $key . '/', $phpfile, $matches ) ) {
21
+ $filename = tc_filename( $php_key );
22
+ $error = ltrim( rtrim( $matches[0], '(' ) );
23
+ $grep = tc_grep( $error, $php_key );
24
+ $this->error[] = sprintf('<span class="tc-lead tc-recommended">'.__('RECOMMENDED','theme-check').'</span>: '.__('<strong>%1$s</strong> was found in the file <strong>%2$s</strong>. Use <strong>%3$s</strong> instead.%4$s', 'theme-check'), $error, $filename, $check, $grep );
25
+ }
26
+ }
27
+ }
28
+ return $ret;
29
+ }
30
+
31
+ function getError() { return $this->error; }
32
+ }
33
+ $themechecks[] = new Constants;
checks/content-width.php ADDED
@@ -0,0 +1,23 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class ContentWidthCheck implements themecheck {
4
+ protected $error = array();
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, '$content_width' ) === false && !preg_match( '/add_filter\(\s?("|\')embed_defaults/', $php ) && !preg_match( '/add_filter\(\s?("|\')content_width/', $php ) ) {
14
+ $this->error[] = '<span class="tc-lead tc-required">'.__('REQUIRED','theme-check').'</span>: '.__('No content width has been defined. Example: <pre>if ( ! isset( $content_width ) ) $content_width = 900;</pre>', 'theme-check' );
15
+ $ret = false;
16
+ }
17
+
18
+ return $ret;
19
+ }
20
+
21
+ function getError() { return $this->error; }
22
+ }
23
+ $themechecks[] = new ContentWidthCheck;
checks/customizer.php ADDED
@@ -0,0 +1,44 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Checks for the Customizer.
5
+ */
6
+
7
+ class CustomizerCheck implements themecheck {
8
+ protected $error = array();
9
+
10
+ function check( $php_files, $css_files, $other_files) {
11
+
12
+ $ret = true;
13
+
14
+ checkcount();
15
+
16
+ /**
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
+ }
35
+ }
36
+ }
37
+ }
38
+
39
+ return $ret;
40
+ }
41
+
42
+ function getError() { return $this->error; }
43
+ }
44
+ $themechecks[] = new CustomizerCheck;
checks/customs.php ADDED
@@ -0,0 +1,26 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class CustomCheck implements themecheck {
4
+ protected $error = array();
5
+
6
+ function check( $php_files, $css_files, $other_files) {
7
+
8
+ $ret = true;
9
+ $php = implode( ' ', $php_files );
10
+
11
+ checkcount();
12
+
13
+ if ( ! preg_match( '#add_theme_support\s?\(\s?[\'|"]custom-header#', $php ) ) {
14
+ $this->error[] = '<span class="tc-lead tc-recommended">'.__('RECOMMENDED','theme-check').'</span>: '.__('No reference to <strong>add_theme_support( "custom-header", $args )</strong> was found in the theme. It is recommended that the theme implement this functionality if using an image for the header.', 'theme-check' );
15
+ }
16
+
17
+ if ( ! preg_match( '#add_theme_support\s?\(\s?[\'|"]custom-background#', $php ) ) {
18
+ $this->error[] = '<span class="tc-lead tc-recommended">'.__('RECOMMENDED','theme-check').'</span>: '.__('No reference to <strong>add_theme_support( "custom-background", $args )</strong> was found in the theme. If the theme uses background images or solid colors for the background, then it is recommended that the theme implement this functionality.', 'theme-check' );
19
+ }
20
+
21
+ return $ret;
22
+ }
23
+
24
+ function getError() { return $this->error; }
25
+ }
26
+ $themechecks[] = new CustomCheck;
checks/dep_recommend.php ADDED
@@ -0,0 +1,60 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ // recommended deprecations checks... After some time, these will move into deprecated.php and become required.
3
+ class Deprecated_Recommended implements themecheck {
4
+ protected $error = array();
5
+
6
+ function check( $php_files, $css_files, $other_files ) {
7
+ $grep = '';
8
+
9
+ $ret = true;
10
+
11
+ $checks = array(
12
+ array( 'rich_edit_exists' => '', '3.9'),
13
+ array( 'default_topic_count_text' => '', '3.9'),
14
+ array( 'format_to_post' => '', '3.9'),
15
+ array( 'get_current_site_name' => 'get_current_site()', '3.9'),
16
+ array( 'wpmu_current_site' => '', '3.9'),
17
+ array( 'get_all_category_ids' => 'get_terms()', '4.0' ),
18
+ array( 'like_escape' => 'wpdb::esc_like()', '4.0' ),
19
+ array( 'url_is_accessable_via_ssl' => '', '4.0' ),
20
+ );
21
+
22
+ foreach ( $php_files as $php_key => $phpfile ) {
23
+ foreach ( $checks as $alt => $check ) {
24
+ checkcount();
25
+ $version = $check;
26
+ $key = key( $check );
27
+ $alt = $check[ $key ];
28
+ if ( preg_match( '/[\s?]' . $key . '\(/', $phpfile, $matches ) ) {
29
+ $filename = tc_filename( $php_key );
30
+ $error = ltrim( rtrim( $matches[0], '(' ) );
31
+ $version = $check[0];
32
+ $grep = tc_grep( $error, $php_key );
33
+
34
+ // Point out the deprecated function.
35
+ $error_msg = sprintf(
36
+ __( '%1$s found in the file %2$s. Deprecated since version %3$s.', 'theme-check' ),
37
+ '<strong>' . $error . '()</strong>',
38
+ '<strong>' . $filename . '</strong>',
39
+ '<strong>' . $version . '</strong>'
40
+ );
41
+
42
+ // Add alternative function when available.
43
+ if ( $alt ) {
44
+ $error_msg .= ' ' . sprintf( __( 'Use %s instead.', 'theme-check' ), '<strong>' . $alt . '</strong>' );
45
+ }
46
+
47
+ // Add the precise code match that was found.
48
+ $error_msg .= $grep;
49
+
50
+ // Add the finalized error message.
51
+ $this->error[] = '<span class="tc-lead tc-recommended">' . __('RECOMMENDED','theme-check') . '</span>: ' . $error_msg;
52
+ }
53
+ }
54
+ }
55
+ return $ret;
56
+ }
57
+
58
+ function getError() { return $this->error; }
59
+ }
60
+ $themechecks[] = new Deprecated_Recommended;
checks/deprecated.php ADDED
@@ -0,0 +1,264 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class Deprecated implements themecheck {
4
+ protected $error = array();
5
+
6
+ function check( $php_files, $css_files, $other_files ) {
7
+ $grep = '';
8
+
9
+ $ret = true;
10
+
11
+ $checks = array(
12
+ // start wp-includes deprecated
13
+ array( 'get_postdata' => 'get_post()', '1.5.1' ),
14
+ array( 'start_wp' => 'the Loop', '1.5' ),
15
+ array( 'the_category_id' => 'get_the_category()', '0.71' ),
16
+ array( 'the_category_head' => 'get_the_category_by_ID()', '0.71' ),
17
+ array( 'previous_post' => 'previous_post_link()', '2.0' ),
18
+ array( 'next_post' => 'next_post_link()', '2.0' ),
19
+ array( 'user_can_create_post' => 'current_user_can()', '2.0' ),
20
+ array( 'user_can_create_draft' => 'current_user_can()', '2.0' ),
21
+ array( 'user_can_edit_post' => 'current_user_can()', '2.0' ),
22
+ array( 'user_can_delete_post' => 'current_user_can()', '2.0' ),
23
+ array( 'user_can_set_post_date' => 'current_user_can()', '2.0' ),
24
+ array( 'user_can_edit_post_comments' => 'current_user_can()', '2.0' ),
25
+ array( 'user_can_delete_post_comments' => 'current_user_can()', '2.0' ),
26
+ array( 'user_can_edit_user' => 'current_user_can()', '2.0' ),
27
+ array( 'get_linksbyname' => 'get_bookmarks()', '2.1' ),
28
+ array( 'wp_get_linksbyname' => 'wp_list_bookmarks()', '2.1' ),
29
+ array( 'get_linkobjectsbyname' => 'get_bookmarks()', '2.1' ),
30
+ array( 'get_linkobjects' => 'get_bookmarks()', '2.1' ),
31
+ array( 'get_linksbyname_withrating' => 'get_bookmarks()', '2.1' ),
32
+ array( 'get_links_withrating' => 'get_bookmarks()', '2.1' ),
33
+ array( 'get_autotoggle' => '', '2.1' ),
34
+ array( 'list_cats' => 'wp_list_categories', '2.1' ),
35
+ array( 'wp_list_cats' => 'wp_list_categories', '2.1' ),
36
+ array( 'dropdown_cats' => 'wp_dropdown_categories()', '2.1' ),
37
+ array( 'list_authors' => 'wp_list_authors()', '2.1' ),
38
+ array( 'wp_get_post_cats' => 'wp_get_post_categories()', '2.1' ),
39
+ array( 'wp_set_post_cats' => 'wp_set_post_categories()', '2.1' ),
40
+ array( 'get_archives' => 'wp_get_archives', '2.1' ),
41
+ array( 'get_author_link' => 'get_author_posts_url()', '2.1' ),
42
+ array( 'link_pages' => 'wp_link_pages()', '2.1' ),
43
+ array( 'get_settings' => 'get_option()', '2.1' ),
44
+ array( 'permalink_link' => 'the_permalink()', '1.2' ),
45
+ array( 'permalink_single_rss' => 'permalink_rss()', '2.3' ),
46
+ array( 'wp_get_links' => 'wp_list_bookmarks()', '2.1' ),
47
+ array( 'get_links' => 'get_bookmarks()', '2.1' ),
48
+ array( 'get_links_list' => 'wp_list_bookmarks()', '2.1' ),
49
+ array( 'links_popup_script' => '', '2.1' ),
50
+ array( 'get_linkrating' => 'sanitize_bookmark_field()', '2.1' ),
51
+ array( 'get_linkcatname' => 'get_category()', '2.1' ),
52
+ array( 'comments_rss_link' => 'post_comments_feed_link()', '2.5' ),
53
+ array( 'get_category_rss_link' => 'get_category_feed_link()'. '2.5' ),
54
+ array( 'get_author_rss_link' => 'get_author_feed_link()', '2.5' ),
55
+ array( 'comments_rss' => 'get_post_comments_feed_link()', '2.2' ),
56
+ array( 'create_user' => 'wp_create_user()', '2.0' ),
57
+ array( 'gzip_compression' => '', '2.5' ),
58
+ array( 'get_commentdata' => 'get_comment()', '2.7' ),
59
+ array( 'get_catname' => 'get_cat_name()', '2.8' ),
60
+ array( 'get_category_children' => 'get_term_children', '2.8' ),
61
+ array( 'get_the_author_description' => 'get_the_author_meta(\'description\')', '2.8' ),
62
+ array( 'the_author_description' => 'the_author_meta(\'description\')', '2.8' ),
63
+ array( 'get_the_author_login' => 'the_author_meta(\'login\')', '2.8' ),
64
+ array( 'get_the_author_firstname' => 'get_the_author_meta(\'first_name\')', '2.8' ),
65
+ array( 'the_author_firstname' => 'the_author_meta(\'first_name\')', '2.8' ),
66
+ array( 'get_the_author_lastname' => 'get_the_author_meta(\'last_name\')', '2.8' ),
67
+ array( 'the_author_lastname' => 'the_author_meta(\'last_name\')', '2.8' ),
68
+ array( 'get_the_author_nickname' => 'get_the_author_meta(\'nickname\')', '2.8' ),
69
+ array( 'the_author_nickname' => 'the_author_meta(\'nickname\')', '2.8' ),
70
+ array( 'get_the_author_email' => 'get_the_author_meta(\'email\')', '2.8' ),
71
+ array( 'the_author_email' => 'the_author_meta(\'email\')', '2.8' ),
72
+ array( 'get_the_author_icq' => 'get_the_author_meta(\'icq\')', '2.8' ),
73
+ array( 'the_author_icq' => 'the_author_meta(\'icq\')', '2.8' ),
74
+ array( 'get_the_author_yim' => 'get_the_author_meta(\'yim\')', '2.8' ),
75
+ array( 'the_author_yim' => 'the_author_meta(\'yim\')', '2.8' ),
76
+ array( 'get_the_author_msn' => 'get_the_author_meta(\'msn\')', '2.8' ),
77
+ array( 'the_author_msn' => 'the_author_meta(\'msn\')', '2.8' ),
78
+ array( 'get_the_author_aim' => 'get_the_author_meta(\'aim\')', '2.8' ),
79
+ array( 'the_author_aim' => 'the_author_meta(\'aim\')', '2.8' ),
80
+ array( 'get_author_name' => 'get_the_author_meta(\'display_name\')', '2.8' ),
81
+ array( 'get_the_author_url' => 'get_the_author_meta(\'url\')', '2.8' ),
82
+ array( 'the_author_url' => 'the_author_meta(\'url\')', '2.8' ),
83
+ array( 'get_the_author_ID' => 'get_the_author_meta(\'ID\')', '2.8' ),
84
+ array( 'the_author_ID' => 'the_author_meta(\'ID\')', '2.8' ),
85
+ array( 'the_content_rss' => 'the_content_feed()', '2.9' ),
86
+ array( 'make_url_footnote' => '', '2.9' ),
87
+ array( '_c' => '_x()', '2.9' ),
88
+ array( 'translate_with_context' => '_x()', '3.0' ),
89
+ array( 'nc' => 'nx()', '3.0' ),
90
+ array( '__ngettext' => '_n_noop()', '2.8' ),
91
+ array( '__ngettext_noop' => '_n_noop()', '2.8' ),
92
+ array( 'get_alloptions' => 'wp_load_alloptions()', '3.0' ),
93
+ array( 'get_the_attachment_link' => 'wp_get_attachment_link()', '2.5' ),
94
+ array( 'get_attachment_icon_src' => 'wp_get_attachment_image_src()', '2.5' ),
95
+ array( 'get_attachment_icon' => 'wp_get_attachment_image()', '2.5' ),
96
+ array( 'get_attachment_innerhtml' => 'wp_get_attachment_image()', '2.5' ),
97
+ array( 'get_link' => 'get_bookmark()', '2.1' ),
98
+ array( 'sanitize_url' => 'esc_url()', '2.8' ),
99
+ array( 'clean_url' => 'esc_url()', '3.0' ),
100
+ array( 'js_escape' => 'esc_js()', '2.8' ),
101
+ array( 'wp_specialchars' => 'esc_html()', '2.8' ),
102
+ array( 'attribute_escape' => 'esc_attr()', '2.8' ),
103
+ array( 'register_sidebar_widget' => 'wp_register_sidebar_widget()', '2.8' ),
104
+ array( 'unregister_sidebar_widget' => 'wp_unregister_sidebar_widget()', '2.8' ),
105
+ array( 'register_widget_control' => 'wp_register_widget_control()', '2.8' ),
106
+ array( 'unregister_widget_control' => 'wp_unregister_widget_control()', '2.8' ),
107
+ array( 'delete_usermeta' => 'delete_user_meta()', '3.0' ),
108
+ array( 'get_usermeta' => 'get_user_meta()', '3.0' ),
109
+ array( 'update_usermeta' => 'update_user_meta()', '3.0' ),
110
+ array( 'automatic_feed_links' => 'add_theme_support( \'automatic-feed-links\' )', '3.0' ),
111
+ array( 'get_profile' => 'get_the_author_meta()', '3.0' ),
112
+ array( 'get_usernumposts' => 'count_user_posts()', '3.0' ),
113
+ array( 'funky_javascript_callback' => '', '3.0' ),
114
+ array( 'funky_javascript_fix' => '', '3.0' ),
115
+ array( 'is_taxonomy' => 'taxonomy_exists()', '3.0' ),
116
+ array( 'is_term' => 'term_exists()', '3.0' ),
117
+ array( 'is_plugin_page' => '$plugin_page and/or get_plugin_page_hookname() hooks', '3.1' ),
118
+ array( 'update_category_cache' => 'No alternatives', '3.1' ),
119
+ array( 'get_users_of_blog' => 'get_users()', '3.1' ),
120
+ array( 'wp_timezone_supported' => '', '3.2' ),
121
+ array( 'the_editor' => 'wp_editor', '3.3' ),
122
+ array( 'get_user_metavalues' => '', '3.3' ),
123
+ array( 'sanitize_user_object' => '', '3.3' ),
124
+ array( 'get_boundary_post_rel_link' => '', '3.3' ),
125
+ array( 'start_post_rel_link' => 'none available ', '3.3' ),
126
+ array( 'get_index_rel_link' => '', '3.3' ),
127
+ array( 'index_rel_link' => '', '3.3' ),
128
+ array( 'get_parent_post_rel_link' => '', '3.3' ),
129
+ array( 'parent_post_rel_link' => '', '3.3' ),
130
+ array( 'wp_admin_bar_dashboard_view_site_menu' => '', '3.3' ),
131
+ array( 'is_blog_user' => 'is_member_of_blog()', '3.3' ),
132
+ array( 'debug_fopen' => 'error_log()', '3.3' ),
133
+ array( 'debug_fwrite' => 'error_log()', '3.3' ),
134
+ array( 'debug_fclose' => 'error_log()', '3.3' ),
135
+ array( 'get_themes' => 'wp_get_themes()', '3.4' ),
136
+ array( 'get_theme' => 'wp_get_theme()', '3.4' ),
137
+ array( 'get_current_theme' => 'wp_get_theme()', '3.4' ),
138
+ array( 'clean_pre' => '', '3.4' ),
139
+ array( 'add_custom_image_header' => 'add_theme_support( \'custom-header\', $args )', '3.4' ),
140
+ array( 'remove_custom_image_header' => 'remove_theme_support( \'custom-header\' )', '3.4' ),
141
+ array( 'add_custom_background' => 'add_theme_support( \'custom-background\', $args )', '3.4' ),
142
+ array( 'remove_custom_background' => 'remove_theme_support( \'custom-background\' )', '3.4' ),
143
+ array( 'get_theme_data' => 'wp_get_theme()', '3.4' ),
144
+ array( 'update_page_cache' => 'update_post_cache()', '3.4' ),
145
+ array( 'clean_page_cache' => 'clean_post_cache()', '3.4' ),
146
+ array( 'wp_explain_nonce' => 'wp_nonce_ays', '3.4.1' ),
147
+ array( 'sticky_class' => 'post_class()', '3.5' ),
148
+ array( '_get_post_ancestors' => '', '3.5' ),
149
+ array( 'wp_load_image' => 'wp_get_image_editor()', '3.5' ),
150
+ array( 'image_resize' => 'wp_get_image_editor()', '3.5' ),
151
+ array( 'wp_get_single_post' => 'get_post()', '3.5' ),
152
+ array( 'user_pass_ok' => 'wp_authenticate()', '3.5' ),
153
+ array( '_save_post_hook' => '', '3.5' ),
154
+ array( 'gd_edit_image_support' => 'wp_image_editor_supports', '3.5' ),
155
+ array( 'get_user_id_from_string' => 'get_user_by()', '3.6' ),
156
+ array( 'wp_convert_bytes_to_hr' => 'size_format()', '3.6' ),
157
+ array('_search_terms_tidy' => '', '3.7' ),
158
+ array( 'get_blogaddress_by_domain' => '', '3.7' ),
159
+ // end wp-includes deprecated
160
+
161
+ // start wp-admin deprecated
162
+ array( 'tinymce_include' => 'wp_tiny_mce()', '2.1' ),
163
+ array( 'documentation_link' => '', '2.5' ),
164
+ array( 'wp_shrink_dimensions' => 'wp_constrain_dimensions()','3.0' ),
165
+ array( 'dropdown_categories' => 'wp_category_checklist()','2.6' ),
166
+ array( 'dropdown_link_categories' => 'wp_link_category_checklist()','2.6' ),
167
+ array( 'wp_dropdown_cats' => 'wp_dropdown_categories()','3.0' ),
168
+ array( 'add_option_update_handler' => 'register_setting()','3.0' ),
169
+ array( 'remove_option_update_handler' => 'unregister_setting()','3.0' ),
170
+ array( 'codepress_get_lang' => '','3.0' ),
171
+ array( 'codepress_footer_js' => '','3.0' ),
172
+ array( 'use_codepress' => '','3.0' ),
173
+ array( 'get_author_user_ids' => '','3.1' ),
174
+ array( 'get_editable_authors' => '','3.1' ),
175
+ array( 'get_editable_user_ids' => '','3.1' ),
176
+ array( 'get_nonauthor_user_ids' => '','3.1' ),
177
+ array( 'WP_User_Search' => 'WP_User_Query','3.1' ),
178
+ array( 'get_others_unpublished_posts' => '','3.1' ),
179
+ array( 'get_others_drafts' => '','3.1' ),
180
+ array( 'get_others_pending' => '', '3.1' ),
181
+ array( 'wp_dashboard_quick_press()' => '', '3.2' ),
182
+ array( 'wp_tiny_mce' => 'wp_editor', '3.2' ),
183
+ array( 'wp_preload_dialogs' => 'wp_editor()', '3.2' ),
184
+ array( 'wp_print_editor_js' => 'wp_editor()', '3.2' ),
185
+ array( 'wp_quicktags' => 'wp_editor()', '3.2' ),
186
+ array( 'favorite_actions' => 'WP_Admin_Bar', '3.2' ),
187
+ array( 'screen_layout' => '$current_screen->render_screen_layout()', '3.3' ),
188
+ array( 'screen_options' => '$current_screen->render_per_page_options()', '3.3' ),
189
+ array( 'screen_meta' => ' $current_screen->render_screen_meta()', '3.3' ),
190
+ array( 'media_upload_image' => 'wp_media_upload_handler()', '3.3' ),
191
+ array( 'media_upload_audio' => 'wp_media_upload_handler()', '3.3' ),
192
+ array( 'media_upload_video' => 'wp_media_upload_handler()', '3.3' ),
193
+ array( 'media_upload_file' => 'wp_media_upload_handler()', '3.3' ),
194
+ array( 'type_url_form_image' => 'wp_media_insert_url_form( \'image\' )', '3.3' ),
195
+ array( 'type_url_form_audio' => 'wp_media_insert_url_form( \'audio\' )', '3.3' ),
196
+ array( 'type_url_form_video' => 'wp_media_insert_url_form( \'video\' )', '3.3' ),
197
+ array( 'type_url_form_file' => 'wp_media_insert_url_form( \'file\' )', '3.3' ),
198
+ array( 'add_contextual_help' => 'get_current_screen()->add_help_tab()', '3.3' ),
199
+ array( 'get_allowed_themes' => 'wp_get_themes( array( \'allowed\' => true ) )', '3.4' ),
200
+ array( 'get_broken_themes' => 'wp_get_themes( array( \'errors\' => true )', '3.4' ),
201
+ array( 'current_theme_info' => 'wp_get_theme()', '3.4' ),
202
+ array( '_insert_into_post_button' => '', '3.5' ),
203
+ array( '_media_button' => '', '3.5' ),
204
+ array( 'get_post_to_edit' => 'get_post()', '3.5' ),
205
+ array( 'get_default_page_to_edit' => 'get_default_post_to_edit()', '3.5' ),
206
+ array( 'wp_create_thumbnail' => 'image_resize()', '3.5' ),
207
+ array( 'wp_nav_menu_locations_meta_box' => '', '3.6' ),
208
+ array( 'the_attachment_links' => '', '3.7'),
209
+ array( 'wp_update_core' => 'new Core_Upgrader()', '3.7'),
210
+ array( 'wp_update_plugin' => 'new Plugin_Upgrader()', '3.7'),
211
+ array( 'wp_update_theme' => 'new Theme_Upgrader()', '3.7'),
212
+ array( 'get_screen_icon' => '', '3.8',),
213
+ array( 'screen_icon' => '', '3.8' ),
214
+ array( 'wp_dashboard_incoming_links' => '', '3.8',),
215
+ array( 'wp_dashboard_incoming_links_control' => '', '3.8',),
216
+ array( 'wp_dashboard_incoming_links_output' => '', '3.8',),
217
+ array( 'wp_dashboard_plugins' => '', '3.8',),
218
+ array( 'wp_dashboard_primary_control' => '', '3.8',),
219
+ array( 'wp_dashboard_recent_comments_control' => '', '3.8',),
220
+ array( 'wp_dashboard_secondary' => '', '3.8',),
221
+ array( 'wp_dashboard_secondary_control' => '', '3.8',),
222
+ array( 'wp_dashboard_secondary_output' => '', '3.8',),
223
+ // end wp-admin
224
+ );
225
+ foreach ( $php_files as $php_key => $phpfile ) {
226
+ foreach ( $checks as $alt => $check ) {
227
+ checkcount();
228
+ $key = key( $check );
229
+ $alt = $check[ $key ];
230
+ if ( preg_match( '/[\s?]' . $key . '\(/', $phpfile, $matches ) ) {
231
+ $filename = tc_filename( $php_key );
232
+ $error = ltrim( rtrim( $matches[0], '(' ) );
233
+ $version = $check[0];
234
+ $grep = tc_grep( $error, $php_key );
235
+
236
+ // Point out the deprecated function.
237
+ $error_msg = sprintf(
238
+ __( '%1$s found in the file %2$s. Deprecated since version %3$s.', 'theme-check' ),
239
+ '<strong>' . $error . '()</strong>',
240
+ '<strong>' . $filename . '</strong>',
241
+ '<strong>' . $version . '</strong>'
242
+ );
243
+
244
+ // Add alternative function when available.
245
+ if ( $alt ) {
246
+ $error_msg .= ' ' . sprintf( __( 'Use %s instead.', 'theme-check' ), '<strong>' . $alt . '</strong>' );
247
+ }
248
+
249
+ // Add the precise code match that was found.
250
+ $error_msg .= $grep;
251
+
252
+ // Add the finalized error message.
253
+ $this->error[] = '<span class="tc-lead tc-required">' . __('REQUIRED','theme-check') . '</span>: ' . $error_msg;
254
+
255
+ $ret = false;
256
+ }
257
+ }
258
+ }
259
+ return $ret;
260
+ }
261
+
262
+ function getError() { return $this->error; }
263
+ }
264
+ $themechecks[] = new Deprecated;
checks/directories.php ADDED
@@ -0,0 +1,36 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class DirectoriesCheck implements themecheck {
4
+ protected $error = array();
5
+
6
+ function check( $php_files, $css_files, $other_files ) {
7
+
8
+ $ret = true;
9
+ $found = false;
10
+
11
+ foreach ( $php_files as $name => $file ) {
12
+ checkcount();
13
+ if ( strpos( $name, '.git' ) !== false || strpos( $name, '.svn' ) !== false ) $found = true;
14
+ }
15
+
16
+ foreach ( $css_files as $name => $file ) {
17
+ checkcount();
18
+ if ( strpos( $name, '.git' ) !== false || strpos( $name, '.svn' ) !== false || strpos( $name, '.hg' ) !== false || strpos( $name, '.bzr' ) !== false ) $found = true;
19
+ }
20
+
21
+ foreach ( $other_files as $name => $file ) {
22
+ checkcount();
23
+ if ( strpos( $name, '.git' ) !== false || strpos( $name, '.svn' ) !== false || strpos( $name, '.hg' ) !== false || strpos( $name, '.bzr' ) !== false ) $found = true;
24
+ }
25
+
26
+ if ($found) {
27
+ $this->error[] = sprintf('<span class="tc-lead tc-required">' . __( 'REQUIRED', 'theme-check' ) . '</span>: ' . __( 'Please remove any extraneous directories like .git or .svn from the ZIP file before uploading it.', 'theme-check') );
28
+ $ret = false;
29
+ }
30
+
31
+ return $ret;
32
+ }
33
+
34
+ function getError() { return $this->error; }
35
+ }
36
+ $themechecks[] = new DirectoriesCheck;
checks/editorstyle.php ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class EditorStyleCheck implements themecheck {
4
+ protected $error = array();
5
+
6
+ function check( $php_files, $css_files, $other_files ) {
7
+ checkcount();
8
+ $ret = true;
9
+
10
+ $php = implode( ' ', $php_files );
11
+
12
+ if ( strpos( $php, 'add_editor_style' ) === false ) {
13
+ $this->error[] = '<span class="tc-lead tc-recommended">'.__('RECOMMENDED','theme-check').'</span>: '.__('No reference to <strong>add_editor_style()</strong> was found in the theme. It is recommended that the theme implement editor styling, so as to make the editor content match the resulting post output in the theme, for a better user experience.', 'theme-check' );
14
+ }
15
+
16
+ return $ret;
17
+ }
18
+
19
+ function getError() { return $this->error; }
20
+ }
21
+ $themechecks[] = new EditorStyleCheck;
checks/filenames.php ADDED
@@ -0,0 +1,66 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ class File_Checks implements themecheck {
3
+ protected $error = array();
4
+
5
+ function check( $php_files, $css_files, $other_files ) {
6
+
7
+ $ret = true;
8
+
9
+ $filenames = array();
10
+
11
+ foreach ( $php_files as $php_key => $phpfile ) {
12
+ array_push( $filenames, strtolower( basename( $php_key ) ) );
13
+ }
14
+ foreach ( $other_files as $php_key => $phpfile ) {
15
+ array_push( $filenames, strtolower( basename( $php_key ) ) );
16
+ }
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
+ );
34
+
35
+ $musthave = array( 'index.php', 'comments.php', 'style.css' );
36
+ $rechave = array( 'readme.txt' => __( 'Please see <a href="http://codex.wordpress.org/Theme_Review#Theme_Documentation">Theme_Documentation</a> for more information.', 'theme-check' ) );
37
+
38
+ checkcount();
39
+
40
+ foreach( $blacklist as $file => $reason ) {
41
+ if ( $filename = preg_grep( '/' . $file . '/', $filenames ) ) {
42
+ $error = implode( array_unique( $filename ), ' ' );
43
+ $this->error[] = sprintf('<span class="tc-lead tc-warning">'.__('WARNING','theme-check').'</span>: '.__('<strong>%1$s</strong> %2$s found.', 'theme-check'), $error, $reason) ;
44
+ $ret = false;
45
+ }
46
+ }
47
+
48
+ foreach( $musthave as $file ) {
49
+ if ( !in_array( $file, $filenames ) ) {
50
+ $this->error[] = sprintf('<span class="tc-lead tc-warning">'.__('WARNING','theme-check').'</span>: '.__('could not find the file <strong>%1$s</strong> in the theme.', 'theme-check'), $file);
51
+ $ret = false;
52
+ }
53
+ }
54
+
55
+ foreach( $rechave as $file => $reason ) {
56
+ if ( !in_array( $file, $filenames ) ) {
57
+ $this->error[] = sprintf('<span class="tc-lead tc-recommended">'.__('RECOMMENDED','theme-check').'</span>: '.__('could not find the file <strong>%1$s</strong> in the theme. %2$s', 'theme-check'), $file, $reason );
58
+ }
59
+ }
60
+
61
+ return $ret;
62
+ }
63
+
64
+ function getError() { return $this->error; }
65
+ }
66
+ $themechecks[] = new File_Checks;
checks/gravatar.php ADDED
@@ -0,0 +1,24 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class GravatarCheck implements themecheck {
4
+ protected $error = array();
5
+
6
+ function check( $php_files, $css_files, $other_files ) {
7
+
8
+ $php = implode( ' ', $php_files );
9
+
10
+ checkcount();
11
+
12
+ $ret = true;
13
+
14
+ if ( ( strpos( $php, 'get_avatar' ) === false ) && ( strpos( $php, 'wp_list_comments' ) === false ) ) {
15
+ $this->error[] = '<span class="tc-lead tc-required">'.__('REQUIRED','theme-check').'</span>: '.__("This theme doesn't seem to support the standard avatar functions. Use <strong>get_avatar</strong> or <strong>wp_list_comments</strong> to add this support.", 'theme-check' );
16
+ $ret = false;
17
+ }
18
+
19
+ return $ret;
20
+ }
21
+
22
+ function getError() { return $this->error; }
23
+ }
24
+ $themechecks[] = new GravatarCheck;
checks/i18n.php ADDED
@@ -0,0 +1,64 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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 = ( !strpos( $error, $line[0] ) ) ? $grep : '';
49
+ $this->error[] = sprintf('<span class="tc-lead tc-recommended">'.__('RECOMMENDED','theme-check').'</span>: '.__('Possible variable <strong>%1$s</strong> found in translation function in <strong>%2$s</strong>. Translation function calls must NOT contain PHP variables. %3$s','theme-check'),
50
+ $token[1], $filename, $error);
51
+ break; // stop looking at the tokens on this line once a variable is found
52
+ }
53
+ }
54
+ }
55
+ }
56
+
57
+
58
+ }
59
+ return $ret;
60
+ }
61
+
62
+ function getError() { return $this->error; }
63
+ }
64
+ $themechecks[] = new I18NCheck;
checks/iframes.php ADDED
@@ -0,0 +1,29 @@