Skip to content

Commit 31bb185

Browse files
CopilotswissspidyCopilot
authored
Implement wp site get command to enable site operations by URL (#571)
Co-authored-by: swissspidy <841956+swissspidy@users.noreply.github.com> Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: Pascal Birchler <pascalb@google.com>
1 parent c764923 commit 31bb185

File tree

3 files changed

+262
-0
lines changed

3 files changed

+262
-0
lines changed

composer.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,7 @@
154154
"site deactivate",
155155
"site delete",
156156
"site empty",
157+
"site get",
157158
"site list",
158159
"site mature",
159160
"site meta",

features/site.feature

Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -763,3 +763,131 @@ Feature: Manage sites in a multisite installation
763763
Then STDOUT should be a table containing rows:
764764
| blog_id | public |
765765
| 2 | 1 |
766+
767+
Scenario: Get site by ID
768+
Given a WP multisite install
769+
770+
When I run `wp site create --slug=testsite --porcelain`
771+
Then STDOUT should be a number
772+
And save STDOUT as {SITE_ID}
773+
774+
When I run `wp site get {SITE_ID} --field=blog_id`
775+
Then STDOUT should be:
776+
"""
777+
{SITE_ID}
778+
"""
779+
780+
When I run `wp site get {SITE_ID}`
781+
Then STDOUT should be a table containing rows:
782+
| Field | Value |
783+
| blog_id | {SITE_ID} |
784+
785+
Scenario: Get site by URL
786+
Given a WP multisite install
787+
788+
When I run `wp site create --slug=testsite --porcelain`
789+
Then STDOUT should be a number
790+
And save STDOUT as {SITE_ID}
791+
And I run `wp site list --blog_id={SITE_ID} --field=url`
792+
And save STDOUT as {SITE_URL}
793+
794+
When I run `wp site get {SITE_URL} --field=blog_id`
795+
Then STDOUT should be:
796+
"""
797+
{SITE_ID}
798+
"""
799+
800+
Scenario: Get site by URL with subdirectory
801+
Given a WP multisite subdirectory install
802+
803+
When I run `wp site create --slug=mysubdir --porcelain`
804+
Then STDOUT should be a number
805+
And save STDOUT as {SITE_ID}
806+
807+
When I run `wp site get http://example.com/mysubdir/ --field=blog_id`
808+
Then STDOUT should be:
809+
"""
810+
{SITE_ID}
811+
"""
812+
813+
Scenario: Use site get with site delete
814+
Given a WP multisite install
815+
816+
When I run `wp site create --slug=deleteme --porcelain`
817+
Then STDOUT should be a number
818+
And save STDOUT as {SITE_ID}
819+
820+
When I run `wp site get http://example.com/deleteme/ --field=blog_id`
821+
Then STDOUT should be:
822+
"""
823+
{SITE_ID}
824+
"""
825+
And save STDOUT as {BLOG_ID}
826+
827+
When I run `wp site delete {BLOG_ID} --yes`
828+
Then STDOUT should contain:
829+
"""
830+
Success: The site at
831+
"""
832+
And STDOUT should contain:
833+
"""
834+
was deleted.
835+
"""
836+
837+
Scenario: Get site with invalid URL should fail
838+
Given a WP multisite install
839+
840+
When I try `wp site get http://example.com/nonexistent/ --field=blog_id`
841+
Then STDERR should contain:
842+
"""
843+
Error: Could not find site with URL: http://example.com/nonexistent/
844+
"""
845+
And the return code should be 1
846+
847+
Scenario: Get site by domain without scheme
848+
Given a WP multisite subdirectory install
849+
850+
When I run `wp site create --slug=noscheme --porcelain`
851+
Then STDOUT should be a number
852+
And save STDOUT as {SITE_ID}
853+
854+
When I run `wp site get example.com/noscheme/ --field=blog_id`
855+
Then STDOUT should be:
856+
"""
857+
{SITE_ID}
858+
"""
859+
860+
Scenario: Get site by simple domain path
861+
Given a WP multisite subdirectory install
862+
863+
When I run `wp site create --slug=simplepath --porcelain`
864+
Then STDOUT should be a number
865+
And save STDOUT as {SITE_ID}
866+
867+
When I run `wp site get example.com/simplepath --field=blog_id`
868+
Then STDOUT should be:
869+
"""
870+
{SITE_ID}
871+
"""
872+
873+
Scenario: Get site by subdomain without scheme
874+
Given a WP multisite subdomain install
875+
876+
When I run `wp site create --slug=subdomain --porcelain`
877+
Then STDOUT should be a number
878+
And save STDOUT as {SITE_ID}
879+
880+
When I run `wp site get subdomain.example.com --field=blog_id`
881+
Then STDOUT should be:
882+
"""
883+
{SITE_ID}
884+
"""
885+
886+
Scenario: Get main site by domain
887+
Given a WP multisite install
888+
889+
When I run `wp site get example.com --field=blog_id`
890+
Then STDOUT should be:
891+
"""
892+
1
893+
"""

src/Site_Command.php

Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -384,6 +384,139 @@ public function delete( $args, $assoc_args ) {
384384
WP_CLI::success( "The site at '{$site_url}' was deleted." );
385385
}
386386

387+
/**
388+
* Gets details about a site in a multisite installation.
389+
*
390+
* ## OPTIONS
391+
*
392+
* <site>
393+
* : Site ID or URL of the site to get. For subdirectory sites, use the full URL (e.g., http://example.com/subdir/).
394+
*
395+
* [--field=<field>]
396+
* : Instead of returning the whole site, returns the value of a single field.
397+
*
398+
* [--fields=<fields>]
399+
* : Limit the output to specific fields. Defaults to all fields.
400+
*
401+
* [--format=<format>]
402+
* : Render output in a particular format.
403+
* ---
404+
* default: table
405+
* options:
406+
* - table
407+
* - csv
408+
* - json
409+
* - yaml
410+
* ---
411+
*
412+
* ## AVAILABLE FIELDS
413+
*
414+
* These fields will be displayed by default for the site:
415+
*
416+
* * blog_id
417+
* * url
418+
* * last_updated
419+
* * registered
420+
*
421+
* These fields are optionally available:
422+
*
423+
* * site_id
424+
* * domain
425+
* * path
426+
* * public
427+
* * archived
428+
* * mature
429+
* * spam
430+
* * deleted
431+
* * lang_id
432+
*
433+
* ## EXAMPLES
434+
*
435+
* # Get site by ID
436+
* $ wp site get 1
437+
* +---------+-------------------------+---------------------+---------------------+
438+
* | blog_id | url | last_updated | registered |
439+
* +---------+-------------------------+---------------------+---------------------+
440+
* | 1 | http://example.com/ | 2025-01-01 12:00:00 | 2025-01-01 12:00:00 |
441+
* +---------+-------------------------+---------------------+---------------------+
442+
*
443+
* # Get site URL by site ID
444+
* $ wp site get 1 --field=url
445+
* http://example.com/
446+
*
447+
* # Get site ID by URL
448+
* $ wp site get http://example.com/subdir/ --field=blog_id
449+
* 2
450+
*
451+
* # Delete a site by URL
452+
* $ wp site delete $(wp site get http://example.com/subdir/ --field=blog_id) --yes
453+
* Success: The site at 'http://example.com/subdir/' was deleted.
454+
*/
455+
public function get( $args, $assoc_args ) {
456+
if ( ! is_multisite() ) {
457+
WP_CLI::error( 'This is not a multisite installation.' );
458+
}
459+
460+
$site_arg = $args[0];
461+
$site = null;
462+
463+
// Check if the argument is a URL or a domain (non-numeric)
464+
if ( ! is_numeric( $site_arg ) ) {
465+
// Normalize URLs without a scheme for proper parsing.
466+
$url_to_parse = $site_arg;
467+
if ( false === strpos( $url_to_parse, '://' ) ) {
468+
$url_to_parse = 'http://' . $url_to_parse;
469+
}
470+
471+
// Parse the URL to get domain and path
472+
$url_parts = wp_parse_url( $url_to_parse );
473+
474+
if ( ! isset( $url_parts['host'] ) ) {
475+
WP_CLI::error( "Invalid URL: {$site_arg}" );
476+
}
477+
478+
$domain = $url_parts['host'];
479+
$path = isset( $url_parts['path'] ) ? $url_parts['path'] : '/';
480+
481+
// Ensure path ends with /
482+
if ( '/' !== substr( $path, -1 ) ) {
483+
$path .= '/';
484+
}
485+
486+
// Use WordPress's cached function to get the blog ID
487+
$blog_id = get_blog_id_from_url( $domain, $path );
488+
489+
if ( ! $blog_id ) {
490+
WP_CLI::error( "Could not find site with URL: {$site_arg}" );
491+
}
492+
493+
$site = $this->fetcher->get_check( $blog_id );
494+
} else {
495+
// Treat as site ID
496+
$site = $this->fetcher->get_check( $site_arg );
497+
}
498+
499+
// Get the site details and add URL
500+
$site_data = get_object_vars( $site );
501+
$site_data['url'] = trailingslashit( get_home_url( $site->blog_id ) );
502+
503+
// Cast numeric fields to int for consistent output
504+
$numeric_fields = [ 'blog_id', 'site_id', 'public', 'archived', 'mature', 'spam', 'deleted', 'lang_id' ];
505+
foreach ( $numeric_fields as $field ) {
506+
if ( isset( $site_data[ $field ] ) && is_scalar( $site_data[ $field ] ) ) {
507+
$site_data[ $field ] = (int) $site_data[ $field ];
508+
}
509+
}
510+
511+
// Set default fields if not specified
512+
if ( empty( $assoc_args['fields'] ) ) {
513+
$assoc_args['fields'] = [ 'blog_id', 'url', 'last_updated', 'registered' ];
514+
}
515+
516+
$formatter = $this->get_formatter( $assoc_args );
517+
$formatter->display_item( $site_data );
518+
}
519+
387520
/**
388521
* Creates a site in a multisite installation.
389522
*

0 commit comments

Comments
 (0)