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