@@ -389,8 +389,15 @@ public function delete( $args, $assoc_args ) {
389389 *
390390 * ## OPTIONS
391391 *
392- * --slug=<slug>
392+ * [ --slug=<slug>]
393393 * : Path for the new site. Subdomain on subdomain installs, directory on subdirectory installs.
394+ * Required if --url is not provided.
395+ *
396+ * [--url=<url>]
397+ * : Full URL for the new site. Use this to specify a custom domain instead of the auto-generated one.
398+ * For subdomain installs, this allows you to use a different base domain (e.g., 'http://site.example.com' instead of 'http://site.main.example.com').
399+ * For subdirectory installs, this allows you to use a different path.
400+ * If provided, --slug is optional and will be derived from the URL.
394401 *
395402 * [--title=<title>]
396403 * : Title of the new site. Default: prettified slug.
@@ -409,8 +416,17 @@ public function delete( $args, $assoc_args ) {
409416 *
410417 * ## EXAMPLES
411418 *
419+ * # Create a site with auto-generated domain
412420 * $ wp site create --slug=example
413421 * Success: Site 3 created: http://www.example.com/example/
422+ *
423+ * # Create a site with a custom domain (subdomain multisite)
424+ * $ wp site create --url=http://site.example.com
425+ * Success: Site 4 created: http://site.example.com/
426+ *
427+ * # Create a site with a custom subdirectory (subdirectory multisite)
428+ * $ wp site create --url=http://example.com/custom/path/
429+ * Success: Site 5 created: http://example.com/custom/path/
414430 */
415431 public function create ( $ args , $ assoc_args ) {
416432 if ( ! is_multisite () ) {
@@ -419,7 +435,56 @@ public function create( $args, $assoc_args ) {
419435
420436 global $ wpdb , $ current_site ;
421437
422- $ base = $ assoc_args ['slug ' ];
438+ // Check if either slug or url is provided
439+ $ has_slug = isset ( $ assoc_args ['slug ' ] );
440+ $ has_url = isset ( $ assoc_args ['url ' ] );
441+
442+ if ( ! $ has_slug && ! $ has_url ) {
443+ WP_CLI ::error ( 'Either --slug or --url must be provided. ' );
444+ }
445+
446+ // If URL is provided, parse it to get domain and path
447+ $ custom_domain = null ;
448+ $ custom_path = null ;
449+ $ base = null ;
450+
451+ if ( $ has_url ) {
452+ $ parsed_url = parse_url ( $ assoc_args ['url ' ] );
453+ if ( ! isset ( $ parsed_url ['host ' ] ) ) {
454+ WP_CLI ::error ( 'Invalid URL format. Please provide a valid URL (e.g., http://site.example.com). ' );
455+ }
456+
457+ $ custom_domain = $ parsed_url ['host ' ];
458+ $ custom_path = isset ( $ parsed_url ['path ' ] ) ? $ parsed_url ['path ' ] : '/ ' ;
459+
460+ // Ensure path ends with /
461+ if ( '/ ' !== substr ( $ custom_path , -1 ) ) {
462+ $ custom_path .= '/ ' ;
463+ }
464+
465+ // Derive base/slug from the URL if not explicitly provided
466+ if ( ! $ has_slug ) {
467+ if ( is_subdomain_install () ) {
468+ // For subdomain installs, use the first part of the domain as the base
469+ $ domain_parts = explode ( '. ' , $ custom_domain );
470+ $ base = $ domain_parts [0 ];
471+ } else {
472+ // For subdirectory installs, use the path as the base
473+ $ base = trim ( $ custom_path , '/ ' );
474+ // Use the last part of the path if there are multiple segments
475+ $ path_parts = explode ( '/ ' , $ base );
476+ $ base = end ( $ path_parts );
477+ // If base is empty (root path), generate a random one
478+ if ( empty ( $ base ) ) {
479+ $ base = 'site- ' . wp_generate_password ( 8 , false );
480+ }
481+ }
482+ } else {
483+ $ base = $ assoc_args ['slug ' ];
484+ }
485+ } else {
486+ $ base = $ assoc_args ['slug ' ];
487+ }
423488
424489 /**
425490 * @var string $title
@@ -471,11 +536,25 @@ public function create( $args, $assoc_args ) {
471536 }
472537
473538 if ( is_subdomain_install () ) {
474- $ newdomain = $ base . '. ' . preg_replace ( '|^www\.| ' , '' , $ current_site ->domain );
475- $ path = $ current_site ->path ;
539+ if ( null !== $ custom_domain ) {
540+ // Use custom domain if provided via --url
541+ $ newdomain = $ custom_domain ;
542+ $ path = $ custom_path ;
543+ } else {
544+ // Use default behavior
545+ $ newdomain = $ base . '. ' . preg_replace ( '|^www\.| ' , '' , $ current_site ->domain );
546+ $ path = $ current_site ->path ;
547+ }
476548 } else {
477- $ newdomain = $ current_site ->domain ;
478- $ path = $ current_site ->path . $ base . '/ ' ;
549+ if ( null !== $ custom_domain ) {
550+ // Use custom domain and path if provided via --url
551+ $ newdomain = $ custom_domain ;
552+ $ path = $ custom_path ;
553+ } else {
554+ // Use default behavior
555+ $ newdomain = $ current_site ->domain ;
556+ $ path = $ current_site ->path . $ base . '/ ' ;
557+ }
479558 }
480559
481560 $ user_id = email_exists ( $ email );
0 commit comments