2007-05-25 03:16:21 -04:00
< ? php
2008-10-01 21:03:26 -04:00
/**
* WordPress Theme Administration API
*
* @ package WordPress
* @ subpackage Administration
*/
2007-05-25 03:16:21 -04:00
2008-10-01 21:03:26 -04:00
/**
* { @ internal Missing Short Description }}
*
2010-12-01 14:24:38 -05:00
* @ since 2.0 . 0
2008-10-01 21:03:26 -04:00
*
* @ return unknown
*/
2007-05-25 03:16:21 -04:00
function current_theme_info () {
$themes = get_themes ();
$current_theme = get_current_theme ();
2010-03-18 23:09:02 -04:00
if ( ! isset ( $themes [ $current_theme ] ) ) {
delete_option ( 'current_theme' );
$current_theme = get_current_theme ();
}
2007-05-25 03:16:21 -04:00
$ct -> name = $current_theme ;
$ct -> title = $themes [ $current_theme ][ 'Title' ];
$ct -> version = $themes [ $current_theme ][ 'Version' ];
$ct -> parent_theme = $themes [ $current_theme ][ 'Parent Theme' ];
$ct -> template_dir = $themes [ $current_theme ][ 'Template Dir' ];
$ct -> stylesheet_dir = $themes [ $current_theme ][ 'Stylesheet Dir' ];
$ct -> template = $themes [ $current_theme ][ 'Template' ];
$ct -> stylesheet = $themes [ $current_theme ][ 'Stylesheet' ];
$ct -> screenshot = $themes [ $current_theme ][ 'Screenshot' ];
$ct -> description = $themes [ $current_theme ][ 'Description' ];
$ct -> author = $themes [ $current_theme ][ 'Author' ];
2007-12-31 13:39:43 -05:00
$ct -> tags = $themes [ $current_theme ][ 'Tags' ];
2009-10-13 15:06:35 -04:00
$ct -> theme_root = $themes [ $current_theme ][ 'Theme Root' ];
$ct -> theme_root_uri = $themes [ $current_theme ][ 'Theme Root URI' ];
2007-05-25 03:16:21 -04:00
return $ct ;
}
2009-03-05 14:15:56 -05:00
/**
* Remove a theme
*
* @ since 2.8 . 0
*
* @ param string $template Template directory of the theme to delete
* @ return mixed
*/
function delete_theme ( $template ) {
global $wp_filesystem ;
if ( empty ( $template ) )
return false ;
ob_start ();
$url = wp_nonce_url ( 'themes.php?action=delete&template=' . $template , 'delete-theme_' . $template );
if ( false === ( $credentials = request_filesystem_credentials ( $url )) ) {
$data = ob_get_contents ();
ob_end_clean ();
if ( ! empty ( $data ) ){
include_once ( ABSPATH . 'wp-admin/admin-header.php' );
echo $data ;
include ( ABSPATH . 'wp-admin/admin-footer.php' );
exit ;
}
return ;
}
if ( ! WP_Filesystem ( $credentials ) ) {
request_filesystem_credentials ( $url , '' , true ); // Failed to connect, Error and request again
$data = ob_get_contents ();
ob_end_clean ();
2010-01-18 15:34:48 -05:00
if ( ! empty ( $data ) ) {
2009-03-05 14:15:56 -05:00
include_once ( ABSPATH . 'wp-admin/admin-header.php' );
echo $data ;
include ( ABSPATH . 'wp-admin/admin-footer.php' );
exit ;
}
return ;
}
if ( ! is_object ( $wp_filesystem ) )
return new WP_Error ( 'fs_unavailable' , __ ( 'Could not access filesystem.' ));
2009-04-19 15:36:28 -04:00
if ( is_wp_error ( $wp_filesystem -> errors ) && $wp_filesystem -> errors -> get_error_code () )
2010-01-21 16:37:43 -05:00
return new WP_Error ( 'fs_error' , __ ( 'Filesystem error.' ), $wp_filesystem -> errors );
2009-03-05 14:15:56 -05:00
//Get the base plugin folder
$themes_dir = $wp_filesystem -> wp_themes_dir ();
if ( empty ( $themes_dir ) )
return new WP_Error ( 'fs_no_themes_dir' , __ ( 'Unable to locate WordPress theme directory.' ));
$themes_dir = trailingslashit ( $themes_dir );
$theme_dir = trailingslashit ( $themes_dir . $template );
$deleted = $wp_filesystem -> delete ( $theme_dir , true );
if ( ! $deleted )
2010-01-21 16:37:43 -05:00
return new WP_Error ( 'could_not_remove_theme' , sprintf ( __ ( 'Could not fully remove the theme %s.' ), $template ) );
2009-03-05 14:15:56 -05:00
// Force refresh of theme update information
2010-01-08 15:49:55 -05:00
delete_site_transient ( 'update_themes' );
2009-03-05 14:15:56 -05:00
return true ;
}
2008-10-01 21:03:26 -04:00
/**
* { @ internal Missing Short Description }}
*
2010-12-01 14:24:38 -05:00
* @ since 1.5 . 0
2008-10-01 21:03:26 -04:00
*
* @ return unknown
*/
2007-05-25 03:16:21 -04:00
function get_broken_themes () {
global $wp_broken_themes ;
get_themes ();
return $wp_broken_themes ;
}
2010-01-18 18:34:36 -05:00
/**
* Get the allowed themes for the current blog .
*
2010-03-26 15:13:36 -04:00
* @ since 3.0 . 0
2010-01-18 18:34:36 -05:00
*
* @ uses get_themes ()
* @ uses current_theme_info ()
* @ uses get_site_allowed_themes ()
* @ uses wpmu_get_blog_allowedthemes
*
* @ return array $themes Array of allowed themes .
*/
function get_allowed_themes () {
if ( ! is_multisite () )
return get_themes ();
$themes = get_themes ();
$ct = current_theme_info ();
$allowed_themes = apply_filters ( " allowed_themes " , get_site_allowed_themes () );
if ( $allowed_themes == false )
$allowed_themes = array ();
$blog_allowed_themes = wpmu_get_blog_allowedthemes ();
if ( is_array ( $blog_allowed_themes ) )
$allowed_themes = array_merge ( $allowed_themes , $blog_allowed_themes );
2010-02-13 05:35:10 -05:00
if ( isset ( $allowed_themes [ esc_html ( $ct -> stylesheet ) ] ) == false )
$allowed_themes [ esc_html ( $ct -> stylesheet ) ] = true ;
2010-01-18 18:34:36 -05:00
reset ( $themes );
foreach ( $themes as $key => $theme ) {
2010-02-13 05:35:10 -05:00
if ( isset ( $allowed_themes [ esc_html ( $theme [ 'Stylesheet' ] ) ] ) == false )
2010-01-18 18:34:36 -05:00
unset ( $themes [ $key ] );
}
reset ( $themes );
2010-01-26 17:49:05 -05:00
2010-01-18 18:34:36 -05:00
return $themes ;
}
2008-10-01 21:03:26 -04:00
/**
2009-11-13 17:40:40 -05:00
* Get the Page Templates available in this theme
2008-10-01 21:03:26 -04:00
*
2010-12-01 14:24:38 -05:00
* @ since 1.5 . 0
2008-10-01 21:03:26 -04:00
*
2009-11-19 14:53:27 -05:00
* @ return array Key is template name , Value is template name
2008-10-01 21:03:26 -04:00
*/
2007-05-25 03:16:21 -04:00
function get_page_templates () {
$themes = get_themes ();
$theme = get_current_theme ();
$templates = $themes [ $theme ][ 'Template Files' ];
2009-11-21 05:05:19 -05:00
$page_templates = array ();
2007-05-25 03:16:21 -04:00
if ( is_array ( $templates ) ) {
2009-11-21 05:05:19 -05:00
$base = array ( trailingslashit ( get_template_directory ()), trailingslashit ( get_stylesheet_directory ()) );
2007-05-25 03:16:21 -04:00
foreach ( $templates as $template ) {
2009-11-21 05:05:19 -05:00
$basename = str_replace ( $base , '' , $template );
// don't allow template files in subdirectories
if ( false !== strpos ( $basename , '/' ) )
continue ;
2009-10-14 16:46:09 -04:00
$template_data = implode ( '' , file ( $template ));
2007-06-13 22:25:30 -04:00
2008-08-08 13:05:10 -04:00
$name = '' ;
if ( preg_match ( '|Template Name:(.*)$|mi' , $template_data , $name ) )
2009-05-04 05:12:12 -04:00
$name = _cleanup_header_comment ( $name [ 1 ]);
2007-05-25 03:16:21 -04:00
2007-06-01 20:02:06 -04:00
if ( ! empty ( $name ) ) {
2009-11-21 05:05:19 -05:00
$page_templates [ trim ( $name )] = $basename ;
2007-05-25 03:16:21 -04:00
}
}
}
return $page_templates ;
}
2009-10-19 17:39:04 -04:00
/**
* Tidies a filename for url display by the theme editor .
2010-01-15 17:11:12 -05:00
*
2009-10-19 17:39:04 -04:00
* @ since 2.9 . 0
2010-05-03 09:27:15 -04:00
* @ access private
2010-01-15 17:11:12 -05:00
*
2009-10-19 17:39:04 -04:00
* @ param string $fullpath Full path to the theme file
* @ param string $containingfolder Path of the theme parent folder
* @ return string
*/
function _get_template_edit_filename ( $fullpath , $containingfolder ) {
return str_replace ( dirname ( dirname ( $containingfolder )) , '' , $fullpath );
}
2010-05-03 09:29:15 -04:00
/**
* Check if there is an update for a theme available .
*
* Will display link , if there is an update available .
*
* @ since 2.7 . 0
*
* @ param object $theme Theme data object .
* @ return bool False if no valid info was passed .
*/
function theme_update_available ( $theme ) {
static $themes_update ;
if ( ! current_user_can ( 'update_themes' ) )
return ;
if ( ! isset ( $themes_update ) )
$themes_update = get_site_transient ( 'update_themes' );
if ( is_object ( $theme ) && isset ( $theme -> stylesheet ) )
$stylesheet = $theme -> stylesheet ;
elseif ( is_array ( $theme ) && isset ( $theme [ 'Stylesheet' ]) )
$stylesheet = $theme [ 'Stylesheet' ];
else
return false ; //No valid info passed.
if ( isset ( $themes_update -> response [ $stylesheet ]) ) {
$update = $themes_update -> response [ $stylesheet ];
$theme_name = is_object ( $theme ) ? $theme -> name : ( is_array ( $theme ) ? $theme [ 'Name' ] : '' );
$details_url = add_query_arg ( array ( 'TB_iframe' => 'true' , 'width' => 1024 , 'height' => 800 ), $update [ 'url' ]); //Theme browser inside WP? replace this, Also, theme preview JS will override this on the available list.
$update_url = wp_nonce_url ( 'update.php?action=upgrade-theme&theme=' . urlencode ( $stylesheet ), 'upgrade-theme_' . $stylesheet );
2010-12-03 04:16:28 -05:00
$update_onclick = 'onclick="if ( confirm(\'' . esc_js ( __ ( " Updating this theme will lose any customizations you have made. 'Cancel' to stop, 'OK' to update. " ) ) . '\') ) {return true;}return false;"' ;
2010-05-03 09:29:15 -04:00
2010-11-29 22:03:40 -05:00
if ( ! is_multisite () ) {
if ( ! current_user_can ( 'update_themes' ) )
printf ( '<p><strong>' . __ ( 'There is a new version of %1$s available. <a href="%2$s" class="thickbox" title="%1$s">View version %3$s details</a>.' ) . '</strong></p>' , $theme_name , $details_url , $update [ 'new_version' ]);
else if ( empty ( $update [ 'package' ]) )
2010-12-02 16:45:47 -05:00
printf ( '<p><strong>' . __ ( 'There is a new version of %1$s available. <a href="%2$s" class="thickbox" title="%1$s">View version %3$s details</a>. <em>Automatic update is unavailable for this theme.</em>' ) . '</strong></p>' , $theme_name , $details_url , $update [ 'new_version' ]);
2010-11-29 22:03:40 -05:00
else
2010-12-02 16:45:47 -05:00
printf ( '<p><strong>' . __ ( 'There is a new version of %1$s available. <a href="%2$s" class="thickbox" title="%1$s">View version %3$s details</a> or <a href="%4$s" %5$s>update automatically</a>.' ) . '</strong></p>' , $theme_name , $details_url , $update [ 'new_version' ], $update_url , $update_onclick );
2010-11-29 22:03:40 -05:00
}
2010-05-03 09:29:15 -04:00
}
}
2010-09-24 11:28:28 -04:00
/**
* Retrieve list of WordPress theme features ( aka theme tags )
*
* @ since 3.1 . 0
*
* @ return array Array of features keyed by category with translations keyed by slug .
*/
function get_theme_feature_list () {
// Hard-coded list is used if api not accessible.
$features = array (
__ ( 'Colors' ) => array (
'black' => __ ( 'Black' ),
'blue' => __ ( 'Blue' ),
'brown' => __ ( 'Brown' ),
'green' => __ ( 'Green' ),
'orange' => __ ( 'Orange' ),
'pink' => __ ( 'Pink' ),
'purple' => __ ( 'Purple' ),
'red' => __ ( 'Red' ),
'silver' => __ ( 'Silver' ),
'tan' => __ ( 'Tan' ),
'white' => __ ( 'White' ),
'yellow' => __ ( 'Yellow' ),
'dark' => __ ( 'Dark' ),
'light' => __ ( 'Light ' )
),
__ ( 'Columns' ) => array (
'one-column' => __ ( 'One Column' ),
'two-columns' => __ ( 'Two Columns' ),
'three-columns' => __ ( 'Three Columns' ),
'four-columns' => __ ( 'Four Columns' ),
'left-sidebar' => __ ( 'Left Sidebar' ),
'right-sidebar' => __ ( 'Right Sidebar' )
),
__ ( 'Width' ) => array (
'fixed-width' => __ ( 'Fixed Width' ),
'flexible-width' => __ ( 'Flexible Width' )
),
__ ( 'Features' ) => array (
'blavatar' => __ ( 'Blavatar' ),
'buddypress' => __ ( 'BuddyPress' ),
'custom-background' => __ ( 'Custom Background' ),
'custom-colors' => __ ( 'Custom Colors' ),
'custom-header' => __ ( 'Custom Header' ),
'custom-menu' => __ ( 'Custom Menu' ),
'editor-style' => __ ( 'Editor Style' ),
'front-page-post-form' => __ ( 'Front Page Posting' ),
'microformats' => __ ( 'Microformats' ),
'sticky-post' => __ ( 'Sticky Post' ),
'theme-options' => __ ( 'Theme Options' ),
'threaded-comments' => __ ( 'Threaded Comments' ),
'translation-ready' => __ ( 'Translation Ready' ),
'rtl-language-support' => __ ( 'RTL Language Support' )
),
__ ( 'Subject' ) => array (
'holiday' => __ ( 'Holiday' ),
'photoblogging' => __ ( 'Photoblogging' ),
'seasonal' => __ ( 'Seasonal' )
)
);
if ( ! current_user_can ( 'install_themes' ) )
return $features ;
if ( ! $feature_list = get_site_transient ( 'wporg_theme_feature_list' ) )
set_site_transient ( 'wporg_theme_feature_list' , array ( ), 10800 );
if ( ! $feature_list ) {
$feature_list = themes_api ( 'feature_list' , array ( ) );
if ( is_wp_error ( $feature_list ) )
return $features ;
}
if ( ! $feature_list )
return $features ;
set_site_transient ( 'wporg_theme_feature_list' , $feature_list , 10800 );
$category_translations = array ( 'Colors' => __ ( 'Colors' ), 'Columns' => __ ( 'Columns' ), 'Width' => __ ( 'Width' ),
'Features' => __ ( 'Features' ), 'Subject' => __ ( 'Subject' ) );
// Loop over the wporg canonical list and apply translations
$wporg_features = array ();
foreach ( ( array ) $feature_list as $feature_category => $feature_items ) {
if ( isset ( $category_translations [ $feature_category ]) )
$feature_category = $category_translations [ $feature_category ];
$wporg_features [ $feature_category ] = array ();
foreach ( $feature_items as $feature ) {
if ( isset ( $features [ $feature_category ][ $feature ]) )
$wporg_features [ $feature_category ][ $feature ] = $features [ $feature_category ][ $feature ];
else
$wporg_features [ $feature_category ][ $feature ] = $feature ;
}
}
return $wporg_features ;
}
2010-10-05 09:24:41 -04:00
/**
* Retrieve theme installer pages from WordPress Themes API .
*
* It is possible for a theme to override the Themes API result with three
* filters . Assume this is for themes , which can extend on the Theme Info to
* offer more choices . This is very powerful and must be used with care , when
* overridding the filters .
*
* The first filter , 'themes_api_args' , is for the args and gives the action as
* the second parameter . The hook for 'themes_api_args' must ensure that an
* object is returned .
*
* The second filter , 'themes_api' , is the result that would be returned .
*
* @ since 2.8 . 0
*
* @ param string $action
* @ param array | object $args Optional . Arguments to serialize for the Theme Info API .
* @ return mixed
*/
function themes_api ( $action , $args = null ) {
if ( is_array ( $args ) )
$args = ( object ) $args ;
if ( ! isset ( $args -> per_page ) )
$args -> per_page = 24 ;
$args = apply_filters ( 'themes_api_args' , $args , $action ); //NOTE: Ensure that an object is returned via this filter.
$res = apply_filters ( 'themes_api' , false , $action , $args ); //NOTE: Allows a theme to completely override the builtin WordPress.org API.
if ( ! $res ) {
$request = wp_remote_post ( 'http://api.wordpress.org/themes/info/1.0/' , array ( 'body' => array ( 'action' => $action , 'request' => serialize ( $args ))) );
if ( is_wp_error ( $request ) ) {
2010-12-02 18:30:21 -05:00
$res = new WP_Error ( 'themes_api_failed' , __ ( 'An Unexpected HTTP Error occurred during the API request.</p> <p><a href="?" onclick="document.location.reload(); return false;">Try again</a>' ), $request -> get_error_message () );
2010-10-05 09:24:41 -04:00
} else {
$res = unserialize ( $request [ 'body' ]);
if ( ! $res )
2010-12-05 09:31:18 -05:00
$res = new WP_Error ( 'themes_api_failed' , __ ( 'An unknown error occurred.' ), $request [ 'body' ]);
2010-10-05 09:24:41 -04:00
}
}
//var_dump(array($args, $res));
return apply_filters ( 'themes_api_result' , $res , $action , $args );
}
2007-05-25 03:16:21 -04:00
?>