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
28 changes: 28 additions & 0 deletions src/wp-includes/class-wp-icons-registry.php
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,34 @@ protected function register( $icon_name, $icon_properties ) {
return false;
}

if ( preg_match( '/[A-Z]/', $icon_name ) ) {
_doing_it_wrong(
__METHOD__,
__( 'Icon names must not contain uppercase characters.' ),
'7.1.0'
);
return false;
}

$name_matcher = '/^[a-z][a-z0-9-]*\/[a-z][a-z0-9-]*$/';
if ( ! preg_match( $name_matcher, $icon_name ) ) {
_doing_it_wrong(
__METHOD__,
__( 'Icon names must contain a namespace prefix. Example: my-plugin/my-custom-icon' ),
'7.1.0'
);
return false;
}

if ( $this->is_registered( $icon_name ) ) {
_doing_it_wrong(
__METHOD__,
__( 'Icon is already registered.' ),
'7.1.0'
);
return false;
}

$allowed_keys = array_fill_keys( array( 'label', 'content', 'filePath' ), 1 );
foreach ( array_keys( $icon_properties ) as $key ) {
if ( ! array_key_exists( $key, $allowed_keys ) ) {
Expand Down
110 changes: 110 additions & 0 deletions tests/phpunit/tests/icons/wpIconsRegistry.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
<?php
/**
* Tests for WP_Icons_Registry::register().
*
* @package WordPress
* @subpackage Icons
*
* @group icons
* @covers WP_Icons_Registry::register
* @covers WP_Icons_Registry::is_registered
*/
class Tests_Icons_WpIconsRegistry extends WP_UnitTestCase {

/**
* Registry instance for testing.
*
* @var WP_Icons_Registry
*/
private $registry;

public function set_up() {
parent::set_up();
$this->registry = WP_Icons_Registry::get_instance();
}

public function tear_down() {
$instance_property = new ReflectionProperty( WP_Icons_Registry::class, 'instance' );

if ( PHP_VERSION_ID < 80100 ) {
$instance_property->setAccessible( true );
}

$instance_property->setValue( null, null );

$this->registry = null;
parent::tear_down();
}

/**
* Invokes WP_Icons_Registry::register despite it being private
*
* @param string $icon_name Icon name including namespace.
* @param array $icon_properties Icon properties (label, content, filePath).
* @return bool True if the icon was registered successfully.
*/
private function register( $icon_name, $icon_properties ) {
$method = new ReflectionMethod( $this->registry, 'register' );

if ( PHP_VERSION_ID < 80100 ) {
$method->setAccessible( true );
}

return $method->invoke( $this->registry, $icon_name, $icon_properties );
}

/**
* Provides invalid icon names.
*
* @return array[]
*/
public function data_invalid_icon_names() {
return array(
'non-string name' => array( 1 ),
'no namespace' => array( 'plus' ),
'uppercase characters' => array( 'Test/Plus' ),
'invalid characters' => array( 'test/_doing_it_wrong' ),
);
}

/**
* Should fail to re-register the same icon.
*
* @ticket 64847
*
* @expectedIncorrectUsage WP_Icons_Registry::register
*/
public function test_register_icon_twice() {
Comment thread
t-hamano marked this conversation as resolved.
$name = 'test-plugin/duplicate';
$settings = array(
'label' => 'Icon',
'content' => '<svg></svg>',
);

$result = $this->register( $name, $settings );
$this->assertTrue( $result );
$result2 = $this->register( $name, $settings );
$this->assertFalse( $result2 );
}


/**
* Should fail to register icon with invalid names.
*
* @ticket 64847
*
* @dataProvider data_invalid_icon_names
Comment thread
t-hamano marked this conversation as resolved.
* @expectedIncorrectUsage WP_Icons_Registry::register
*
* @param mixed $icon_name Icon name to register.
*/
public function test_register_invalid_name( $icon_name ) {
$settings = array(
'label' => 'Icon',
'content' => '<svg></svg>',
);

$result = $this->register( $icon_name, $settings );
$this->assertFalse( $result );
}
}
Loading