wp/wp-admin/includes/theme.php
changeset 0 d970ebf37754
child 5 5e2f62d02dcd
equal deleted inserted replaced
-1:000000000000 0:d970ebf37754
       
     1 <?php
       
     2 /**
       
     3  * WordPress Theme Administration API
       
     4  *
       
     5  * @package WordPress
       
     6  * @subpackage Administration
       
     7  */
       
     8 
       
     9 /**
       
    10  * Remove a theme
       
    11  *
       
    12  * @since 2.8.0
       
    13  *
       
    14  * @param string $stylesheet Stylesheet of the theme to delete
       
    15  * @param string $redirect Redirect to page when complete.
       
    16  * @return mixed
       
    17  */
       
    18 function delete_theme($stylesheet, $redirect = '') {
       
    19 	global $wp_filesystem;
       
    20 
       
    21 	if ( empty($stylesheet) )
       
    22 		return false;
       
    23 
       
    24 	ob_start();
       
    25 	if ( empty( $redirect ) )
       
    26 		$redirect = wp_nonce_url('themes.php?action=delete&stylesheet=' . urlencode( $stylesheet ), 'delete-theme_' . $stylesheet);
       
    27 	if ( false === ($credentials = request_filesystem_credentials($redirect)) ) {
       
    28 		$data = ob_get_contents();
       
    29 		ob_end_clean();
       
    30 		if ( ! empty($data) ){
       
    31 			include_once( ABSPATH . 'wp-admin/admin-header.php');
       
    32 			echo $data;
       
    33 			include( ABSPATH . 'wp-admin/admin-footer.php');
       
    34 			exit;
       
    35 		}
       
    36 		return;
       
    37 	}
       
    38 
       
    39 	if ( ! WP_Filesystem($credentials) ) {
       
    40 		request_filesystem_credentials($redirect, '', true); // Failed to connect, Error and request again
       
    41 		$data = ob_get_contents();
       
    42 		ob_end_clean();
       
    43 		if ( ! empty($data) ) {
       
    44 			include_once( ABSPATH . 'wp-admin/admin-header.php');
       
    45 			echo $data;
       
    46 			include( ABSPATH . 'wp-admin/admin-footer.php');
       
    47 			exit;
       
    48 		}
       
    49 		return;
       
    50 	}
       
    51 
       
    52 	if ( ! is_object($wp_filesystem) )
       
    53 		return new WP_Error('fs_unavailable', __('Could not access filesystem.'));
       
    54 
       
    55 	if ( is_wp_error($wp_filesystem->errors) && $wp_filesystem->errors->get_error_code() )
       
    56 		return new WP_Error('fs_error', __('Filesystem error.'), $wp_filesystem->errors);
       
    57 
       
    58 	//Get the base plugin folder
       
    59 	$themes_dir = $wp_filesystem->wp_themes_dir();
       
    60 	if ( empty($themes_dir) )
       
    61 		return new WP_Error('fs_no_themes_dir', __('Unable to locate WordPress theme directory.'));
       
    62 
       
    63 	$themes_dir = trailingslashit( $themes_dir );
       
    64 	$theme_dir = trailingslashit($themes_dir . $stylesheet);
       
    65 	$deleted = $wp_filesystem->delete($theme_dir, true);
       
    66 
       
    67 	if ( ! $deleted )
       
    68 		return new WP_Error('could_not_remove_theme', sprintf(__('Could not fully remove the theme %s.'), $stylesheet) );
       
    69 
       
    70 	// Force refresh of theme update information
       
    71 	delete_site_transient('update_themes');
       
    72 
       
    73 	return true;
       
    74 }
       
    75 
       
    76 /**
       
    77  * Get the Page Templates available in this theme
       
    78  *
       
    79  * @since 1.5.0
       
    80  *
       
    81  * @return array Key is the template name, value is the filename of the template
       
    82  */
       
    83 function get_page_templates() {
       
    84 	return array_flip( wp_get_theme()->get_page_templates() );
       
    85 }
       
    86 
       
    87 /**
       
    88  * Tidies a filename for url display by the theme editor.
       
    89  *
       
    90  * @since 2.9.0
       
    91  * @access private
       
    92  *
       
    93  * @param string $fullpath Full path to the theme file
       
    94  * @param string $containingfolder Path of the theme parent folder
       
    95  * @return string
       
    96  */
       
    97 function _get_template_edit_filename($fullpath, $containingfolder) {
       
    98 	return str_replace(dirname(dirname( $containingfolder )) , '', $fullpath);
       
    99 }
       
   100 
       
   101 /**
       
   102  * Check if there is an update for a theme available.
       
   103  *
       
   104  * Will display link, if there is an update available.
       
   105  *
       
   106  * @since 2.7.0
       
   107  *
       
   108  * @param object $theme Theme data object.
       
   109  * @return bool False if no valid info was passed.
       
   110  */
       
   111 function theme_update_available( $theme ) {
       
   112 	static $themes_update;
       
   113 
       
   114 	if ( !current_user_can('update_themes' ) )
       
   115 		return;
       
   116 
       
   117 	if ( !isset($themes_update) )
       
   118 		$themes_update = get_site_transient('update_themes');
       
   119 
       
   120 	if ( ! is_a( $theme, 'WP_Theme' ) )
       
   121 		return;
       
   122 
       
   123 	$stylesheet = $theme->get_stylesheet();
       
   124 
       
   125 	if ( isset($themes_update->response[ $stylesheet ]) ) {
       
   126 		$update = $themes_update->response[ $stylesheet ];
       
   127 		$theme_name = $theme->display('Name');
       
   128 		$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.
       
   129 		$update_url = wp_nonce_url('update.php?action=upgrade-theme&amp;theme=' . urlencode($stylesheet), 'upgrade-theme_' . $stylesheet);
       
   130 		$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;"';
       
   131 
       
   132 		if ( !is_multisite() ) {
       
   133 			if ( ! current_user_can('update_themes') )
       
   134 				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']);
       
   135 			else if ( empty($update['package']) )
       
   136 				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']);
       
   137 			else
       
   138 				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 now</a>.') . '</strong></p>', $theme_name, $details_url, $update['new_version'], $update_url, $update_onclick );
       
   139 		}
       
   140 	}
       
   141 }
       
   142 
       
   143 /**
       
   144  * Retrieve list of WordPress theme features (aka theme tags)
       
   145  *
       
   146  * @since 3.1.0
       
   147  *
       
   148  * @param bool $api Optional. Whether try to fetch tags from the WP.org API. Defaults to true.
       
   149  * @return array Array of features keyed by category with translations keyed by slug.
       
   150  */
       
   151 function get_theme_feature_list( $api = true ) {
       
   152 	// Hard-coded list is used if api not accessible.
       
   153 	$features = array(
       
   154 			__( 'Colors' ) => array(
       
   155 				'black'   => __( 'Black' ),
       
   156 				'blue'    => __( 'Blue' ),
       
   157 				'brown'   => __( 'Brown' ),
       
   158 				'gray'    => __( 'Gray' ),
       
   159 				'green'   => __( 'Green' ),
       
   160 				'orange'  => __( 'Orange' ),
       
   161 				'pink'    => __( 'Pink' ),
       
   162 				'purple'  => __( 'Purple' ),
       
   163 				'red'     => __( 'Red' ),
       
   164 				'silver'  => __( 'Silver' ),
       
   165 				'tan'     => __( 'Tan' ),
       
   166 				'white'   => __( 'White' ),
       
   167 				'yellow'  => __( 'Yellow' ),
       
   168 				'dark'    => __( 'Dark' ),
       
   169 				'light'   => __( 'Light' ),
       
   170 			),
       
   171 
       
   172 		__( 'Columns' ) => array(
       
   173 			'one-column'    => __( 'One Column' ),
       
   174 			'two-columns'   => __( 'Two Columns' ),
       
   175 			'three-columns' => __( 'Three Columns' ),
       
   176 			'four-columns'  => __( 'Four Columns' ),
       
   177 			'left-sidebar'  => __( 'Left Sidebar' ),
       
   178 			'right-sidebar' => __( 'Right Sidebar' ),
       
   179 		),
       
   180 
       
   181 		__( 'Width' ) => array(
       
   182 			'fixed-width'    => __( 'Fixed Width' ),
       
   183 			'flexible-width' => __( 'Flexible Width' ),
       
   184 		),
       
   185 
       
   186 		__( 'Features' ) => array(
       
   187 			'blavatar'              => __( 'Blavatar' ),
       
   188 			'buddypress'            => __( 'BuddyPress' ),
       
   189 			'custom-background'     => __( 'Custom Background' ),
       
   190 			'custom-colors'         => __( 'Custom Colors' ),
       
   191 			'custom-header'         => __( 'Custom Header' ),
       
   192 			'custom-menu'           => __( 'Custom Menu' ),
       
   193 			'editor-style'          => __( 'Editor Style' ),
       
   194 			'featured-image-header' => __( 'Featured Image Header' ),
       
   195 			'featured-images'       => __( 'Featured Images' ),
       
   196 			'flexible-header'       => __( 'Flexible Header' ),
       
   197 			'front-page-post-form'  => __( 'Front Page Posting' ),
       
   198 			'full-width-template'   => __( 'Full Width Template' ),
       
   199 			'microformats'          => __( 'Microformats' ),
       
   200 			'post-formats'          => __( 'Post Formats' ),
       
   201 			'rtl-language-support'  => __( 'RTL Language Support' ),
       
   202 			'sticky-post'           => __( 'Sticky Post' ),
       
   203 			'theme-options'         => __( 'Theme Options' ),
       
   204 			'threaded-comments'     => __( 'Threaded Comments' ),
       
   205 			'translation-ready'     => __( 'Translation Ready' ),
       
   206 		),
       
   207 
       
   208 		__( 'Subject' )  => array(
       
   209 			'holiday'       => __( 'Holiday' ),
       
   210 			'photoblogging' => __( 'Photoblogging' ),
       
   211 			'seasonal'      => __( 'Seasonal' ),
       
   212 		)
       
   213 	);
       
   214 
       
   215 	if ( ! $api || ! current_user_can( 'install_themes' ) )
       
   216 		return $features;
       
   217 
       
   218 	if ( !$feature_list = get_site_transient( 'wporg_theme_feature_list' ) )
       
   219 		set_site_transient( 'wporg_theme_feature_list', array(), 10800);
       
   220 
       
   221 	if ( !$feature_list ) {
       
   222 		$feature_list = themes_api( 'feature_list', array() );
       
   223 		if ( is_wp_error( $feature_list ) )
       
   224 			return $features;
       
   225 	}
       
   226 
       
   227 	if ( !$feature_list )
       
   228 		return $features;
       
   229 
       
   230 	set_site_transient( 'wporg_theme_feature_list', $feature_list, 10800 );
       
   231 
       
   232 	$category_translations = array( 'Colors' => __('Colors'), 'Columns' => __('Columns'), 'Width' => __('Width'),
       
   233 								   'Features' => __('Features'), 'Subject' => __('Subject') );
       
   234 
       
   235 	// Loop over the wporg canonical list and apply translations
       
   236 	$wporg_features = array();
       
   237 	foreach ( (array) $feature_list as $feature_category => $feature_items ) {
       
   238 		if ( isset($category_translations[$feature_category]) )
       
   239 			$feature_category = $category_translations[$feature_category];
       
   240 		$wporg_features[$feature_category] = array();
       
   241 
       
   242 		foreach ( $feature_items as $feature ) {
       
   243 			if ( isset($features[$feature_category][$feature]) )
       
   244 				$wporg_features[$feature_category][$feature] = $features[$feature_category][$feature];
       
   245 			else
       
   246 				$wporg_features[$feature_category][$feature] = $feature;
       
   247 		}
       
   248 	}
       
   249 
       
   250 	return $wporg_features;
       
   251 }
       
   252 
       
   253 /**
       
   254  * Retrieve theme installer pages from WordPress Themes API.
       
   255  *
       
   256  * It is possible for a theme to override the Themes API result with three
       
   257  * filters. Assume this is for themes, which can extend on the Theme Info to
       
   258  * offer more choices. This is very powerful and must be used with care, when
       
   259  * overridding the filters.
       
   260  *
       
   261  * The first filter, 'themes_api_args', is for the args and gives the action as
       
   262  * the second parameter. The hook for 'themes_api_args' must ensure that an
       
   263  * object is returned.
       
   264  *
       
   265  * The second filter, 'themes_api', is the result that would be returned.
       
   266  *
       
   267  * @since 2.8.0
       
   268  *
       
   269  * @param string $action
       
   270  * @param array|object $args Optional. Arguments to serialize for the Theme Info API.
       
   271  * @return mixed
       
   272  */
       
   273 function themes_api($action, $args = null) {
       
   274 
       
   275 	if ( is_array($args) )
       
   276 		$args = (object)$args;
       
   277 
       
   278 	if ( !isset($args->per_page) )
       
   279 		$args->per_page = 24;
       
   280 
       
   281 	$args = apply_filters('themes_api_args', $args, $action); //NOTE: Ensure that an object is returned via this filter.
       
   282 	$res = apply_filters('themes_api', false, $action, $args); //NOTE: Allows a theme to completely override the builtin WordPress.org API.
       
   283 
       
   284 	if ( ! $res ) {
       
   285 		$url = $http_url = 'http://api.wordpress.org/themes/info/1.0/';
       
   286 		if ( $ssl = wp_http_supports( array( 'ssl' ) ) )
       
   287 			$url = set_url_scheme( $url, 'https' );
       
   288 
       
   289 		$args = array(
       
   290 			'body' => array(
       
   291 				'action' => $action,
       
   292 				'request' => serialize( $args )
       
   293 			)
       
   294 		);
       
   295 		$request = wp_remote_post( $url, $args );
       
   296 
       
   297 		if ( $ssl && is_wp_error( $request ) ) {
       
   298 			trigger_error( __( 'An unexpected error occurred. Something may be wrong with WordPress.org or this server&#8217;s configuration. If you continue to have problems, please try the <a href="http://wordpress.org/support/">support forums</a>.' ) . ' ' . '(WordPress could not establish a secure connection to WordPress.org. Please contact your server administrator.)', headers_sent() || WP_DEBUG ? E_USER_WARNING : E_USER_NOTICE );
       
   299 			$request = wp_remote_post( $http_url, $args );
       
   300 		}
       
   301 
       
   302 		if ( is_wp_error($request) ) {
       
   303 			$res = new WP_Error('themes_api_failed', __( 'An unexpected error occurred. Something may be wrong with WordPress.org or this server&#8217;s configuration. If you continue to have problems, please try the <a href="http://wordpress.org/support/">support forums</a>.' ), $request->get_error_message() );
       
   304 		} else {
       
   305 			$res = maybe_unserialize( wp_remote_retrieve_body( $request ) );
       
   306 			if ( ! is_object( $res ) && ! is_array( $res ) )
       
   307 				$res = new WP_Error('themes_api_failed', __( 'An unexpected error occurred. Something may be wrong with WordPress.org or this server&#8217;s configuration. If you continue to have problems, please try the <a href="http://wordpress.org/support/">support forums</a>.' ), wp_remote_retrieve_body( $request ) );
       
   308 		}
       
   309 	}
       
   310 
       
   311 	return apply_filters('themes_api_result', $res, $action, $args);
       
   312 }