|
1 <?php |
|
2 /** |
|
3 * Theme, template, and stylesheet functions. |
|
4 * |
|
5 * @package WordPress |
|
6 * @subpackage Template |
|
7 */ |
|
8 |
|
9 /** |
|
10 * Retrieve name of the current stylesheet. |
|
11 * |
|
12 * The theme name that the administrator has currently set the front end theme |
|
13 * as. |
|
14 * |
|
15 * For all extensive purposes, the template name and the stylesheet name are |
|
16 * going to be the same for most cases. |
|
17 * |
|
18 * @since 1.5.0 |
|
19 * @uses apply_filters() Calls 'stylesheet' filter on stylesheet name. |
|
20 * |
|
21 * @return string Stylesheet name. |
|
22 */ |
|
23 function get_stylesheet() { |
|
24 return apply_filters('stylesheet', get_option('stylesheet')); |
|
25 } |
|
26 |
|
27 /** |
|
28 * Retrieve stylesheet directory path for current theme. |
|
29 * |
|
30 * @since 1.5.0 |
|
31 * @uses apply_filters() Calls 'stylesheet_directory' filter on stylesheet directory and theme name. |
|
32 * |
|
33 * @return string Path to current theme directory. |
|
34 */ |
|
35 function get_stylesheet_directory() { |
|
36 $stylesheet = get_stylesheet(); |
|
37 $stylesheet_dir = get_theme_root() . "/$stylesheet"; |
|
38 return apply_filters('stylesheet_directory', $stylesheet_dir, $stylesheet); |
|
39 } |
|
40 |
|
41 /** |
|
42 * Retrieve stylesheet directory URI. |
|
43 * |
|
44 * @since 1.5.0 |
|
45 * |
|
46 * @return string |
|
47 */ |
|
48 function get_stylesheet_directory_uri() { |
|
49 $stylesheet = get_stylesheet(); |
|
50 $stylesheet_dir_uri = get_theme_root_uri() . "/$stylesheet"; |
|
51 return apply_filters('stylesheet_directory_uri', $stylesheet_dir_uri, $stylesheet); |
|
52 } |
|
53 |
|
54 /** |
|
55 * Retrieve URI of current theme stylesheet. |
|
56 * |
|
57 * The stylesheet file name is 'style.css' which is appended to {@link |
|
58 * get_stylesheet_directory_uri() stylesheet directory URI} path. |
|
59 * |
|
60 * @since 1.5.0 |
|
61 * @uses apply_filters() Calls 'stylesheet_uri' filter on stylesheet URI path and stylesheet directory URI. |
|
62 * |
|
63 * @return string |
|
64 */ |
|
65 function get_stylesheet_uri() { |
|
66 $stylesheet_dir_uri = get_stylesheet_directory_uri(); |
|
67 $stylesheet_uri = $stylesheet_dir_uri . "/style.css"; |
|
68 return apply_filters('stylesheet_uri', $stylesheet_uri, $stylesheet_dir_uri); |
|
69 } |
|
70 |
|
71 /** |
|
72 * Retrieve localized stylesheet URI. |
|
73 * |
|
74 * The stylesheet directory for the localized stylesheet files are located, by |
|
75 * default, in the base theme directory. The name of the locale file will be the |
|
76 * locale followed by '.css'. If that does not exist, then the text direction |
|
77 * stylesheet will be checked for existence, for example 'ltr.css'. |
|
78 * |
|
79 * The theme may change the location of the stylesheet directory by either using |
|
80 * the 'stylesheet_directory_uri' filter or the 'locale_stylesheet_uri' filter. |
|
81 * If you want to change the location of the stylesheet files for the entire |
|
82 * WordPress workflow, then change the former. If you just have the locale in a |
|
83 * separate folder, then change the latter. |
|
84 * |
|
85 * @since 2.1.0 |
|
86 * @uses apply_filters() Calls 'locale_stylesheet_uri' filter on stylesheet URI path and stylesheet directory URI. |
|
87 * |
|
88 * @return string |
|
89 */ |
|
90 function get_locale_stylesheet_uri() { |
|
91 global $wp_locale; |
|
92 $stylesheet_dir_uri = get_stylesheet_directory_uri(); |
|
93 $dir = get_stylesheet_directory(); |
|
94 $locale = get_locale(); |
|
95 if ( file_exists("$dir/$locale.css") ) |
|
96 $stylesheet_uri = "$stylesheet_dir_uri/$locale.css"; |
|
97 elseif ( !empty($wp_locale->text_direction) && file_exists("$dir/{$wp_locale->text_direction}.css") ) |
|
98 $stylesheet_uri = "$stylesheet_dir_uri/{$wp_locale->text_direction}.css"; |
|
99 else |
|
100 $stylesheet_uri = ''; |
|
101 return apply_filters('locale_stylesheet_uri', $stylesheet_uri, $stylesheet_dir_uri); |
|
102 } |
|
103 |
|
104 /** |
|
105 * Retrieve name of the current theme. |
|
106 * |
|
107 * @since 1.5.0 |
|
108 * @uses apply_filters() Calls 'template' filter on template option. |
|
109 * |
|
110 * @return string Template name. |
|
111 */ |
|
112 function get_template() { |
|
113 return apply_filters('template', get_option('template')); |
|
114 } |
|
115 |
|
116 /** |
|
117 * Retrieve current theme directory. |
|
118 * |
|
119 * @since 1.5.0 |
|
120 * @uses apply_filters() Calls 'template_directory' filter on template directory path and template name. |
|
121 * |
|
122 * @return string Template directory path. |
|
123 */ |
|
124 function get_template_directory() { |
|
125 $template = get_template(); |
|
126 $template_dir = get_theme_root() . "/$template"; |
|
127 return apply_filters('template_directory', $template_dir, $template); |
|
128 } |
|
129 |
|
130 /** |
|
131 * Retrieve theme directory URI. |
|
132 * |
|
133 * @since 1.5.0 |
|
134 * @uses apply_filters() Calls 'template_directory_uri' filter on template directory URI path and template name. |
|
135 * |
|
136 * @return string Template directory URI. |
|
137 */ |
|
138 function get_template_directory_uri() { |
|
139 $template = get_template(); |
|
140 $template_dir_uri = get_theme_root_uri() . "/$template"; |
|
141 return apply_filters('template_directory_uri', $template_dir_uri, $template); |
|
142 } |
|
143 |
|
144 /** |
|
145 * Retrieve theme data from parsed theme file. |
|
146 * |
|
147 * The description will have the tags filtered with the following HTML elements |
|
148 * whitelisted. The <b>'a'</b> element with the <em>href</em> and <em>title</em> |
|
149 * attributes. The <b>abbr</b> element with the <em>title</em> attribute. The |
|
150 * <b>acronym<b> element with the <em>title</em> attribute allowed. The |
|
151 * <b>code</b>, <b>em</b>, and <b>strong</b> elements also allowed. |
|
152 * |
|
153 * The style.css file must contain theme name, theme URI, and description. The |
|
154 * data can also contain author URI, author, template (parent template), |
|
155 * version, status, and finally tags. Some of these are not used by WordPress |
|
156 * administration panels, but are used by theme directory web sites which list |
|
157 * the theme. |
|
158 * |
|
159 * @since 1.5.0 |
|
160 * |
|
161 * @param string $theme_file Theme file path. |
|
162 * @return array Theme data. |
|
163 */ |
|
164 function get_theme_data( $theme_file ) { |
|
165 $themes_allowed_tags = array( |
|
166 'a' => array( |
|
167 'href' => array(),'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 = implode( '', file( $theme_file ) ); |
|
181 $theme_data = str_replace ( '\r', '\n', $theme_data ); |
|
182 if ( preg_match( '|Theme Name:(.*)$|mi', $theme_data, $theme_name ) ) |
|
183 $name = $theme = wp_kses( _cleanup_header_comment($theme_name[1]), $themes_allowed_tags ); |
|
184 else |
|
185 $name = $theme = ''; |
|
186 |
|
187 if ( preg_match( '|Theme URI:(.*)$|mi', $theme_data, $theme_uri ) ) |
|
188 $theme_uri = esc_url( _cleanup_header_comment($theme_uri[1]) ); |
|
189 else |
|
190 $theme_uri = ''; |
|
191 |
|
192 if ( preg_match( '|Description:(.*)$|mi', $theme_data, $description ) ) |
|
193 $description = wptexturize( wp_kses( _cleanup_header_comment($description[1]), $themes_allowed_tags ) ); |
|
194 else |
|
195 $description = ''; |
|
196 |
|
197 if ( preg_match( '|Author URI:(.*)$|mi', $theme_data, $author_uri ) ) |
|
198 $author_uri = esc_url( _cleanup_header_comment($author_uri[1]) ); |
|
199 else |
|
200 $author_uri = ''; |
|
201 |
|
202 if ( preg_match( '|Template:(.*)$|mi', $theme_data, $template ) ) |
|
203 $template = wp_kses( _cleanup_header_comment($template[1]), $themes_allowed_tags ); |
|
204 else |
|
205 $template = ''; |
|
206 |
|
207 if ( preg_match( '|Version:(.*)|i', $theme_data, $version ) ) |
|
208 $version = wp_kses( _cleanup_header_comment($version[1]), $themes_allowed_tags ); |
|
209 else |
|
210 $version = ''; |
|
211 |
|
212 if ( preg_match('|Status:(.*)|i', $theme_data, $status) ) |
|
213 $status = wp_kses( _cleanup_header_comment($status[1]), $themes_allowed_tags ); |
|
214 else |
|
215 $status = 'publish'; |
|
216 |
|
217 if ( preg_match('|Tags:(.*)|i', $theme_data, $tags) ) |
|
218 $tags = array_map( 'trim', explode( ',', wp_kses( _cleanup_header_comment($tags[1]), array() ) ) ); |
|
219 else |
|
220 $tags = array(); |
|
221 |
|
222 if ( preg_match( '|Author:(.*)$|mi', $theme_data, $author_name ) ) { |
|
223 if ( empty( $author_uri ) ) { |
|
224 $author = wp_kses( _cleanup_header_comment($author_name[1]), $themes_allowed_tags ); |
|
225 } else { |
|
226 $author = sprintf( '<a href="%1$s" title="%2$s">%3$s</a>', $author_uri, __( 'Visit author homepage' ), wp_kses( _cleanup_header_comment($author_name[1]), $themes_allowed_tags ) ); |
|
227 } |
|
228 } else { |
|
229 $author = __('Anonymous'); |
|
230 } |
|
231 |
|
232 return array( 'Name' => $name, 'Title' => $theme, 'URI' => $theme_uri, 'Description' => $description, 'Author' => $author, 'Version' => $version, 'Template' => $template, 'Status' => $status, 'Tags' => $tags ); |
|
233 } |
|
234 |
|
235 /** |
|
236 * Retrieve list of themes with theme data in theme directory. |
|
237 * |
|
238 * The theme is broken, if it doesn't have a parent theme and is missing either |
|
239 * style.css and, or index.php. If the theme has a parent theme then it is |
|
240 * broken, if it is missing style.css; index.php is optional. The broken theme |
|
241 * list is saved in the {@link $wp_broken_themes} global, which is displayed on |
|
242 * the theme list in the administration panels. |
|
243 * |
|
244 * @since 1.5.0 |
|
245 * @global array $wp_broken_themes Stores the broken themes. |
|
246 * @global array $wp_themes Stores the working themes. |
|
247 * |
|
248 * @return array Theme list with theme data. |
|
249 */ |
|
250 function get_themes() { |
|
251 global $wp_themes, $wp_broken_themes; |
|
252 |
|
253 if ( isset($wp_themes) ) |
|
254 return $wp_themes; |
|
255 |
|
256 $themes = array(); |
|
257 $wp_broken_themes = array(); |
|
258 $theme_loc = $theme_root = get_theme_root(); |
|
259 if ( '/' != WP_CONTENT_DIR ) // don't want to replace all forward slashes, see Trac #4541 |
|
260 $theme_loc = str_replace(WP_CONTENT_DIR, '', $theme_root); |
|
261 |
|
262 // Files in wp-content/themes directory and one subdir down |
|
263 $themes_dir = @ opendir($theme_root); |
|
264 if ( !$themes_dir ) |
|
265 return false; |
|
266 |
|
267 while ( ($theme_dir = readdir($themes_dir)) !== false ) { |
|
268 if ( is_dir($theme_root . '/' . $theme_dir) && is_readable($theme_root . '/' . $theme_dir) ) { |
|
269 if ( $theme_dir{0} == '.' || $theme_dir == '..' || $theme_dir == 'CVS' ) |
|
270 continue; |
|
271 $stylish_dir = @ opendir($theme_root . '/' . $theme_dir); |
|
272 $found_stylesheet = false; |
|
273 while ( ($theme_file = readdir($stylish_dir)) !== false ) { |
|
274 if ( $theme_file == 'style.css' ) { |
|
275 $theme_files[] = $theme_dir . '/' . $theme_file; |
|
276 $found_stylesheet = true; |
|
277 break; |
|
278 } |
|
279 } |
|
280 @closedir($stylish_dir); |
|
281 if ( !$found_stylesheet ) { // look for themes in that dir |
|
282 $subdir = "$theme_root/$theme_dir"; |
|
283 $subdir_name = $theme_dir; |
|
284 $theme_subdir = @ opendir( $subdir ); |
|
285 while ( ($theme_dir = readdir($theme_subdir)) !== false ) { |
|
286 if ( is_dir( $subdir . '/' . $theme_dir) && is_readable($subdir . '/' . $theme_dir) ) { |
|
287 if ( $theme_dir{0} == '.' || $theme_dir == '..' || $theme_dir == 'CVS' ) |
|
288 continue; |
|
289 $stylish_dir = @ opendir($subdir . '/' . $theme_dir); |
|
290 $found_stylesheet = false; |
|
291 while ( ($theme_file = readdir($stylish_dir)) !== false ) { |
|
292 if ( $theme_file == 'style.css' ) { |
|
293 $theme_files[] = $subdir_name . '/' . $theme_dir . '/' . $theme_file; |
|
294 $found_stylesheet = true; |
|
295 break; |
|
296 } |
|
297 } |
|
298 @closedir($stylish_dir); |
|
299 } |
|
300 } |
|
301 @closedir($theme_subdir); |
|
302 $wp_broken_themes[$theme_dir] = array('Name' => $theme_dir, 'Title' => $theme_dir, 'Description' => __('Stylesheet is missing.')); |
|
303 } |
|
304 } |
|
305 } |
|
306 if ( is_dir( $theme_dir ) ) |
|
307 @closedir( $theme_dir ); |
|
308 |
|
309 if ( !$themes_dir || !$theme_files ) |
|
310 return $themes; |
|
311 |
|
312 sort($theme_files); |
|
313 |
|
314 foreach ( (array) $theme_files as $theme_file ) { |
|
315 if ( !is_readable("$theme_root/$theme_file") ) { |
|
316 $wp_broken_themes[$theme_file] = array('Name' => $theme_file, 'Title' => $theme_file, 'Description' => __('File not readable.')); |
|
317 continue; |
|
318 } |
|
319 |
|
320 $theme_data = get_theme_data("$theme_root/$theme_file"); |
|
321 |
|
322 $name = $theme_data['Name']; |
|
323 $title = $theme_data['Title']; |
|
324 $description = wptexturize($theme_data['Description']); |
|
325 $version = $theme_data['Version']; |
|
326 $author = $theme_data['Author']; |
|
327 $template = $theme_data['Template']; |
|
328 $stylesheet = dirname($theme_file); |
|
329 |
|
330 $screenshot = false; |
|
331 foreach ( array('png', 'gif', 'jpg', 'jpeg') as $ext ) { |
|
332 if (file_exists("$theme_root/$stylesheet/screenshot.$ext")) { |
|
333 $screenshot = "screenshot.$ext"; |
|
334 break; |
|
335 } |
|
336 } |
|
337 |
|
338 if ( empty($name) ) { |
|
339 $name = dirname($theme_file); |
|
340 $title = $name; |
|
341 } |
|
342 |
|
343 if ( empty($template) ) { |
|
344 if ( file_exists(dirname("$theme_root/$theme_file/index.php")) ) |
|
345 $template = dirname($theme_file); |
|
346 else |
|
347 continue; |
|
348 } |
|
349 |
|
350 $template = trim($template); |
|
351 |
|
352 if ( !file_exists("$theme_root/$template/index.php") ) { |
|
353 $parent_dir = dirname(dirname($theme_file)); |
|
354 if ( file_exists("$theme_root/$parent_dir/$template/index.php") ) { |
|
355 $template = "$parent_dir/$template"; |
|
356 } else { |
|
357 $wp_broken_themes[$name] = array('Name' => $name, 'Title' => $title, 'Description' => __('Template is missing.')); |
|
358 continue; |
|
359 } |
|
360 } |
|
361 |
|
362 $stylesheet_files = array(); |
|
363 $template_files = array(); |
|
364 |
|
365 $stylesheet_dir = @ dir("$theme_root/$stylesheet"); |
|
366 if ( $stylesheet_dir ) { |
|
367 while ( ($file = $stylesheet_dir->read()) !== false ) { |
|
368 if ( !preg_match('|^\.+$|', $file) ) { |
|
369 if ( preg_match('|\.css$|', $file) ) |
|
370 $stylesheet_files[] = "$theme_loc/$stylesheet/$file"; |
|
371 elseif ( preg_match('|\.php$|', $file) ) |
|
372 $template_files[] = "$theme_loc/$stylesheet/$file"; |
|
373 } |
|
374 } |
|
375 @ $stylesheet_dir->close(); |
|
376 } |
|
377 |
|
378 $template_dir = @ dir("$theme_root/$template"); |
|
379 if ( $template_dir ) { |
|
380 while ( ($file = $template_dir->read()) !== false ) { |
|
381 if ( preg_match('|^\.+$|', $file) ) |
|
382 continue; |
|
383 if ( preg_match('|\.php$|', $file) ) { |
|
384 $template_files[] = "$theme_loc/$template/$file"; |
|
385 } elseif ( is_dir("$theme_root/$template/$file") ) { |
|
386 $template_subdir = @ dir("$theme_root/$template/$file"); |
|
387 while ( ($subfile = $template_subdir->read()) !== false ) { |
|
388 if ( preg_match('|^\.+$|', $subfile) ) |
|
389 continue; |
|
390 if ( preg_match('|\.php$|', $subfile) ) |
|
391 $template_files[] = "$theme_loc/$template/$file/$subfile"; |
|
392 } |
|
393 @ $template_subdir->close(); |
|
394 } |
|
395 } |
|
396 @ $template_dir->close(); |
|
397 } |
|
398 |
|
399 $template_dir = dirname($template_files[0]); |
|
400 $stylesheet_dir = dirname($stylesheet_files[0]); |
|
401 |
|
402 if ( empty($template_dir) ) |
|
403 $template_dir = '/'; |
|
404 if ( empty($stylesheet_dir) ) |
|
405 $stylesheet_dir = '/'; |
|
406 |
|
407 // Check for theme name collision. This occurs if a theme is copied to |
|
408 // a new theme directory and the theme header is not updated. Whichever |
|
409 // theme is first keeps the name. Subsequent themes get a suffix applied. |
|
410 // The Default and Classic themes always trump their pretenders. |
|
411 if ( isset($themes[$name]) ) { |
|
412 if ( ('WordPress Default' == $name || 'WordPress Classic' == $name) && |
|
413 ('default' == $stylesheet || 'classic' == $stylesheet) ) { |
|
414 // If another theme has claimed to be one of our default themes, move |
|
415 // them aside. |
|
416 $suffix = $themes[$name]['Stylesheet']; |
|
417 $new_name = "$name/$suffix"; |
|
418 $themes[$new_name] = $themes[$name]; |
|
419 $themes[$new_name]['Name'] = $new_name; |
|
420 } else { |
|
421 $name = "$name/$stylesheet"; |
|
422 } |
|
423 } |
|
424 |
|
425 $themes[$name] = array('Name' => $name, 'Title' => $title, 'Description' => $description, 'Author' => $author, 'Version' => $version, 'Template' => $template, 'Stylesheet' => $stylesheet, 'Template Files' => $template_files, 'Stylesheet Files' => $stylesheet_files, 'Template Dir' => $template_dir, 'Stylesheet Dir' => $stylesheet_dir, 'Status' => $theme_data['Status'], 'Screenshot' => $screenshot, 'Tags' => $theme_data['Tags']); |
|
426 } |
|
427 |
|
428 // Resolve theme dependencies. |
|
429 $theme_names = array_keys($themes); |
|
430 |
|
431 foreach ( (array) $theme_names as $theme_name ) { |
|
432 $themes[$theme_name]['Parent Theme'] = ''; |
|
433 if ( $themes[$theme_name]['Stylesheet'] != $themes[$theme_name]['Template'] ) { |
|
434 foreach ( (array) $theme_names as $parent_theme_name ) { |
|
435 if ( ($themes[$parent_theme_name]['Stylesheet'] == $themes[$parent_theme_name]['Template']) && ($themes[$parent_theme_name]['Template'] == $themes[$theme_name]['Template']) ) { |
|
436 $themes[$theme_name]['Parent Theme'] = $themes[$parent_theme_name]['Name']; |
|
437 break; |
|
438 } |
|
439 } |
|
440 } |
|
441 } |
|
442 |
|
443 $wp_themes = $themes; |
|
444 |
|
445 return $themes; |
|
446 } |
|
447 |
|
448 /** |
|
449 * Retrieve theme data. |
|
450 * |
|
451 * @since 1.5.0 |
|
452 * |
|
453 * @param string $theme Theme name. |
|
454 * @return array|null Null, if theme name does not exist. Theme data, if exists. |
|
455 */ |
|
456 function get_theme($theme) { |
|
457 $themes = get_themes(); |
|
458 |
|
459 if ( array_key_exists($theme, $themes) ) |
|
460 return $themes[$theme]; |
|
461 |
|
462 return null; |
|
463 } |
|
464 |
|
465 /** |
|
466 * Retrieve current theme display name. |
|
467 * |
|
468 * If the 'current_theme' option has already been set, then it will be returned |
|
469 * instead. If it is not set, then each theme will be iterated over until both |
|
470 * the current stylesheet and current template name. |
|
471 * |
|
472 * @since 1.5.0 |
|
473 * |
|
474 * @return string |
|
475 */ |
|
476 function get_current_theme() { |
|
477 if ( $theme = get_option('current_theme') ) |
|
478 return $theme; |
|
479 |
|
480 $themes = get_themes(); |
|
481 $theme_names = array_keys($themes); |
|
482 $current_template = get_option('template'); |
|
483 $current_stylesheet = get_option('stylesheet'); |
|
484 $current_theme = 'WordPress Default'; |
|
485 |
|
486 if ( $themes ) { |
|
487 foreach ( (array) $theme_names as $theme_name ) { |
|
488 if ( $themes[$theme_name]['Stylesheet'] == $current_stylesheet && |
|
489 $themes[$theme_name]['Template'] == $current_template ) { |
|
490 $current_theme = $themes[$theme_name]['Name']; |
|
491 break; |
|
492 } |
|
493 } |
|
494 } |
|
495 |
|
496 update_option('current_theme', $current_theme); |
|
497 |
|
498 return $current_theme; |
|
499 } |
|
500 |
|
501 /** |
|
502 * Retrieve path to themes directory. |
|
503 * |
|
504 * Does not have trailing slash. |
|
505 * |
|
506 * @since 1.5.0 |
|
507 * @uses apply_filters() Calls 'theme_root' filter on path. |
|
508 * |
|
509 * @return string Theme path. |
|
510 */ |
|
511 function get_theme_root() { |
|
512 return apply_filters('theme_root', WP_CONTENT_DIR . "/themes"); |
|
513 } |
|
514 |
|
515 /** |
|
516 * Retrieve URI for themes directory. |
|
517 * |
|
518 * Does not have trailing slash. |
|
519 * |
|
520 * @since 1.5.0 |
|
521 * |
|
522 * @return string Themes URI. |
|
523 */ |
|
524 function get_theme_root_uri() { |
|
525 return apply_filters('theme_root_uri', content_url('themes'), get_option('siteurl')); |
|
526 } |
|
527 |
|
528 /** |
|
529 * Retrieve path to file without the use of extension. |
|
530 * |
|
531 * Used to quickly retrieve the path of file without including the file |
|
532 * extension. It will also check the parent template, if the file exists, with |
|
533 * the use of {@link locate_template()}. Allows for more generic file location |
|
534 * without the use of the other get_*_template() functions. |
|
535 * |
|
536 * Can be used with include() or require() to retrieve path. |
|
537 * <code> |
|
538 * if( '' != get_query_template( '404' ) ) |
|
539 * include( get_query_template( '404' ) ); |
|
540 * </code> |
|
541 * or the same can be accomplished with |
|
542 * <code> |
|
543 * if( '' != get_404_template() ) |
|
544 * include( get_404_template() ); |
|
545 * </code> |
|
546 * |
|
547 * @since 1.5.0 |
|
548 * |
|
549 * @param string $type Filename without extension. |
|
550 * @return string Full path to file. |
|
551 */ |
|
552 function get_query_template($type) { |
|
553 $type = preg_replace( '|[^a-z0-9-]+|', '', $type ); |
|
554 return apply_filters("{$type}_template", locate_template(array("{$type}.php"))); |
|
555 } |
|
556 |
|
557 /** |
|
558 * Retrieve path of 404 template in current or parent template. |
|
559 * |
|
560 * @since 1.5.0 |
|
561 * |
|
562 * @return string |
|
563 */ |
|
564 function get_404_template() { |
|
565 return get_query_template('404'); |
|
566 } |
|
567 |
|
568 /** |
|
569 * Retrieve path of archive template in current or parent template. |
|
570 * |
|
571 * @since 1.5.0 |
|
572 * |
|
573 * @return string |
|
574 */ |
|
575 function get_archive_template() { |
|
576 return get_query_template('archive'); |
|
577 } |
|
578 |
|
579 /** |
|
580 * Retrieve path of author template in current or parent template. |
|
581 * |
|
582 * @since 1.5.0 |
|
583 * |
|
584 * @return string |
|
585 */ |
|
586 function get_author_template() { |
|
587 return get_query_template('author'); |
|
588 } |
|
589 |
|
590 /** |
|
591 * Retrieve path of category template in current or parent template. |
|
592 * |
|
593 * Works by retrieving the current category ID, for example 'category-1.php' and |
|
594 * will fallback to category.php template, if the ID category file doesn't |
|
595 * exist. |
|
596 * |
|
597 * @since 1.5.0 |
|
598 * @uses apply_filters() Calls 'category_template' on file path of category template. |
|
599 * |
|
600 * @return string |
|
601 */ |
|
602 function get_category_template() { |
|
603 $template = locate_template(array("category-" . absint( get_query_var('cat') ) . '.php', 'category.php')); |
|
604 return apply_filters('category_template', $template); |
|
605 } |
|
606 |
|
607 /** |
|
608 * Retrieve path of tag template in current or parent template. |
|
609 * |
|
610 * Works by retrieving the current tag name, for example 'tag-wordpress.php' and will |
|
611 * fallback to tag.php template, if the name tag file doesn't exist. |
|
612 * |
|
613 * @since 2.3.0 |
|
614 * @uses apply_filters() Calls 'tag_template' on file path of tag template. |
|
615 * |
|
616 * @return string |
|
617 */ |
|
618 function get_tag_template() { |
|
619 $template = locate_template(array("tag-" . get_query_var('tag') . '.php', 'tag.php')); |
|
620 return apply_filters('tag_template', $template); |
|
621 } |
|
622 |
|
623 /** |
|
624 * Retrieve path of taxonomy template in current or parent template. |
|
625 * |
|
626 * Retrieves the taxonomy and term, if term is available. The template is |
|
627 * prepended with 'taxonomy-' and followed by both the taxonomy string and |
|
628 * the taxonomy string followed by a dash and then followed by the term. |
|
629 * |
|
630 * The taxonomy and term template is checked and used first, if it exists. |
|
631 * Second, just the taxonomy template is checked, and then finally, taxonomy.php |
|
632 * template is used. If none of the files exist, then it will fall back on to |
|
633 * index.php. |
|
634 * |
|
635 * @since unknown (2.6.0 most likely) |
|
636 * @uses apply_filters() Calls 'taxonomy_template' filter on found path. |
|
637 * |
|
638 * @return string |
|
639 */ |
|
640 function get_taxonomy_template() { |
|
641 $taxonomy = get_query_var('taxonomy'); |
|
642 $term = get_query_var('term'); |
|
643 |
|
644 $templates = array(); |
|
645 if ( $taxonomy && $term ) |
|
646 $templates[] = "taxonomy-$taxonomy-$term.php"; |
|
647 if ( $taxonomy ) |
|
648 $templates[] = "taxonomy-$taxonomy.php"; |
|
649 |
|
650 $templates[] = "taxonomy.php"; |
|
651 |
|
652 $template = locate_template($templates); |
|
653 return apply_filters('taxonomy_template', $template); |
|
654 } |
|
655 |
|
656 /** |
|
657 * Retrieve path of date template in current or parent template. |
|
658 * |
|
659 * @since 1.5.0 |
|
660 * |
|
661 * @return string |
|
662 */ |
|
663 function get_date_template() { |
|
664 return get_query_template('date'); |
|
665 } |
|
666 |
|
667 /** |
|
668 * Retrieve path of home template in current or parent template. |
|
669 * |
|
670 * Attempts to locate 'home.php' first before falling back to 'index.php'. |
|
671 * |
|
672 * @since 1.5.0 |
|
673 * @uses apply_filters() Calls 'home_template' on file path of home template. |
|
674 * |
|
675 * @return string |
|
676 */ |
|
677 function get_home_template() { |
|
678 $template = locate_template(array('home.php', 'index.php')); |
|
679 return apply_filters('home_template', $template); |
|
680 } |
|
681 |
|
682 /** |
|
683 * Retrieve path of page template in current or parent template. |
|
684 * |
|
685 * First attempt is to look for the file in the '_wp_page_template' page meta |
|
686 * data. The second attempt, if the first has a file and is not empty, is to |
|
687 * look for 'page.php'. |
|
688 * |
|
689 * @since 1.5.0 |
|
690 * |
|
691 * @return string |
|
692 */ |
|
693 function get_page_template() { |
|
694 global $wp_query; |
|
695 |
|
696 $id = (int) $wp_query->post->ID; |
|
697 $template = get_post_meta($id, '_wp_page_template', true); |
|
698 |
|
699 if ( 'default' == $template ) |
|
700 $template = ''; |
|
701 |
|
702 $templates = array(); |
|
703 if ( !empty($template) && !validate_file($template) ) |
|
704 $templates[] = $template; |
|
705 |
|
706 $templates[] = "page.php"; |
|
707 |
|
708 return apply_filters('page_template', locate_template($templates)); |
|
709 } |
|
710 |
|
711 /** |
|
712 * Retrieve path of paged template in current or parent template. |
|
713 * |
|
714 * @since 1.5.0 |
|
715 * |
|
716 * @return string |
|
717 */ |
|
718 function get_paged_template() { |
|
719 return get_query_template('paged'); |
|
720 } |
|
721 |
|
722 /** |
|
723 * Retrieve path of search template in current or parent template. |
|
724 * |
|
725 * @since 1.5.0 |
|
726 * |
|
727 * @return string |
|
728 */ |
|
729 function get_search_template() { |
|
730 return get_query_template('search'); |
|
731 } |
|
732 |
|
733 /** |
|
734 * Retrieve path of single template in current or parent template. |
|
735 * |
|
736 * @since 1.5.0 |
|
737 * |
|
738 * @return string |
|
739 */ |
|
740 function get_single_template() { |
|
741 return get_query_template('single'); |
|
742 } |
|
743 |
|
744 /** |
|
745 * Retrieve path of attachment template in current or parent template. |
|
746 * |
|
747 * The attachment path first checks if the first part of the mime type exists. |
|
748 * The second check is for the second part of the mime type. The last check is |
|
749 * for both types separated by an underscore. If neither are found then the file |
|
750 * 'attachment.php' is checked and returned. |
|
751 * |
|
752 * Some examples for the 'text/plain' mime type are 'text.php', 'plain.php', and |
|
753 * finally 'text_plain.php'. |
|
754 * |
|
755 * @since 2.0.0 |
|
756 * |
|
757 * @return string |
|
758 */ |
|
759 function get_attachment_template() { |
|
760 global $posts; |
|
761 $type = explode('/', $posts[0]->post_mime_type); |
|
762 if ( $template = get_query_template($type[0]) ) |
|
763 return $template; |
|
764 elseif ( $template = get_query_template($type[1]) ) |
|
765 return $template; |
|
766 elseif ( $template = get_query_template("$type[0]_$type[1]") ) |
|
767 return $template; |
|
768 else |
|
769 return get_query_template('attachment'); |
|
770 } |
|
771 |
|
772 /** |
|
773 * Retrieve path of comment popup template in current or parent template. |
|
774 * |
|
775 * Checks for comment popup template in current template, if it exists or in the |
|
776 * parent template. If it doesn't exist, then it retrieves the comment-popup.php |
|
777 * file from the default theme. The default theme must then exist for it to |
|
778 * work. |
|
779 * |
|
780 * @since 1.5.0 |
|
781 * @uses apply_filters() Calls 'comments_popup_template' filter on path. |
|
782 * |
|
783 * @return string |
|
784 */ |
|
785 function get_comments_popup_template() { |
|
786 $template = locate_template(array("comments-popup.php")); |
|
787 if ('' == $template) |
|
788 $template = get_theme_root() . '/default/comments-popup.php'; |
|
789 |
|
790 return apply_filters('comments_popup_template', $template); |
|
791 } |
|
792 |
|
793 /** |
|
794 * Retrieve the name of the highest priority template file that exists. |
|
795 * |
|
796 * Searches in the STYLESHEETPATH before TEMPLATEPATH so that themes which |
|
797 * inherit from a parent theme can just overload one file. |
|
798 * |
|
799 * @since 2.7.0 |
|
800 * |
|
801 * @param array $template_names Array of template files to search for in priority order. |
|
802 * @param bool $load If true the template file will be loaded if it is found. |
|
803 * @return string The template filename if one is located. |
|
804 */ |
|
805 function locate_template($template_names, $load = false) { |
|
806 if (!is_array($template_names)) |
|
807 return ''; |
|
808 |
|
809 $located = ''; |
|
810 foreach($template_names as $template_name) { |
|
811 if ( file_exists(STYLESHEETPATH . '/' . $template_name)) { |
|
812 $located = STYLESHEETPATH . '/' . $template_name; |
|
813 break; |
|
814 } else if ( file_exists(TEMPLATEPATH . '/' . $template_name) ) { |
|
815 $located = TEMPLATEPATH . '/' . $template_name; |
|
816 break; |
|
817 } |
|
818 } |
|
819 |
|
820 if ($load && '' != $located) |
|
821 load_template($located); |
|
822 |
|
823 return $located; |
|
824 } |
|
825 |
|
826 /** |
|
827 * Require once the template file with WordPress environment. |
|
828 * |
|
829 * The globals are set up for the template file to ensure that the WordPress |
|
830 * environment is available from within the function. The query variables are |
|
831 * also available. |
|
832 * |
|
833 * @since 1.5.0 |
|
834 * |
|
835 * @param string $_template_file Path to template file. |
|
836 */ |
|
837 function load_template($_template_file) { |
|
838 global $posts, $post, $wp_did_header, $wp_did_template_redirect, $wp_query, $wp_rewrite, $wpdb, $wp_version, $wp, $id, $comment, $user_ID; |
|
839 |
|
840 if ( is_array($wp_query->query_vars) ) |
|
841 extract($wp_query->query_vars, EXTR_SKIP); |
|
842 |
|
843 require_once($_template_file); |
|
844 } |
|
845 |
|
846 /** |
|
847 * Display localized stylesheet link element. |
|
848 * |
|
849 * @since 2.1.0 |
|
850 */ |
|
851 function locale_stylesheet() { |
|
852 $stylesheet = get_locale_stylesheet_uri(); |
|
853 if ( empty($stylesheet) ) |
|
854 return; |
|
855 echo '<link rel="stylesheet" href="' . $stylesheet . '" type="text/css" media="screen" />'; |
|
856 } |
|
857 |
|
858 /** |
|
859 * Start preview theme output buffer. |
|
860 * |
|
861 * Will only preform task if the user has permissions and template and preview |
|
862 * query variables exist. |
|
863 * |
|
864 * @since 2.5.0 |
|
865 */ |
|
866 function preview_theme() { |
|
867 if ( ! (isset($_GET['template']) && isset($_GET['preview'])) ) |
|
868 return; |
|
869 |
|
870 if ( !current_user_can( 'switch_themes' ) ) |
|
871 return; |
|
872 |
|
873 $_GET['template'] = preg_replace('|[^a-z0-9_./-]|i', '', $_GET['template']); |
|
874 |
|
875 if ( validate_file($_GET['template']) ) |
|
876 return; |
|
877 |
|
878 add_filter( 'template', '_preview_theme_template_filter' ); |
|
879 |
|
880 if ( isset($_GET['stylesheet']) ) { |
|
881 $_GET['stylesheet'] = preg_replace('|[^a-z0-9_./-]|i', '', $_GET['stylesheet']); |
|
882 if ( validate_file($_GET['stylesheet']) ) |
|
883 return; |
|
884 add_filter( 'stylesheet', '_preview_theme_stylesheet_filter' ); |
|
885 } |
|
886 |
|
887 // Prevent theme mods to current theme being used on theme being previewed |
|
888 add_filter( 'pre_option_mods_' . get_current_theme(), create_function( '', "return array();" ) ); |
|
889 |
|
890 ob_start( 'preview_theme_ob_filter' ); |
|
891 } |
|
892 add_action('setup_theme', 'preview_theme'); |
|
893 |
|
894 /** |
|
895 * Private function to modify the current template when previewing a theme |
|
896 * |
|
897 * @return string |
|
898 */ |
|
899 function _preview_theme_template_filter() { |
|
900 return isset($_GET['template']) ? $_GET['template'] : ''; |
|
901 } |
|
902 |
|
903 /** |
|
904 * Private function to modify the current stylesheet when previewing a theme |
|
905 * |
|
906 * @return string |
|
907 */ |
|
908 function _preview_theme_stylesheet_filter() { |
|
909 return isset($_GET['stylesheet']) ? $_GET['stylesheet'] : ''; |
|
910 } |
|
911 |
|
912 /** |
|
913 * Callback function for ob_start() to capture all links in the theme. |
|
914 * |
|
915 * @since unknown |
|
916 * @access private |
|
917 * |
|
918 * @param string $content |
|
919 * @return string |
|
920 */ |
|
921 function preview_theme_ob_filter( $content ) { |
|
922 return preg_replace_callback( "|(<a.*?href=([\"']))(.*?)([\"'].*?>)|", 'preview_theme_ob_filter_callback', $content ); |
|
923 } |
|
924 |
|
925 /** |
|
926 * Manipulates preview theme links in order to control and maintain location. |
|
927 * |
|
928 * Callback function for preg_replace_callback() to accept and filter matches. |
|
929 * |
|
930 * @since unknown |
|
931 * @access private |
|
932 * |
|
933 * @param array $matches |
|
934 * @return string |
|
935 */ |
|
936 function preview_theme_ob_filter_callback( $matches ) { |
|
937 if ( strpos($matches[4], 'onclick') !== false ) |
|
938 $matches[4] = preg_replace('#onclick=([\'"]).*?(?<!\\\)\\1#i', '', $matches[4]); //Strip out any onclicks from rest of <a>. (?<!\\\) means to ignore the '" if its escaped by \ to prevent breaking mid-attribute. |
|
939 if ( |
|
940 ( false !== strpos($matches[3], '/wp-admin/') ) |
|
941 || |
|
942 ( false !== strpos($matches[3], '://') && 0 !== strpos($matches[3], get_option('home')) ) |
|
943 || |
|
944 ( false !== strpos($matches[3], '/feed/') ) |
|
945 || |
|
946 ( false !== strpos($matches[3], '/trackback/') ) |
|
947 ) |
|
948 return $matches[1] . "#$matches[2] onclick=$matches[2]return false;" . $matches[4]; |
|
949 |
|
950 $link = add_query_arg( array('preview' => 1, 'template' => $_GET['template'], 'stylesheet' => @$_GET['stylesheet'] ), $matches[3] ); |
|
951 if ( 0 === strpos($link, 'preview=1') ) |
|
952 $link = "?$link"; |
|
953 return $matches[1] . esc_attr( $link ) . $matches[4]; |
|
954 } |
|
955 |
|
956 /** |
|
957 * Switches current theme to new template and stylesheet names. |
|
958 * |
|
959 * @since unknown |
|
960 * @uses do_action() Calls 'switch_theme' action on updated theme display name. |
|
961 * |
|
962 * @param string $template Template name |
|
963 * @param string $stylesheet Stylesheet name. |
|
964 */ |
|
965 function switch_theme($template, $stylesheet) { |
|
966 update_option('template', $template); |
|
967 update_option('stylesheet', $stylesheet); |
|
968 delete_option('current_theme'); |
|
969 $theme = get_current_theme(); |
|
970 do_action('switch_theme', $theme); |
|
971 } |
|
972 |
|
973 /** |
|
974 * Checks that current theme files 'index.php' and 'style.css' exists. |
|
975 * |
|
976 * Does not check the 'default' theme. The 'default' theme should always exist |
|
977 * or should have another theme renamed to that template name and directory |
|
978 * path. Will switch theme to default if current theme does not validate. |
|
979 * You can use the 'validate_current_theme' filter to return FALSE to |
|
980 * disable this functionality. |
|
981 * |
|
982 * @since 1.5.0 |
|
983 * |
|
984 * @return bool |
|
985 */ |
|
986 function validate_current_theme() { |
|
987 // Don't validate during an install/upgrade. |
|
988 if ( defined('WP_INSTALLING') || !apply_filters( 'validate_current_theme', true ) ) |
|
989 return true; |
|
990 |
|
991 if ( get_template() != 'default' && !file_exists(get_template_directory() . '/index.php') ) { |
|
992 switch_theme('default', 'default'); |
|
993 return false; |
|
994 } |
|
995 |
|
996 if ( get_stylesheet() != 'default' && !file_exists(get_template_directory() . '/style.css') ) { |
|
997 switch_theme('default', 'default'); |
|
998 return false; |
|
999 } |
|
1000 |
|
1001 return true; |
|
1002 } |
|
1003 |
|
1004 /** |
|
1005 * Retrieve theme modification value for the current theme. |
|
1006 * |
|
1007 * If the modification name does not exist, then the $default will be passed |
|
1008 * through {@link http://php.net/sprintf sprintf()} PHP function with the first |
|
1009 * string the template directory URI and the second string the stylesheet |
|
1010 * directory URI. |
|
1011 * |
|
1012 * @since 2.1.0 |
|
1013 * @uses apply_filters() Calls 'theme_mod_$name' filter on the value. |
|
1014 * |
|
1015 * @param string $name Theme modification name. |
|
1016 * @param bool|string $default |
|
1017 * @return string |
|
1018 */ |
|
1019 function get_theme_mod($name, $default = false) { |
|
1020 $theme = get_current_theme(); |
|
1021 |
|
1022 $mods = get_option("mods_$theme"); |
|
1023 |
|
1024 if ( isset($mods[$name]) ) |
|
1025 return apply_filters( "theme_mod_$name", $mods[$name] ); |
|
1026 |
|
1027 return apply_filters( "theme_mod_$name", sprintf($default, get_template_directory_uri(), get_stylesheet_directory_uri()) ); |
|
1028 } |
|
1029 |
|
1030 /** |
|
1031 * Update theme modification value for the current theme. |
|
1032 * |
|
1033 * @since 2.1.0 |
|
1034 * |
|
1035 * @param string $name Theme modification name. |
|
1036 * @param string $value theme modification value. |
|
1037 */ |
|
1038 function set_theme_mod($name, $value) { |
|
1039 $theme = get_current_theme(); |
|
1040 |
|
1041 $mods = get_option("mods_$theme"); |
|
1042 |
|
1043 $mods[$name] = $value; |
|
1044 |
|
1045 update_option("mods_$theme", $mods); |
|
1046 wp_cache_delete("mods_$theme", 'options'); |
|
1047 } |
|
1048 |
|
1049 /** |
|
1050 * Remove theme modification name from current theme list. |
|
1051 * |
|
1052 * If removing the name also removes all elements, then the entire option will |
|
1053 * be removed. |
|
1054 * |
|
1055 * @since 2.1.0 |
|
1056 * |
|
1057 * @param string $name Theme modification name. |
|
1058 * @return null |
|
1059 */ |
|
1060 function remove_theme_mod( $name ) { |
|
1061 $theme = get_current_theme(); |
|
1062 |
|
1063 $mods = get_option("mods_$theme"); |
|
1064 |
|
1065 if ( !isset($mods[$name]) ) |
|
1066 return; |
|
1067 |
|
1068 unset($mods[$name]); |
|
1069 |
|
1070 if ( empty($mods) ) |
|
1071 return remove_theme_mods(); |
|
1072 |
|
1073 update_option("mods_$theme", $mods); |
|
1074 wp_cache_delete("mods_$theme", 'options'); |
|
1075 } |
|
1076 |
|
1077 /** |
|
1078 * Remove theme modifications option for current theme. |
|
1079 * |
|
1080 * @since 2.1.0 |
|
1081 */ |
|
1082 function remove_theme_mods() { |
|
1083 $theme = get_current_theme(); |
|
1084 |
|
1085 delete_option("mods_$theme"); |
|
1086 } |
|
1087 |
|
1088 /** |
|
1089 * Retrieve text color for custom header. |
|
1090 * |
|
1091 * @since 2.1.0 |
|
1092 * @uses HEADER_TEXTCOLOR |
|
1093 * |
|
1094 * @return string |
|
1095 */ |
|
1096 function get_header_textcolor() { |
|
1097 return get_theme_mod('header_textcolor', HEADER_TEXTCOLOR); |
|
1098 } |
|
1099 |
|
1100 /** |
|
1101 * Display text color for custom header. |
|
1102 * |
|
1103 * @since 2.1.0 |
|
1104 */ |
|
1105 function header_textcolor() { |
|
1106 echo get_header_textcolor(); |
|
1107 } |
|
1108 |
|
1109 /** |
|
1110 * Retrieve header image for custom header. |
|
1111 * |
|
1112 * @since 2.1.0 |
|
1113 * @uses HEADER_IMAGE |
|
1114 * |
|
1115 * @return string |
|
1116 */ |
|
1117 function get_header_image() { |
|
1118 return get_theme_mod('header_image', HEADER_IMAGE); |
|
1119 } |
|
1120 |
|
1121 /** |
|
1122 * Display header image path. |
|
1123 * |
|
1124 * @since 2.1.0 |
|
1125 */ |
|
1126 function header_image() { |
|
1127 echo get_header_image(); |
|
1128 } |
|
1129 |
|
1130 /** |
|
1131 * Add callbacks for image header display. |
|
1132 * |
|
1133 * The parameter $header_callback callback will be required to display the |
|
1134 * content for the 'wp_head' action. The parameter $admin_header_callback |
|
1135 * callback will be added to Custom_Image_Header class and that will be added |
|
1136 * to the 'admin_menu' action. |
|
1137 * |
|
1138 * @since 2.1.0 |
|
1139 * @uses Custom_Image_Header Sets up for $admin_header_callback for administration panel display. |
|
1140 * |
|
1141 * @param callback $header_callback Call on 'wp_head' action. |
|
1142 * @param callback $admin_header_callback Call on administration panels. |
|
1143 */ |
|
1144 function add_custom_image_header($header_callback, $admin_header_callback) { |
|
1145 if ( ! empty($header_callback) ) |
|
1146 add_action('wp_head', $header_callback); |
|
1147 |
|
1148 if ( ! is_admin() ) |
|
1149 return; |
|
1150 require_once(ABSPATH . 'wp-admin/custom-header.php'); |
|
1151 $GLOBALS['custom_image_header'] =& new Custom_Image_Header($admin_header_callback); |
|
1152 add_action('admin_menu', array(&$GLOBALS['custom_image_header'], 'init')); |
|
1153 } |
|
1154 |
|
1155 ?> |