From e104bdef2bdcaa3247b98920b896e6e3e2613fb9 Mon Sep 17 00:00:00 2001 From: Pascal Birchler Date: Wed, 26 Aug 2026 08:02:58 +0000 Subject: [PATCH] Add `wp icon` and `wp icon collection` commands for the Icons API WordPress 7.1 introduced an Icons API where SVG icons are registered in code with `wp_register_icon()` and grouped into collections registered with `wp_register_icon_collection()`. Like font collections, they are registry-based and only exist for the duration of a request, so the new commands read and render them rather than creating or deleting them. `wp icon list` supports filtering by collection and searching names and labels, `wp icon get` exposes the registered SVG markup and the file an icon is loaded from, and `wp icon render` applies the same sizing and accessibility attributes that WordPress applies on the front end, so the markup can be piped straight into a template. Both commands abort on WordPress < 7.1 via `before_invoke`. The Icons API is not covered by the WordPress stubs yet, so the PHPStan entries for the unknown symbols use `reportUnmatched` to avoid becoming errors themselves once the stubs catch up. Co-authored-by: Pascal Birchler Co-authored-by: Claude Claude-Session: https://claude.ai/code/session_01Gg5xvmNbnSSpXzmGmWu1xh --- composer.json | 9 + entity-command.php | 11 + features/icon-collection.feature | 110 +++++++++ features/icon.feature | 205 +++++++++++++++++ phpcs.xml.dist | 1 + phpstan.neon.dist | 34 +++ src/Icon_Collection_Command.php | 260 +++++++++++++++++++++ src/Icon_Command.php | 377 +++++++++++++++++++++++++++++++ 8 files changed, 1007 insertions(+) create mode 100644 features/icon-collection.feature create mode 100644 features/icon.feature create mode 100644 src/Icon_Collection_Command.php create mode 100644 src/Icon_Command.php diff --git a/composer.json b/composer.json index a79ab7213..751aaac86 100644 --- a/composer.json +++ b/composer.json @@ -74,6 +74,15 @@ "font face install", "font family", "font family install", + "icon", + "icon collection", + "icon collection get", + "icon collection is-registered", + "icon collection list", + "icon get", + "icon is-registered", + "icon list", + "icon render", "menu", "menu create", "menu delete", diff --git a/entity-command.php b/entity-command.php index 52bc0a4cd..e16b522a3 100644 --- a/entity-command.php +++ b/entity-command.php @@ -140,3 +140,14 @@ WP_CLI::add_command( 'font collection', 'Font_Collection_Command', $wpcli_entity_font_version_check ); WP_CLI::add_command( 'font family', 'Font_Family_Command', $wpcli_entity_font_version_check ); WP_CLI::add_command( 'font face', 'Font_Face_Command', $wpcli_entity_font_version_check ); + +$wpcli_entity_icon_version_check = array( + 'before_invoke' => function () { + if ( Utils\wp_version_compare( '7.1', '<' ) ) { + WP_CLI::error( 'Requires WordPress 7.1 or greater.' ); + } + }, +); + +WP_CLI::add_command( 'icon', 'Icon_Command', $wpcli_entity_icon_version_check ); +WP_CLI::add_command( 'icon collection', 'Icon_Collection_Command', $wpcli_entity_icon_version_check ); diff --git a/features/icon-collection.feature b/features/icon-collection.feature new file mode 100644 index 000000000..88e2ec49b --- /dev/null +++ b/features/icon-collection.feature @@ -0,0 +1,110 @@ +Feature: Manage WordPress icon collections + + Background: + Given a WP install + + @require-wp-7.1 + Scenario: Listing icon collections + When I run `wp icon collection list --fields=slug,label,description` + Then STDOUT should be a table containing rows: + | slug | label | description | + | core | WordPress | Default icon collection. | + + @require-wp-7.1 + Scenario: Listing icon collections in other formats + When I run `wp icon collection list --format=ids` + Then STDOUT should contain: + """ + core + """ + + When I run `wp icon collection list --fields=slug,label --format=json` + Then STDOUT should be JSON containing: + """ + [{"slug":"core","label":"WordPress"}] + """ + + When I run `wp icon collection list --format=count` + Then STDOUT should be a number + + @require-wp-7.1 + Scenario: Getting an icon collection + When I run `wp icon collection get core --fields=slug,label,description` + Then STDOUT should be a table containing rows: + | Field | Value | + | slug | core | + | label | WordPress | + | description | Default icon collection. | + + When I run `wp icon collection get core --field=label` + Then STDOUT should be: + """ + WordPress + """ + + @require-wp-7.1 + Scenario: Counting the icons of a collection + When I run `wp icon collection get core --field=count` + Then STDOUT should be a number + + @require-wp-7.1 + Scenario: Getting a non-existent icon collection + When I try `wp icon collection get nonexistent-collection` + Then the return code should be 1 + And STDERR should contain: + """ + doesn't exist + """ + + @require-wp-7.1 + Scenario: Checking whether an icon collection is registered + When I try `wp icon collection is-registered nonexistent-collection` + Then the return code should be 1 + + When I run `wp icon collection is-registered core` + Then the return code should be 0 + + @require-wp-7.1 + Scenario: Listing a collection registered by a plugin + Given a wp-content/mu-plugins/test-icons.php file: + """ + 'Test Icons', + 'description' => 'A collection for testing.', + ) + ); + + wp_register_icon( + 'test-icons/square', + array( + 'label' => 'Square', + 'content' => '', + ) + ); + } + ); + """ + + When I run `wp icon collection list --fields=slug,label,description,count` + Then STDOUT should be a table containing rows: + | slug | label | description | count | + | test-icons | Test Icons | A collection for testing. | 1 | + + When I run `wp icon collection is-registered test-icons` + Then the return code should be 0 + + @less-than-wp-7.1 + Scenario: Icon collection commands fail on WordPress < 7.1 + When I try `wp icon collection list` + Then the return code should be 1 + And STDERR should contain: + """ + Requires WordPress 7.1 or greater + """ diff --git a/features/icon.feature b/features/icon.feature new file mode 100644 index 000000000..107ac3e1b --- /dev/null +++ b/features/icon.feature @@ -0,0 +1,205 @@ +Feature: Manage WordPress SVG icons + + Background: + Given a WP install + + @require-wp-7.1 + Scenario: Listing icons + When I run `wp icon list --collection=core --format=count` + Then STDOUT should be a number + + When I run `wp icon list --search=arrow-down --field=name` + Then STDOUT should contain: + """ + core/arrow-down + """ + + When I run `wp icon list --format=ids` + Then STDOUT should contain: + """ + core/plus + """ + + @require-wp-7.1 + Scenario: Listing icons matches names and labels + When I run `wp icon list --search="Arrow Down" --fields=name,label,collection` + Then STDOUT should be a table containing rows: + | name | label | collection | + | core/arrow-down | Arrow Down | core | + + @require-wp-7.1 + Scenario: Listing icons of a non-existent collection + When I try `wp icon list --collection=nonexistent-collection` + Then the return code should be 1 + And STDERR should contain: + """ + doesn't exist + """ + + @require-wp-7.1 + Scenario: Getting an icon + When I run `wp icon get core/plus --fields=name,label,collection` + Then STDOUT should be a table containing rows: + | Field | Value | + | name | core/plus | + | label | Plus | + | collection | core | + + When I run `wp icon get core/plus --field=content` + Then STDOUT should contain: + """ +