@@ -185,8 +185,17 @@ private function show_legend( $items ) {
185185 }
186186
187187 public function install ( $ args , $ assoc_args ) {
188- $ successes = 0 ;
189- $ errors = 0 ;
188+ $ successes = 0 ;
189+ $ errors = 0 ;
190+ $ custom_slug = Utils \get_flag_value ( $ assoc_args , 'slug ' , false );
191+ if ( $ custom_slug ) {
192+ $ custom_slug = sanitize_file_name ( $ custom_slug );
193+ }
194+
195+ if ( $ custom_slug && count ( $ args ) > 1 ) {
196+ WP_CLI ::error ( 'The --slug option can only be used when installing a single item. ' );
197+ }
198+
190199 foreach ( $ args as $ slug ) {
191200
192201 if ( empty ( $ slug ) ) {
@@ -267,10 +276,33 @@ public function install( $args, $assoc_args ) {
267276 $ file_upgrader = $ this ->get_upgrader ( $ assoc_args );
268277
269278 $ filter = false ;
270- // If a GitHub URL, do some guessing as to the correct plugin/theme directory.
271- if ( $ is_remote && 'github.com ' === Utils \parse_url ( $ slug , PHP_URL_HOST )
279+ if ( $ custom_slug ) {
280+ // If --slug is specified, rename the extracted directory to the provided slug.
281+ $ filter = function ( $ source ) use ( $ custom_slug ) {
282+ /**
283+ * @var \WP_Filesystem_Base $wp_filesystem
284+ */
285+ global $ wp_filesystem ;
286+
287+ $ source_dir = Utils \basename ( $ source ); // `$source` is trailing-slashed path to the unzipped archive directory.
288+ if ( $ source_dir === $ custom_slug ) {
289+ return $ source ;
290+ }
291+ $ custom_slug = sanitize_file_name ( $ custom_slug );
292+ $ new_path = substr_replace ( $ source , $ custom_slug , (int ) strrpos ( $ source , $ source_dir ), strlen ( $ source_dir ) );
293+
294+ if ( $ wp_filesystem ->move ( $ source , $ new_path ) ) {
295+ WP_CLI ::log ( sprintf ( "Renamed '%s' to '%s'. " , $ source_dir , $ custom_slug ) );
296+ return $ new_path ;
297+ }
298+
299+ return new WP_Error ( 'wpcli_install_slug ' , "Couldn't rename to ' {$ custom_slug }'. " );
300+ };
301+ add_filter ( 'upgrader_source_selection ' , $ filter , 10 );
302+ } elseif ( $ is_remote && 'github.com ' === Utils \parse_url ( $ slug , PHP_URL_HOST )
272303 // Don't attempt to rename ZIPs uploaded to the releases page or coming from a raw source.
273304 && ! preg_match ( '#github\.com/[^/]+/[^/]+/(?:releases/download|raw)/# ' , $ slug ) ) {
305+ // If a GitHub URL, do some guessing as to the correct plugin/theme directory.
274306
275307 $ filter = function ( $ source ) use ( $ slug ) {
276308 /**
0 commit comments