fetcher = new \WP_CLI\Fetchers\Theme; } protected function get_upgrader_class( $force ) { return $force ? '\\WP_CLI\\DestructiveThemeUpgrader' : 'Theme_Upgrader'; } /** * See the status of one or all themes. * * ## OPTIONS * * [] * : A particular theme to show the status for. */ function status( $args ) { parent::status( $args ); } /** * Search the wordpress.org theme repository. * * ## OPTIONS * * * : The string to search for. * * [--per-page=] * : Optional number of results to display. Defaults to 10. * * [--field=] * : Prints the value of a single field for each plugin. * * [--fields=] * : Ask for specific fields from the API. Defaults to name,slug,author,rating. Acceptable values: * * **name**: Theme Name * **slug**: Theme Slug * **version**: Current Version Number * **author**: Theme Author * **preview_url**: Theme Preview URL * **screenshot_url**: Theme Screenshot URL * **rating**: Theme Rating * **num_ratings**: Number of Theme Ratings * **homepage**: Theme Author's Homepage * **description**: Theme Description * * [--format=] * : Output list as table, CSV or JSON. Defaults to table. * * ## EXAMPLES * * wp theme search automattic --per-page=20 * * wp theme search automattic --fields=name,version,slug,rating,num_ratings,description */ public function search( $args, $assoc_args ) { parent::_search( $args, $assoc_args ); } protected function status_single( $args ) { $theme = $this->fetcher->get_check( $args[0] ); $status = $this->format_status( $this->get_status( $theme ), 'long' ); $version = $theme->get('Version'); if ( $this->has_update( $theme->get_stylesheet() ) ) $version .= ' (%gUpdate available%n)'; echo WP_CLI::colorize( \WP_CLI\Utils\mustache_render( 'theme-status.mustache', array( 'slug' => $theme->get_stylesheet(), 'status' => $status, 'version' => $version, 'name' => $theme->get('Name'), 'author' => $theme->get('Author'), ) ) ); } protected function get_all_items() { return $this->get_item_list(); } protected function get_status( $theme ) { return ( $this->is_active_theme( $theme ) ) ? 'active' : 'inactive'; } /** * Activate a theme. * * ## OPTIONS * * * : The theme to activate. */ public function activate( $args = array() ) { $theme = $this->fetcher->get_check( $args[0] ); switch_theme( $theme->get_template(), $theme->get_stylesheet() ); $name = $theme->get('Name'); if ( $this->is_active_theme( $theme ) ) { WP_CLI::success( "Switched to '$name' theme." ); } else { WP_CLI::error( "Could not switch to '$name' theme." ); } } private function is_active_theme( $theme ) { return $theme->get_stylesheet_directory() == get_stylesheet_directory(); } private function get_active_theme() { $stylesheetDirectory = get_stylesheet_directory(); foreach ( wp_get_themes( array( 'errors' => null ) ) as $theme ) { if ($theme->get_stylesheet_directory() == $stylesheetDirectory) { return $theme; } } return null; } /** * Get the path to a theme or to the theme directory. * * ## OPTIONS * * [] * : The theme to get the path to. Path includes "style.css" file. * If not set, will return the path to the themes directory. * * [--dir] * : If set, get the path to the closest parent directory, instead of the * theme's "style.css" file. * * ## EXAMPLES * * cd $(wp theme path) */ public function path( $args, $assoc_args ) { if ( empty( $args ) ) { $path = WP_CONTENT_DIR . '/themes'; } else { $theme = $this->fetcher->get_check( $args[0] ); $path = $theme->get_stylesheet_directory(); if ( !isset( $assoc_args['dir'] ) ) $path .= '/style.css'; } WP_CLI::line( $path ); } protected function install_from_repo( $slug, $assoc_args ) { $api = themes_api( 'theme_information', array( 'slug' => $slug ) ); if ( is_wp_error( $api ) ) { return $api; } if ( isset( $assoc_args['version'] ) ) { self::alter_api_response( $api, $assoc_args['version'] ); } if ( !isset( $assoc_args['force'] ) && wp_get_theme( $slug )->exists() ) { // We know this will fail, so avoid a needless download of the package. return new WP_Error( 'already_installed', 'Theme already installed.' ); } WP_CLI::log( sprintf( 'Installing %s (%s)', $api->name, $api->version ) ); if ( !isset( $assoc_args['version'] ) || 'dev' !== $assoc_args['version'] ) { WP_CLI::get_http_cache_manager()->whitelist_package( $api->download_link, $this->item_type, $api->slug, $api->version ); } $result = $this->get_upgrader( $assoc_args )->install( $api->download_link ); return $result; } protected function get_item_list() { $items = array(); foreach ( wp_get_themes() as $key => $theme ) { $file = $theme->get_stylesheet_directory(); $update_info = $this->get_update_info( $theme->get_stylesheet() ); $items[ $file ] = array( 'name' => $key, 'status' => $this->get_status( $theme ), 'update' => (bool) $update_info, 'update_version' => $update_info['new_version'], 'update_package' => $update_info['package'], 'version' => $theme->get('Version'), 'update_id' => $theme->get_stylesheet(), 'title' => $theme->get('Name'), 'description' => wordwrap( $theme->get('Description') ), ); } return $items; } protected function filter_item_list( $items, $args ) { $theme_files = array(); foreach ( $args as $arg ) { $theme_files[] = $this->fetcher->get_check( $arg )->get_stylesheet_directory(); } return \WP_CLI\Utils\pick_fields( $items, $theme_files ); } /** * Install a theme. * * ## OPTIONS * * ... * : A theme slug, the path to a local zip file, or URL to a remote zip file. * * [--version=] * : If set, get that particular version from wordpress.org, instead of the * stable version. * * [--force] * : If set, the command will overwrite any installed version of the theme, without prompting * for confirmation. * * [--activate] * : If set, the theme will be activated immediately after install. * * ## EXAMPLES * * # Install the latest version from wordpress.org and activate * wp theme install twentytwelve --activate * * # Install from a local zip file * wp theme install ../my-theme.zip * * # Install from a remote zip file * wp theme install http://s3.amazonaws.com/bucketname/my-theme.zip?AWSAccessKeyId=123&Expires=456&Signature=abcdef */ function install( $args, $assoc_args ) { $missedParentThemesBefore = array(); foreach ( wp_get_themes( array( 'errors' => true ) ) as $key => $theme ) { if ($parent = $theme->parent()) { $missedParentThemesBefore[] = $parent->name; } } parent::install( $args, $assoc_args ); $missedParentThemesAfter = array(); foreach ( wp_get_themes( array( 'errors' => true ) ) as $key => $theme ) { if ($parent = $theme->parent()) { $missedParentThemesAfter[] = $parent->name; } } // if there are some new themes with missed parents, install it now $missedParentThemes = array_diff( $missedParentThemesAfter, $missedParentThemesBefore ); foreach ( $missedParentThemes as $theme ) { $this->install( array( $theme ) ); } } /** * Get theme download link. * * ## OPTIONS * * * : The theme to get the download link. * * ## EXAMPLES * * wget $(wp theme get-download-link bbpress) * * @subcommand get-download-link */ public function get_download_link( $args, $assoc_args ) { $api = themes_api( 'theme_information', array( 'slug' => $args[0] ) ); if ( is_wp_error( $api ) ) { WP_CLI::line( '' ); } WP_CLI::line( $api->download_link ); } /** * Get a theme * * ## OPTIONS * * * : The theme to get. * * [--field=] * : Instead of returning the whole theme, returns the value of a single field. * * [--format=] * : Output list as table or JSON. Defaults to table. * * ## EXAMPLES * * wp theme get twentytwelve --format=json */ public function get( $args, $assoc_args ) { $theme = $this->fetcher->get_check( $args[0] ); // WP_Theme object employs magic getter, unfortunately $theme_vars = array( 'name', 'title', 'version', 'parent_theme', 'template_dir', 'stylesheet_dir', 'template', 'stylesheet', 'screenshot', 'description', 'author', 'tags', 'theme_root', 'theme_root_uri', ); $theme_obj = new stdClass; foreach( $theme_vars as $var ) { $theme_obj->$var = $theme->$var; } $theme_obj->description = wordwrap( $theme_obj->description ); $formatter = $this->get_formatter( $assoc_args ); $formatter->display_item( $theme_obj ); } /** * Update one or more themes. * * ## OPTIONS * * [...] * : One or more themes to update. * * [--all] * : If set, all themes that have updates will be updated. * * [--version=] * : If set, the theme will be updated to the latest development version, * regardless of what version is currently installed. * * [--dry-run] * : Preview which themes would be updated. * * ## EXAMPLES * * wp theme update twentyeleven twentytwelve * * wp theme update --all */ function update( $args, $assoc_args ) { parent::update_many( $args, $assoc_args ); } /** * Check if the theme is installed. * * ## OPTIONS * * * : The theme to check. * * ## EXAMPLES * * wp theme is-installed twentytwelve * * @subcommand is-installed */ function is_installed( $args, $assoc_args = array() ) { $theme = wp_get_theme( $args[0] ); if ( $theme->exists() ) { exit( 0 ); } else { exit( 1 ); } } /** * Delete a theme. * * ## OPTIONS * * ... * : One or more themes to delete. * * ## EXAMPLES * * wp theme delete twentyeleven */ function delete( $args ) { foreach ( $this->fetcher->get_many( $args ) as $theme ) { $theme_slug = $theme->get_stylesheet(); if ( $this->is_active_theme( $theme ) ) { WP_CLI::error( "Can't delete the currently active theme: $theme_slug" ); continue; } // check, that this theme has not active children if ( !is_null( $activeTheme = $this->get_active_theme() ) && ( $activeThemeParent = $activeTheme->parent() ) ) { if ($activeThemeParent->get_stylesheet() == $theme->get_stylesheet()) { WP_CLI::error( "Can't delete parent of the currently active theme: {$activeTheme->get_stylesheet()}" ); continue; } } $this->_check_content_direcory_permissions(); // check, that theme files is writeable $path = $theme->get_stylesheet_directory(); if ( !is_writable( $path ) ) { \WP_CLI::error( "Unable to remove theme files: $path", 40008 ); } $r = delete_theme( $theme_slug ); if ( is_wp_error( $r ) ) { WP_CLI::error( WP_CLI::error_to_string( $r ) ); } else { WP_CLI::success( "Deleted '$theme_slug' theme." ); } } } /** * Get a list of themes. * * ## OPTIONS * * [--=] * : Filter results based on the value of a field. * * [--field=] * : Prints the value of a single field for each theme. * * [--fields=] * : Limit the output to specific object fields. Defaults to name,status,update,version. * * [--format=] * : Output list as table, CSV or JSON. Defaults to table. * * [--check-updates=] * : Check updates for instance: * * **true**: check updates for instance. * **false**: do not check updates for instance. * * ## EXAMPLES * * wp theme list --status=inactive --format=csv * * @subcommand list */ function _list( $_, $assoc_args ) { parent::_list( $_, $assoc_args ); } } WP_CLI::add_command( 'theme', 'Theme_Command' );