Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ wp-tests-config.php
/src/wp-admin/css/colors/*/*.css
/src/wp-admin/js
/src/wp-includes/assets/*
!/src/wp-includes/assets/icon-library-inlined-icons.php
!/src/wp-includes/assets/icon-library-manifest.php
!/src/wp-includes/assets/script-loader-packages.php
!/src/wp-includes/assets/script-modules-packages.php
Expand Down
8 changes: 8 additions & 0 deletions Gruntfile.js
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ module.exports = function(grunt) {
// Routes and pages.
SOURCE_DIR + 'wp-includes/build',
// PHP manifests generated by gutenberg:copy.
SOURCE_DIR + 'wp-includes/assets/icon-library-inlined-icons.php',
SOURCE_DIR + 'wp-includes/assets/icon-library-manifest.php',
SOURCE_DIR + 'wp-includes/assets/script-loader-packages.php',
SOURCE_DIR + 'wp-includes/assets/script-modules-packages.php',
Expand Down Expand Up @@ -821,6 +822,12 @@ module.exports = function(grunt) {
dest: SOURCE_DIR + 'wp-includes/assets/icon-library-manifest.php',
} ],
},
'icon-library-inlined-icons': {
files: [ {
src: 'gutenberg/packages/icons/src/inlined-icons.php',
dest: SOURCE_DIR + 'wp-includes/assets/icon-library-inlined-icons.php',
} ],
},
},
sass: {
colors: {
Expand Down Expand Up @@ -2314,6 +2321,7 @@ module.exports = function(grunt) {
'copy:gutenberg-theme-json',
'copy:icon-library-images',
'copy:icon-library-manifest',
'copy:icon-library-inlined-icons',
] );

grunt.registerTask( 'build', 'Builds WordPress. Use --dev to build into src/ for development.', function() {
Expand Down
28 changes: 28 additions & 0 deletions src/wp-includes/assets/icon-library-inlined-icons.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<?php
// This file is automatically generated. Do not edit directly.
if ( ! defined( 'ABSPATH' ) ) {
die( 'Silence is golden.' );
}

return array(
'core-admin/brush' => '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" style="fill: none" stroke="currentColor" stroke-width="1.5"><path d="M17 15.25L17.5858 14.6642C18.3668 13.8832 18.3668 12.6168 17.5858 11.8358L16.7071 10.9571C16.3166 10.5666 16.3166 9.93342 16.7071 9.54289L20 6.25C20.5523 5.69772 20.5523 4.80228 20 4.25C19.4477 3.69772 18.5523 3.69771 18 4.25L14.7071 7.54289C14.3166 7.93342 13.6834 7.93342 13.2929 7.54289L12.4142 6.66421C11.6332 5.88316 10.3668 5.88316 9.58579 6.66421L9 7.25M17 15.25L14.1213 18.1287C12.9497 19.3003 11.0503 19.3003 9.87868 18.1287L8 16.25M17 15.25L9 7.25M9 7.25L4 12.25L6 14.25M6 14.25L8 12.25M6 14.25L8 16.25M8 16.25L10 14.25" vector-effect="non-scaling-stroke" /></svg>',
'core-admin/chevron-left' => '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" style="fill: none" stroke="currentColor" stroke-width="1.5"><path d="M14 6.5L9 12L14 17.5" vector-effect="non-scaling-stroke" /></svg>',
'core-admin/comment' => '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" style="fill: none" stroke="currentColor" stroke-width="1.5"><path d="M18 5.5H6C5.30964 5.5 4.75 6.05964 4.75 6.75V16V18.4096C4.75 18.8725 5.32471 19.0869 5.62784 18.7371L8 16H18C18.6904 16 19.25 15.4404 19.25 14.75V6.75C19.25 6.05964 18.6904 5.5 18 5.5Z" vector-effect="non-scaling-stroke" /></svg>',
'core-admin/dashboard' => '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" style="fill: none" stroke="currentColor" stroke-width="1.5"><path d="M18 6L12.5303 11.4697M12.5303 11.4697C12.3946 11.3339 12.2071 11.25 12 11.25C11.5858 11.25 11.25 11.5858 11.25 12C11.25 12.4142 11.5858 12.75 12 12.75C12.4142 12.75 12.75 12.4142 12.75 12C12.75 11.7929 12.6661 11.6054 12.5303 11.4697ZM18.2798 8.37444C18.8968 9.44094 19.25 10.6792 19.25 12C19.25 14.002 18.4385 15.8145 17.1266 17.1265M15.6256 5.72029C14.5591 5.1032 13.3208 4.75 12 4.75C7.99594 4.75 4.75 7.99594 4.75 12C4.75 14.002 5.5615 15.8146 6.87351 17.1266" stroke-linejoin="round" vector-effect="non-scaling-stroke" /></svg>',
'core-admin/home' => '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" style="fill: none" stroke="currentColor" stroke-width="1.5"><path d="M13.75 19.25H19.25V8.5L12 5L4.75 8.5V19.25H10.25M13.75 19.25V13.7H10.25V19.25M13.75 19.25H10.25" vector-effect="non-scaling-stroke" /></svg>',
'core-admin/link' => '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" style="fill: none" stroke="currentColor" stroke-width="1.5"><path d="M9.5 12L14.5 12M10 7.75H8.25C5.90279 7.75 4 9.65279 4 12C4 14.3472 5.90279 16.25 8.25 16.25H10M14 16.25H15.75C18.0972 16.25 20 14.3472 20 12C20 9.65279 18.0972 7.75 15.75 7.75L14 7.75" vector-effect="non-scaling-stroke" /></svg>',
'core-admin/media' => '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" style="fill: none" stroke="currentColor" stroke-width="1.5"><path d="M14 12.375V6.51534C14 6.21609 13.7879 5.95882 13.4941 5.9018L11.8239 5.57758C11.5677 5.52784 11.341 5.37988 11.1924 5.1653L10.3985 4.01913C10.2818 3.85057 10.0898 3.75 9.88474 3.75H8.11526C7.91022 3.75 7.71822 3.85057 7.60147 4.01913L6.80758 5.1653C6.65896 5.37988 6.43232 5.52784 6.17608 5.57758L4.5059 5.9018C4.21213 5.95882 4 6.21609 4 6.51534V12.375C4 12.7202 4.27982 13 4.625 13H13.375C13.7202 13 14 12.7202 14 12.375Z" vector-effect="non-scaling-stroke" /><circle cx="9" cy="9" r="1" fill="currentColor" vector-effect="non-scaling-stroke" /><path d="M20 17.25V9" vector-effect="non-scaling-stroke" /><path d="M17 10H20V9H17V10Z" fill="currentColor" vector-effect="non-scaling-stroke" /><path d="M11.75 18.5C12.4404 18.5 13 17.9404 13 17.25V16H11.75C11.0596 16 10.5 16.5596 10.5 17.25C10.5 17.9404 11.0596 18.5 11.75 18.5Z" fill="currentColor" vector-effect="non-scaling-stroke" /><path d="M18.75 18.5C19.4404 18.5 20 17.9404 20 17.25V16H18.75C18.0596 16 17.5 16.5596 17.5 17.25C17.5 17.9404 18.0596 18.5 18.75 18.5Z" fill="currentColor" vector-effect="non-scaling-stroke" /></svg>',
'core-admin/menu' => '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" style="fill: none" stroke="currentColor" stroke-width="1.5"><path d="M5 12H19M5 18.25H19M5 5.75H19" vector-effect="non-scaling-stroke" /></svg>',
'core-admin/page' => '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" style="fill: none" stroke="currentColor" stroke-width="1.5"><path d="M8.5 8.25H15.5M8.5 11.75H15.5M8.5 15.25H15.5M18.25 18V6C18.25 5.30964 17.6904 4.75 17 4.75H7C6.30964 4.75 5.75 5.30964 5.75 6L5.75 18C5.75 18.6904 6.30964 19.25 7 19.25H17C17.6904 19.25 18.25 18.6904 18.25 18Z" vector-effect="non-scaling-stroke" /></svg>',
'core-admin/pencil' => '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" style="fill: none" stroke="currentColor" stroke-width="1.5"><path d="M5 19.25H12" vector-effect="non-scaling-stroke" /><path d="M10 15L7.5 15.5L8 13L16 5L18 7L10 15Z" fill="currentColor" vector-effect="non-scaling-stroke" /></svg>',
'core-admin/people' => '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" style="fill: none" stroke="currentColor" stroke-width="1.5"><path d="M4.5 17V15C4.5 13.8954 5.39543 13 6.5 13H10.5C11.6046 13 12.5 13.8954 12.5 15V17M15 13H17.5C18.6046 13 19.5 13.8954 19.5 15V17M10.25 8.5C10.25 9.4665 9.4665 10.25 8.5 10.25C7.5335 10.25 6.75 9.4665 6.75 8.5C6.75 7.5335 7.5335 6.75 8.5 6.75C9.4665 6.75 10.25 7.5335 10.25 8.5ZM17.25 8.5C17.25 9.4665 16.4665 10.25 15.5 10.25C14.5335 10.25 13.75 9.4665 13.75 8.5C13.75 7.5335 14.5335 6.75 15.5 6.75C16.4665 6.75 17.25 7.5335 17.25 8.5Z" vector-effect="non-scaling-stroke" /></svg>',
'core-admin/pin' => '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" style="fill: none" stroke="currentColor" stroke-width="1.5"><path d="M5 19L10 14M13.5355 17.5355L6.46447 10.4645C7.731 9.19794 9.50794 8.75292 11.1332 9.12941L14.5 4.50002L19.5 9.50002L14.8706 12.8669C15.2471 14.4921 14.8021 16.269 13.5355 17.5355Z" vector-effect="non-scaling-stroke" /></svg>',
'core-admin/plugins' => '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" style="fill: none" stroke="currentColor" stroke-width="1.5"><path d="M15.3995 11.5711L12.2175 8.38909L10.273 6.44454L7.67678 9.04074C7.3017 9.41581 7.09099 9.92452 7.09099 10.455L7.09099 13.455C7.09099 13.7202 6.98563 13.9745 6.7981 14.1621L5.14645 15.8137C4.95118 16.009 4.95118 16.3256 5.14645 16.5208L7.26777 18.6421C7.46303 18.8374 7.77961 18.8374 7.97487 18.6421L9.62652 16.9905C9.81406 16.8029 10.0684 16.6976 10.3336 16.6976H13.3336C13.8641 16.6976 14.3728 16.4869 14.7478 16.1118L17.344 13.5156L15.3995 11.5711ZM12.2175 8.38909L16.1066 4.5M15.3995 11.5711L19.2886 7.68198" vector-effect="non-scaling-stroke" /></svg>',
'core-admin/plus' => '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" style="fill: none" stroke="currentColor" stroke-width="1.5"><path d="M12 18V6M18 12H6" vector-effect="non-scaling-stroke" /></svg>',
'core-admin/search' => '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" style="fill: none" stroke="currentColor" stroke-width="1.5"><path d="M5 19L9.28769 14.7123M18.25 11C18.25 13.8995 15.8995 16.25 13 16.25C10.1005 16.25 7.75 13.8995 7.75 11C7.75 8.10051 10.1005 5.75 13 5.75C15.8995 5.75 18.25 8.10051 18.25 11Z" vector-effect="non-scaling-stroke" /></svg>',
'core-admin/settings' => '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" style="fill: none" stroke="currentColor" stroke-width="1.5"><path d="M5 8H19M19 16H5M10.75 8C10.75 8.82843 10.0784 9.5 9.25 9.5C8.42157 9.5 7.75 8.82843 7.75 8C7.75 7.17157 8.42157 6.5 9.25 6.5C10.0784 6.5 10.75 7.17157 10.75 8ZM16.25 16C16.25 16.8284 15.5784 17.5 14.75 17.5C13.9216 17.5 13.25 16.8284 13.25 16C13.25 15.1716 13.9216 14.5 14.75 14.5C15.5784 14.5 16.25 15.1716 16.25 16Z" vector-effect="non-scaling-stroke" /></svg>',
'core-admin/sites' => '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" style="fill: none" stroke="currentColor" stroke-width="1.5"><rect x="4.75" y="13.75" width="5.5" height="5.5" rx="1.25" vector-effect="non-scaling-stroke" /><rect x="13.75" y="13.75" width="5.5" height="5.5" rx="1.25" vector-effect="non-scaling-stroke" /><rect x="8.75" y="4.75" width="6" height="5.5" rx="1.25" vector-effect="non-scaling-stroke" /></svg>',
'core-admin/tool' => '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" style="fill: none" stroke="currentColor" stroke-width="1.5"><path d="M14.5 13.25C16.5711 13.25 18.25 11.5711 18.25 9.5C18.25 9.03597 18.1657 8.59162 18.0116 8.18143C17.9867 8.11497 17.9017 8.09828 17.8515 8.14848L15.7071 10.2929C15.3166 10.6834 14.6834 10.6834 14.2929 10.2929L13.7071 9.70711C13.3166 9.31658 13.3166 8.68342 13.7071 8.29289L15.8515 6.14848C15.9017 6.09828 15.885 6.01334 15.8186 5.98838C15.4084 5.83428 14.964 5.75 14.5 5.75C12.4289 5.75 10.75 7.42893 10.75 9.5C10.75 10.0166 10.8545 10.5088 11.0434 10.9566L5.70711 16.2929C5.31658 16.6834 5.31658 17.3166 5.70711 17.7071L6.2929 18.2929C6.68342 18.6834 7.31658 18.6834 7.70711 18.2929L13.0434 12.9566C13.4912 13.1455 13.9834 13.25 14.5 13.25Z" vector-effect="non-scaling-stroke" /></svg>',
'core-admin/update' => '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" style="fill: none" stroke="currentColor" stroke-width="1.5"><path d="M12 5.5L17.7929 11.2929C18.1834 11.6834 18.1834 12.3166 17.7929 12.7071L16 14.5M16 5.5H12V9.5M12 18.5L6.20711 12.7071C5.81658 12.3166 5.81658 11.6834 6.20711 11.2929L8 9.5M8 18.5H12V14.5" vector-effect="non-scaling-stroke" /></svg>',
'core-admin/wordpress' => '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor"><path d="M 22 12 C 22 6.49 17.51 2 12 2 C 6.48 2 2 6.49 2 12 C 2 17.52 6.48 22 12 22 C 17.51 22 22 17.52 22 12 M 9.78 17.37 L 6.37 8.22 C 6.92 8.2 7.54 8.14 7.54 8.14 C 8.04 8.08 7.98 7.01 7.48 7.03 C 7.48 7.03 6.03 7.14 5.11 7.14 C 4.93 7.14 4.74 7.14 4.53 7.13 C 6.12 4.69 8.87 3.11 12 3.11 C 14.33 3.11 16.45 3.98 18.05 5.45 C 17.37 5.34 16.4 5.84 16.4 7.03 C 16.4 7.77 16.85 8.39 17.3 9.13 C 17.65 9.74 17.85 10.49 17.85 11.59 C 17.85 13.08 16.45 16.59 16.45 16.59 L 13.42 8.22 C 13.96 8.2 14.24 8.05 14.24 8.05 C 14.74 8 14.68 6.8 14.18 6.83 C 14.18 6.83 12.74 6.95 11.8 6.95 C 10.93 6.95 9.47 6.83 9.47 6.83 C 8.97 6.8 8.91 8.03 9.41 8.05 L 10.33 8.13 L 11.59 11.54 L 9.78 17.37 M 19.41 12 C 19.65 11.36 20.15 10.13 19.84 7.75 C 20.54 9.04 20.89 10.46 20.89 12 C 20.89 15.29 19.16 18.24 16.49 19.78 C 17.46 17.19 18.43 14.58 19.41 12 M 8.1 20.09 C 5.12 18.65 3.11 15.53 3.11 12 C 3.11 10.7 3.34 9.52 3.83 8.41 C 5.25 12.3 6.67 16.2 8.1 20.09 M 12.13 13.46 L 14.71 20.44 C 13.85 20.73 12.95 20.89 12 20.89 C 11.21 20.89 10.43 20.78 9.71 20.56 C 10.52 18.18 11.33 15.82 12.13 13.46 L 12.13 13.46" /></svg>',
);
20 changes: 19 additions & 1 deletion src/wp-includes/class-wp-icons-registry.php
Original file line number Diff line number Diff line change
Expand Up @@ -357,13 +357,31 @@ protected function sanitize_icon_content( $icon_content ) {
* Retrieves the content of a registered icon.
*
* @since 7.0.0
* @since 7.2.0 The content of some of the bundled icons comes from a generated file.
*
* @param string $icon_name Icon name including namespace.
* @return string|null The content of the icon, if found.
*/
protected function get_content( $icon_name ) {
static $inlined_icons = null;

if ( ! isset( $this->registered_icons[ $icon_name ]['content'] ) ) {
$file_path = $this->registered_icons[ $icon_name ]['file_path'] ?? '';
$file_path = $this->registered_icons[ $icon_name ]['file_path'] ?? '';

// Some bundled icons have their markup inlined in a generated file, to skip reading and sanitizing their files.
$icons_directory = ABSPATH . WPINC . '/images/icon-library/';
if ( is_string( $file_path ) && str_starts_with( $file_path, $icons_directory ) ) {
if ( null === $inlined_icons ) {
$inlined_icons_path = ABSPATH . WPINC . '/assets/icon-library-inlined-icons.php';
$inlined_icons = file_exists( $inlined_icons_path ) ? include $inlined_icons_path : array();
}

if ( isset( $inlined_icons[ $icon_name ] ) ) {
$this->registered_icons[ $icon_name ]['content'] = $inlined_icons[ $icon_name ];
return $inlined_icons[ $icon_name ];
}
}

$is_stringy = is_string( $file_path ) || ( is_object( $file_path ) && method_exists( $file_path, '__toString' ) );
$icon_path = $is_stringy ? realpath( (string) $file_path ) : false;

Expand Down
102 changes: 102 additions & 0 deletions tests/phpunit/tests/icons/wpIconsRegistry.php
Original file line number Diff line number Diff line change
Expand Up @@ -540,6 +540,108 @@ public function test_get_content_returns_null_for_invalid_file( $contents, $exte
$this->assertNull( $icon['content'] );
}

/**
* Provides the icons whose markup is inlined in the generated file.
*
* @return array<string, array{0: string, 1: string, 2: string}> Data sets of [ $icon_name, $content, $file_path ], keyed by icon name.
*/
public function data_inlined_icons(): array {
$manifest = include ABSPATH . WPINC . '/assets/icon-library-manifest.php';
$inlined = include ABSPATH . WPINC . '/assets/icon-library-inlined-icons.php';
$data = array();

foreach ( $inlined as $icon_name => $content ) {
$slug = explode( '/', $icon_name, 2 )[1];
$file_path = ABSPATH . WPINC . '/images/icon-library/' . ( $manifest[ $slug ]['filePath'] ?? '' );
$data[ $icon_name ] = array( $icon_name, $content, $file_path );
}

return $data;
}

/**
* Should only inline icons which exist in the manifest.
*
* The file is generated in Gutenberg and copied over by `npm run grunt build:gutenberg`.
*/
public function test_inlined_icons_exist_in_manifest() {
$manifest = include ABSPATH . WPINC . '/assets/icon-library-manifest.php';
$inlined = include ABSPATH . WPINC . '/assets/icon-library-inlined-icons.php';

$this->assertNotEmpty( $inlined );

foreach ( array_keys( $inlined ) as $icon_name ) {
list( $collection, $slug ) = explode( '/', $icon_name, 2 );

$this->assertArrayHasKey( $slug, $manifest, "The inlined icon \"$icon_name\" should exist in the manifest." );
$this->assertContains( $collection, $manifest[ $slug ]['collections'], "The inlined icon \"$icon_name\" should belong to its collection." );
}
}

/**
* The inlined markup is not sanitized at runtime, so it should be equivalent
* to the sanitized content of the icon file it was generated from.
*
* @dataProvider data_inlined_icons
*
* @param string $icon_name The namespaced icon name.
* @param string $content The inlined SVG markup of the icon.
* @param string $file_path Absolute path to the icon file.
*/
public function test_inlined_icon_content_matches_sanitized_icon_file( $icon_name, $content, $file_path ) {
$expected = $this->sanitize_icon_content( file_get_contents( $file_path ) );

// The generated file has the whitespace between tags removed.
$expected = preg_replace( '/>\s+</', '><', trim( $expected ) );

$this->assertEqualHTML( $expected, $content );
}

/**
* Should use the inlined markup for a bundled icon, without reading its file.
*
* @covers ::get_content
*
* @dataProvider data_inlined_icons
*
* @param string $icon_name The namespaced icon name.
* @param string $content The inlined SVG markup of the icon.
* @param string $file_path Absolute path to the icon file.
*/
public function test_get_content_uses_inlined_content_for_bundled_icon( $icon_name, $content, $file_path ) {
$this->registry->register(
$icon_name,
array(
'label' => 'Inlined',
'file_path' => $file_path,
)
);

$icon = $this->registry->get_registered_icon( $icon_name );
$this->assertSame( $content, $icon['content'] );
}

/**
* Should read the file of an icon registered under an inlined name from another location.
*
* @covers ::get_content
*
*/
public function test_get_content_reads_file_for_core_admin_name_outside_bundled_directory() {
$path = $this->create_temp_icon_file( '<svg><path d="M1 2"/></svg>' );

$this->registry->register(
'core-admin/dashboard',
array(
'label' => 'Replacement',
'file_path' => $path,
)
);

$icon = $this->registry->get_registered_icon( 'core-admin/dashboard' );
$this->assertEqualHTML( '<svg><path d="M1 2"/></svg>', $icon['content'] );
}

/**
* Should register an icon that provides a valid `keywords` array.
*
Expand Down
Loading