From a99acb3cfdcd95fb73a92035538fac4070857e19 Mon Sep 17 00:00:00 2001
From: Ryan Boren
Date: Wed, 11 Feb 2009 23:10:11 +0000
Subject: [PATCH] Rough first cut of theme browser/installer. Props DD32. see
#8652
git-svn-id: https://develop.svn.wordpress.org/trunk@10553 602fd350-edb4-49c9-b593-d223f7449a82
---
wp-admin/includes/schema.php | 14 +
wp-admin/includes/theme-install.php | 895 ++++++++++++++++++++++++++++
wp-admin/includes/upgrade.php | 15 +
wp-admin/menu.php | 1 +
wp-admin/theme-install.php | 77 +++
wp-includes/version.php | 2 +-
6 files changed, 1003 insertions(+), 1 deletion(-)
create mode 100644 wp-admin/includes/theme-install.php
create mode 100644 wp-admin/theme-install.php
diff --git a/wp-admin/includes/schema.php b/wp-admin/includes/schema.php
index 6f300baf5f..53f64488f2 100644
--- a/wp-admin/includes/schema.php
+++ b/wp-admin/includes/schema.php
@@ -327,6 +327,7 @@ function populate_roles() {
populate_roles_250();
populate_roles_260();
populate_roles_270();
+ populate_roles_280();
}
/**
@@ -530,4 +531,17 @@ function populate_roles_270() {
}
}
+/**
+ * Create and modify WordPress roles for WordPress 2.8.
+ *
+ * @since 2.8.0
+ */
+function populate_roles_280() {
+ $role =& get_role( 'administrator' );
+
+ if ( !empty( $role ) ) {
+ $role->add_cap( 'install_themes' );
+ }
+}
+
?>
diff --git a/wp-admin/includes/theme-install.php b/wp-admin/includes/theme-install.php
new file mode 100644
index 0000000000..52c4ab7881
--- /dev/null
+++ b/wp-admin/includes/theme-install.php
@@ -0,0 +1,895 @@
+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) ) {
+ $res = new WP_Error('themes_api_failed', __('An Unexpected HTTP Error occured during the API request.
Try again'), $request->get_error_message() );
+ } else {
+ $res = unserialize($request['body']);
+ if ( ! $res )
+ $res = new WP_Error('themes_api_failed', __('An unknown error occured'), $request['body']);
+ }
+ }
+
+ return apply_filters('themes_api_result', $res, $action, $args);
+}
+
+/**
+ * Retrieve popular WordPress theme tags.
+ *
+ * @since 2.8.0
+ *
+ * @param array $args
+ * @return array
+ */
+function install_themes_popular_tags( $args = array() ) {
+ if ( !$cache = get_option('wporg_theme_popular_tags') )
+ add_option('wporg_theme_popular_tags', array(), '', 'no'); ///No autoload.
+
+ if ( $cache && $cache->timeout + 3 * 60 * 60 > time() )
+ return $cache->cached;
+
+ $tags = themes_api('hot_tags', $args);
+
+ if ( is_wp_error($tags) )
+ return $tags;
+
+ $cache = (object) array('timeout' => time(), 'cached' => $tags);
+
+ update_option('wporg_theme_popular_tags', $cache);
+
+ return $tags;
+}
+
+add_action('install_themes_search', 'install_theme_search', 10, 1);
+/**
+ * Display theme search results and display as tag cloud.
+ *
+ * @since 2.8.0
+ *
+ * @param string $page
+ */
+function install_theme_search($page) {
+ $type = isset($_REQUEST['type']) ? stripslashes( $_REQUEST['type'] ) : '';
+ $term = isset($_REQUEST['s']) ? stripslashes( $_REQUEST['s'] ) : '';
+
+ $args = array();
+
+ switch( $type ){
+ case 'tag':
+ $args['tag'] = sanitize_title_with_dashes($term);
+ break;
+ case 'term':
+ $args['search'] = $term;
+ break;
+ case 'author':
+ $args['author'] = $term;
+ break;
+ }
+
+ $args['page'] = $page;
+
+ $api = themes_api('query_themes', $args);
+
+ if ( is_wp_error($api) )
+ wp_die($api);
+
+ add_action('install_themes_table_header', 'install_theme_search_form');
+
+ display_themes($api->themes, $api->info['page'], $api->info['pages']);
+}
+
+add_action('install_themes_dashboard', 'install_themes_dashboard');
+function install_themes_dashboard() {
+ ?>
+
WordPress Theme Directory or upload a theme in .zip format via this page.') ?>
+
+
+ ' . __('[need help?]') . '') ?>
+
+
+ Term: Searches theme names and descriptions for the specified term') ?>
+ Tag: Searches for themes tagged as such') ?>
+ Author: Searches for themes created by the Author, or which the Author contributed to.') ?>
+
+
+
+
+
+
+
+
+ clean_url( admin_url('theme-install.php?tab=search&type=tag&s=' . urlencode($tag['name'])) ),
+ 'name' => $tag['name'],
+ 'id' => sanitize_title_with_dashes($tag['name']),
+ 'count' => $tag['count'] );
+ echo '';
+ echo wp_generate_tag_cloud($tags, array( 'single_text' => __('%d theme'), 'multiple_text' => __('%d themes') ) );
+ echo '
';
+}
+
+/**
+ * Display search form for searching themes.
+ *
+ * @since 2.8.0
+ */
+function install_theme_search_form(){
+ $type = isset($_REQUEST['type']) ? stripslashes( $_REQUEST['type'] ) : '';
+ $term = isset($_REQUEST['s']) ? stripslashes( $_REQUEST['s'] ) : '';
+
+ ?> 'featured', 'page' => $page);
+ $api = themes_api('query_themes', $args);
+ if ( is_wp_error($api) )
+ wp_die($api);
+ display_themes($api->themes, $api->info['page'], $api->info['pages']);
+}
+
+add_action('install_thems_popular', 'install_themes_popular', 10, 1);
+/**
+ * Display popular themes.
+ *
+ * @since 2.8.0
+ *
+ * @param string $page
+ */
+function install_themes_popular($page = 1) {
+ $args = array('browse' => 'popular', 'page' => $page);
+ $api = themes_api('query_themes', $args);
+ display_themes($api->themes, $api->info['page'], $api->info['pages']);
+}
+
+add_action('install_themes_new', 'install_themes_new', 10, 1);
+/**
+ * Display new themes/
+ *
+ * @since 2.8.0
+ *
+ * @param string $page
+ */
+function install_themes_new($page = 1) {
+ $args = array('browse' => 'new', 'page' => $page);
+ $api = themes_api('query_themes', $args);
+ if ( is_wp_error($api) )
+ wp_die($api);
+ display_themes($api->themes, $api->info['page'], $api->info['pages']);
+}
+
+add_action('install_themes_updated', 'install_themes_updated', 10, 1);
+/**
+ * Display recently updated themes.
+ *
+ * @since 2.8.0
+ *
+ * @param string $page
+ */
+function install_themes_updated($page = 1) {
+ $args = array('browse' => 'updated', 'page' => $page);
+ $api = themes_api('query_themes', $args);
+ display_themes($api->themes, $api->info['page'], $api->info['pages']);
+}
+
+/**
+ * Display theme content based on theme list.
+ *
+ * @since 2.8.0
+ *
+ * @param array $themes List of themes.
+ * @param string $page
+ * @param int $totalpages Number of pages.
+ */
+function display_themes($themes, $page = 1, $totalpages = 1) {
+ $type = isset($_REQUEST['type']) ? stripslashes( $_REQUEST['type'] ) : '';
+ $term = isset($_REQUEST['s']) ? stripslashes( $_REQUEST['s'] ) : '';
+
+ $themes_allowedtags = array('a' => array('href' => array(),'title' => array(), 'target' => array()),
+ 'abbr' => array('title' => array()),'acronym' => array('title' => array()),
+ 'code' => array(), 'pre' => array(), 'em' => array(),'strong' => array());
+
+?>
+
+
+
+
+ add_query_arg('paged', '%#%', $url),
+ 'format' => '',
+ 'prev_text' => __('«'),
+ 'next_text' => __('»'),
+ 'total' => $totalpages,
+ 'current' => $page
+ ));
+
+ if ( $page_links )
+ echo "\t\t
$page_links
";
+?>
+
+
+
+
+
+ |
+ |
+ |
+ |
+ |
+
+
+
+
+
+ |
+ |
+ |
+ |
+ |
+
+
+
+
+ ', __('No themes match your request.'), ' | ';
+
+ foreach( (array) $themes as $theme ){
+ if ( is_object($theme) )
+ $theme = (array) $theme;
+
+ $title = wp_kses($theme['name'], $themes_allowedtags);
+ $description = wp_kses($theme['description'], $themes_allowedtags);
+ $version = wp_kses($theme['version'], $themes_allowedtags);
+
+ $name = strip_tags($title . ' ' . $version);
+
+ $author = $theme['author'];
+ if( ! empty($theme['author']) )
+ $author = ' ' . sprintf( __('By %s'), $author ) . '.';
+
+ $author = wp_kses($author, $themes_allowedtags);
+
+ if( isset($theme['homepage']) )
+ $title = '' . $title . '';
+
+ $action_links = array();
+ $action_links[] = '' . __('Install') . '';
+
+ $action_links = apply_filters('theme_install_action_links', $action_links, $theme);
+ ?>
+
+ |
+ |
+
+
+ |
+ |
+ |
+
+
+
+
+
+
+ $page_links
"; ?>
+
+
+
+ stripslashes( $_REQUEST['theme'] ) ));
+
+ if ( is_wp_error($api) )
+ wp_die($api);
+
+ $themes_allowedtags = array('a' => array('href' => array(), 'title' => array(), 'target' => array()),
+ 'abbr' => array('title' => array()), 'acronym' => array('title' => array()),
+ 'code' => array(), 'pre' => array(), 'em' => array(), 'strong' => array(),
+ 'div' => array(), 'p' => array(), 'ul' => array(), 'ol' => array(), 'li' => array(),
+ 'h1' => array(), 'h2' => array(), 'h3' => array(), 'h4' => array(), 'h5' => array(), 'h6' => array(),
+ 'img' => array('src' => array(), 'class' => array(), 'alt' => array()));
+ //Sanitize HTML
+ foreach ( (array)$api->sections as $section_name => $content )
+ $api->sections[$section_name] = wp_kses($content, $themes_allowedtags);
+ foreach ( array('version', 'author', 'requires', 'tested', 'homepage', 'downloaded', 'slug') as $key )
+ $api->$key = wp_kses($api->$key, $themes_allowedtags);
+
+ $section = isset($_REQUEST['section']) ? stripslashes( $_REQUEST['section'] ) : 'description'; //Default to the Description tab, Do not translate, API returns English.
+ if( empty($section) || ! isset($api->sections[ $section ]) )
+ $section = array_shift( $section_titles = array_keys((array)$api->sections) );
+
+ iframe_header( __('Theme Install') );
+ echo "\n";
+ ?>
+
+ download_link) ) : ?>
+
+ response as $file => $theme ) {
+ if ( $theme->slug === $api->slug ) {
+ $type = 'update_available';
+ $update_file = $file;
+ break;
+ }
+ }
+ /*if ( 'install' == $type && is_dir( WP_PLUGIN_DIR . '/' . $api->slug ) ) {
+ $installed_theme = get_themes('/' . $api->slug);
+ if ( ! empty($installed_theme) ) {
+ $key = array_shift( $key = array_keys($installed_theme) ); //Use the first theme regardless of the name, Could have issues for multiple-themes in one directory if they share different version numbers
+ if ( version_compare($api->version, $installed_theme[ $key ]['Version'], '>') ){
+ $type = 'latest_installed';
+ } elseif ( version_compare($api->version, $installed_theme[ $key ]['Version'], '<') ) {
+ $type = 'newer_installed';
+ $newer_version = $installed_theme[ $key ]['Version'];
+ } else {
+ //If the above update check failed, Then that probably means that the update checker has out-of-date information, force a refresh
+ delete_option('update_themes');
+ $update_file = $api->slug . '/' . $key; //This code branch only deals with a theme which is in a folder the same name as its slug, Doesnt support themes which have 'non-standard' names
+ $type = 'update_available';
+ }
+ }
+ }*/
+
+ switch ( $type ) :
+ default:
+ case 'install':
+ if ( current_user_can('install_themes') ) :
+ ?>
+
+
+
+
+version) ) : ?>
+ - version ?>
+author) ) : ?>
+ - author, '_blank') ?>
+last_updated) ) : ?>
+ - last_updated)) ) ?>
+requires) ) : ?>
+ - requires) ?>
+tested) ) : ?>
+ - tested ?>
+downloaded) ) : ?>
+ - downloaded), number_format_i18n($api->downloaded)) ?>
+slug) ) : ?>
+
+homepage) ) : ?>
+
+
+
+
+
+
num_ratings), number_format_i18n($api->num_ratings)); ?>
+
+
+ tested, '>') )
+ echo '
' . __('Warning: This theme has not been tested with your current version of WordPress.') . '
';
+ else if ( version_compare($GLOBALS['wp_version'], $api->requires, '<') )
+ echo '
' . __('Warning: This theme has not been marked as compatible with your version of WordPress.') . '
';
+ foreach ( (array)$api->sections as $section_name => $content ) {
+ $title = $section_name;
+ $title[0] = strtoupper($title[0]);
+ $title = str_replace('_', ' ', $title);
+
+ $content = links_add_base_url($content, 'http://wordpress.org/extend/themes/' . $api->slug . '/');
+ $content = links_add_target($content, '_blank');
+
+ $san_title = attribute_escape(sanitize_title_with_dashes($title));
+
+ $display = ( $section_name == $section ) ? 'block' : 'none';
+
+ echo "\t
\n";
+ echo "\t\t";
+ echo $content;
+ echo "\t
\n";
+ }
+ echo "
\n";
+
+ iframe_footer();
+ exit;
+}
+
+
+add_action('install_themes_upload', 'upload_theme');
+function upload_theme() {
+
+ if ( ! ( ( $uploads = wp_upload_dir() ) && false === $uploads['error'] ) )
+ wp_die($uploads['error']);
+
+ if ( !empty($_FILES) )
+ $filename = $_FILES['themezip']['name'];
+ else if ( isset($_GET['package']) )
+ $filename = $_GET['package'];
+
+ check_admin_referer('theme-upload');
+
+ echo '';
+ echo '
', sprintf( __('Installing Theme from file: %s'), basename($filename) ), '
';
+
+ //Handle a newly uploaded file, Else assume it was
+ if ( !empty($_FILES) ) {
+ $filename = wp_unique_filename( $uploads['basedir'], $filename );
+ $local_file = $uploads['basedir'] . '/' . $filename;
+
+ // Move the file to the uploads dir
+ if ( false === @ move_uploaded_file( $_FILES['themezip']['tmp_name'], $local_file) )
+ wp_die( sprintf( __('The uploaded file could not be moved to %s.' ), $uploads['path']));
+ } else {
+ $local_file = $uploads['basedir'] . '/' . $filename;
+ }
+
+ do_theme_install_local_package($local_file, $filename);
+ echo '';
+}
+
+add_action('install_themes_install', 'install_theme');
+
+/**
+ * Display theme link and execute install.
+ *
+ * @since 2.8.0
+ */
+function install_theme() {
+
+ $theme = isset($_REQUEST['theme']) ? stripslashes( $_REQUEST['theme'] ) : '';
+
+ check_admin_referer('install-theme_' . $theme);
+ $api = themes_api('theme_information', array('slug' => $theme, 'fields' => array('sections' => false) ) ); //Save on a bit of bandwidth.
+
+ if ( is_wp_error($api) )
+ wp_die($api);
+
+ echo '';
+ echo '
', sprintf( __('Installing Theme: %s'), $api->name . ' ' . $api->version ), '
';
+
+ do_theme_install($api->download_link, $api);
+ echo '';
+
+}
+
+/**
+ * Retrieve theme and install.
+ *
+ * @since 2.8.0
+ *
+ * @param string $download_url Download URL.
+ * @param object $theme_information Optional. Theme information
+ */
+function do_theme_install($download_url, $theme_information = null) {
+ global $wp_filesystem;
+
+ if ( empty($download_url) ) {
+ show_message( __('No theme Specified') );
+ return;
+ }
+
+ $theme = isset($_REQUEST['theme']) ? stripslashes( $_REQUEST['theme'] ) : '';
+
+ $url = 'theme-install.php?tab=install';
+ $url = add_query_arg(array('theme' => $theme, 'theme_name' => stripslashes( $_REQUEST['theme_name'] ), 'download_url' => stripslashes( $_REQUEST['download_url'] ) ), $url);
+
+ $url = wp_nonce_url($url, 'install-theme_' . $theme);
+ if ( false === ($credentials = request_filesystem_credentials($url)) )
+ return;
+
+ if ( ! WP_Filesystem($credentials) ) {
+ request_filesystem_credentials($url, '', true); //Failed to connect, Error and request again
+ return;
+ }
+
+ if ( $wp_filesystem->errors->get_error_code() ) {
+ foreach ( $wp_filesystem->errors->get_error_messages() as $message )
+ show_message($message);
+ return;
+ }
+
+ $result = wp_install_theme( $download_url, 'show_message' );
+
+ if ( is_wp_error($result) ) {
+ show_message($result);
+ show_message( __('Installation Failed') );
+ } else {
+ show_message( sprintf(__('Successfully installed the theme %s %s.'), $theme_information->name, $theme_information->version) );
+ $theme_file = $result;
+
+ $install_actions = apply_filters('install_theme_complete_actions', array(
+ //'activate_theme' => '' . __('Activate Theme') . '',
+ 'themes_page' => '' . __('Return to Themes page') . ''
+ ), $theme_information, $theme_file);
+ if ( ! empty($install_actions) )
+ show_message('' . __('Actions:') . ' ' . implode(' | ', (array)$install_actions));
+ }
+}
+
+/**
+ * Install a theme from a local file.
+ *
+ * @since 2.8.0
+ *
+ * @param string $package Local Theme zip
+ * @param string $filename Optional. Original filename
+ * @param object $theme_information Optional. Theme information
+ */
+function do_theme_install_local_package($package, $filename = '') {
+ global $wp_filesystem;
+
+ if ( empty($package) ) {
+ show_message( __('No theme Specified') );
+ return;
+ }
+
+ if ( empty($filename) )
+ $filename = basename($package);
+
+ $url = 'theme-install.php?tab=upload';
+ $url = add_query_arg(array('package' => $filename), $url);
+
+ $url = wp_nonce_url($url, 'theme-upload');
+ if ( false === ($credentials = request_filesystem_credentials($url)) )
+ return;
+
+ if ( ! WP_Filesystem($credentials) ) {
+ request_filesystem_credentials($url, '', true); //Failed to connect, Error and request again
+ return;
+ }
+
+ if ( $wp_filesystem->errors->get_error_code() ) {
+ foreach ( $wp_filesystem->errors->get_error_messages() as $message )
+ show_message($message);
+ return;
+ }
+
+ $result = wp_install_theme_local_package( $package, 'show_message' );
+
+ if ( is_wp_error($result) ) {
+ show_message($result);
+ show_message( __('Installation Failed') );
+ } else {
+ show_message( __('Successfully installed the theme.') );
+ $theme_file = $result;
+
+ $install_actions = apply_filters('install_theme_complete_actions', array(
+ //'activate_theme' => '' . __('Activate Theme') . '',
+ 'themes_page' => '' . __('Return to Themes page') . ''
+ ), array(), $theme_file);
+ if ( ! empty($install_actions) )
+ show_message('' . __('Actions:') . ' ' . implode(' | ', (array)$install_actions));
+ }
+}
+
+/**
+ * Install theme.
+ *
+ * @since 2.8.0
+ *
+ * @param string $package
+ * @param string $feedback Optional.
+ * @return mixed.
+ */
+function wp_install_theme($package, $feedback = '') {
+ global $wp_filesystem;
+
+ if ( !empty($feedback) )
+ add_filter('install_feedback', $feedback);
+
+ // Is a filesystem accessor setup?
+ if ( ! $wp_filesystem || ! is_object($wp_filesystem) )
+ WP_Filesystem();
+
+ if ( ! is_object($wp_filesystem) )
+ return new WP_Error('fs_unavailable', __('Could not access filesystem.'));
+
+ if ( $wp_filesystem->errors->get_error_code() )
+ return new WP_Error('fs_error', __('Filesystem error'), $wp_filesystem->errors);
+
+ //Get the base theme 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.'));
+
+ //And the same for the Content directory.
+ $content_dir = $wp_filesystem->wp_content_dir();
+ if( empty($content_dir) )
+ return new WP_Error('fs_no_content_dir', __('Unable to locate WordPress Content directory (wp-content).'));
+
+ $themes_dir = trailingslashit( $themes_dir );
+ $content_dir = trailingslashit( $content_dir );
+
+ if ( empty($package) )
+ return new WP_Error('no_package', __('Install package not available.'));
+
+ // Download the package
+ apply_filters('install_feedback', sprintf(__('Downloading theme package from %s'), $package));
+ $download_file = download_url($package);
+
+ if ( is_wp_error($download_file) )
+ return new WP_Error('download_failed', __('Download failed.'), $download_file->get_error_message());
+
+ $working_dir = $content_dir . 'upgrade/' . basename($package, '.zip');
+
+ // Clean up working directory
+ if ( $wp_filesystem->is_dir($working_dir) )
+ $wp_filesystem->delete($working_dir, true);
+
+ apply_filters('install_feedback', __('Unpacking the theme package'));
+ // Unzip package to working directory
+ $result = unzip_file($download_file, $working_dir);
+
+ // Once extracted, delete the package
+ @unlink($download_file);
+
+ if ( is_wp_error($result) ) {
+ $wp_filesystem->delete($working_dir, true);
+ return $result;
+ }
+
+ //Get a list of the directories in the working directory before we delete it, We need to know the new folder for the theme
+ $filelist = array_keys( $wp_filesystem->dirlist($working_dir) );
+
+ if( $wp_filesystem->exists( $themes_dir . $filelist[0] ) ) {
+ $wp_filesystem->delete($working_dir, true);
+ return new WP_Error('install_folder_exists', __('Folder already exists.'), $filelist[0] );
+ }
+
+ apply_filters('install_feedback', __('Installing the theme'));
+ // Copy new version of theme into place.
+ $result = copy_dir($working_dir, $themes_dir);
+ if ( is_wp_error($result) ) {
+ $wp_filesystem->delete($working_dir, true);
+ return $result;
+ }
+
+ //Get a list of the directories in the working directory before we delete it, We need to know the new folder for the theme
+ $filelist = array_keys( $wp_filesystem->dirlist($working_dir) );
+
+ // Remove working directory
+ $wp_filesystem->delete($working_dir, true);
+
+ if( empty($filelist) )
+ return false; //We couldnt find any files in the working dir, therefor no theme installed? Failsafe backup.
+
+
+//TODO: TODO: TODO
+ $stylesheet = $filelist[0];
+// $theme = get_themes('/' . $folder); //Ensure to pass with leading slash //TODO: TODO: TODO
+// $themefiles = array_keys($theme); //Assume the requested theme is the first in the list
+
+ //Return the theme files name.
+ return $stylesheet; //$folder . '/' . $themefiles[0];
+}
+
+/**
+ * Install theme from local package
+ *
+ * @since 2.8.0
+ *
+ * @param string $package
+ * @param string $feedback Optional.
+ * @return mixed.
+ */
+function wp_install_theme_local_package($package, $feedback = '') {
+ global $wp_filesystem;
+
+ if ( !empty($feedback) )
+ add_filter('install_feedback', $feedback);
+
+ // Is a filesystem accessor setup?
+ if ( ! $wp_filesystem || ! is_object($wp_filesystem) )
+ WP_Filesystem();
+
+ if ( ! is_object($wp_filesystem) )
+ return new WP_Error('fs_unavailable', __('Could not access filesystem.'));
+
+ if ( $wp_filesystem->errors->get_error_code() )
+ return new WP_Error('fs_error', __('Filesystem error'), $wp_filesystem->errors);
+
+ //Get the base theme 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.'));
+
+ //And the same for the Content directory.
+ $content_dir = $wp_filesystem->wp_content_dir();
+ if( empty($content_dir) )
+ return new WP_Error('fs_no_content_dir', __('Unable to locate WordPress Content directory (wp-content).'));
+
+ $themes_dir = trailingslashit( $themes_dir );
+ $content_dir = trailingslashit( $content_dir );
+
+ if ( empty($package) )
+ return new WP_Error('no_package', __('Install package not available.'));
+
+ $working_dir = $content_dir . 'upgrade/' . basename($package, '.zip');
+
+
+ // Clean up working directory
+ if ( $wp_filesystem->is_dir($working_dir) )
+ $wp_filesystem->delete($working_dir, true);
+
+ apply_filters('install_feedback', __('Unpacking the theme package'));
+ // Unzip package to working directory
+ $result = unzip_file($package, $working_dir);
+
+ // Once extracted, delete the package
+ unlink($package);
+
+ if ( is_wp_error($result) ) {
+ $wp_filesystem->delete($working_dir, true);
+ return $result;
+ }
+
+ //Get a list of the directories in the working directory before we delete it, We need to know the new folder for the theme
+ $filelist = array_keys( $wp_filesystem->dirlist($working_dir) );
+
+ if( $wp_filesystem->exists( $themes_dir . $filelist[0] ) ) {
+ $wp_filesystem->delete($working_dir, true);
+ return new WP_Error('install_folder_exists', __('Folder already exists.'), $filelist[0] );
+ }
+
+ apply_filters('install_feedback', __('Installing the theme'));
+ // Copy new version of theme into place.
+ $result = copy_dir($working_dir, $themes_dir);
+ if ( is_wp_error($result) ) {
+ $wp_filesystem->delete($working_dir, true);
+ return $result;
+ }
+
+ //Get a list of the directories in the working directory before we delete it, We need to know the new folder for the theme
+ $filelist = array_keys( $wp_filesystem->dirlist($working_dir) );
+
+ // Remove working directory
+ $wp_filesystem->delete($working_dir, true);
+
+ if( empty($filelist) )
+ return false; //We couldnt find any files in the working dir, therefor no theme installed? Failsafe backup.
+
+//TODO TODO TODO
+ $stylesheet = $filelist[0];
+// $theme = get_themes('/' . $folder); //Ensure to pass with leading slash
+// $themefiles = array_keys($theme); //Assume the requested theme is the first in the list
+
+ //Return the theme files name.
+ return $stylsheet; //$folder . '/' . $themefiles[0];
+}
diff --git a/wp-admin/includes/upgrade.php b/wp-admin/includes/upgrade.php
index 922ac59642..7042f2c2ae 100644
--- a/wp-admin/includes/upgrade.php
+++ b/wp-admin/includes/upgrade.php
@@ -276,6 +276,9 @@ function upgrade_all() {
if ( $wp_current_db_version < 8989 )
upgrade_270();
+ if ( $wp_current_db_version < 10360 )
+ upgrade_280();
+
maybe_disable_automattic_widgets();
update_option('db_version', 'db_upgraded');
@@ -906,6 +909,18 @@ function upgrade_270() {
$wpdb->query( "UPDATE $wpdb->posts SET post_date = post_modified WHERE post_date = '0000-00-00 00:00:00'" );
}
+/**
+ * Execute changes made in WordPress 2.8.
+ *
+ * @since 2.8.0
+ */
+function upgrade_280() {
+ global $wp_current_db_version;
+
+ if ( $wp_current_db_version < 10360 )
+ populate_roles_280();
+}
+
// The functions we use to actually do stuff
diff --git a/wp-admin/menu.php b/wp-admin/menu.php
index 293d18a2f2..20afafcdcd 100644
--- a/wp-admin/menu.php
+++ b/wp-admin/menu.php
@@ -57,6 +57,7 @@ $menu[39] = array( '', 'read', '', '', 'wp-menu-separator' );
$menu[40] = array( __('Appearance'), 'switch_themes', 'themes.php', '', 'menu-top', 'menu-appearance', 'div' );
$submenu['themes.php'][5] = array(__('Themes'), 'switch_themes', 'themes.php');
$submenu['themes.php'][10] = array(__('Editor'), 'edit_themes', 'theme-editor.php');
+ $submenu['themes.php'][15] = array(__('Add New Themes'), 'install_themes', 'theme-install.php');
$update_plugins = get_transient( 'update_plugins' );
$update_count = 0;
diff --git a/wp-admin/theme-install.php b/wp-admin/theme-install.php
new file mode 100644
index 0000000000..a3229c7370
--- /dev/null
+++ b/wp-admin/theme-install.php
@@ -0,0 +1,77 @@
+
+
+
+
+
+
+ $text ) {
+ $sep = ( end($tabs) != $text ) ? ' | ' : '';
+ $class = ( $action == $tab ) ? ' class="current"' : '';
+ $href = admin_url('theme-install.php?tab='. $action);
+ echo "\t\t- $text$sep
\n";
+}
+?>
+
+
+
+
+