Problem/Motivation

Drupal\Component\Utility\Color::validateHex('###FF0') return TRUE.

/**
 * Validates whether a hexadecimal color value is syntactically correct.
 *
 * @param $hex
 *   The hexadecimal string to validate. May contain a leading '#'. May use
 *   the shorthand notation (e.g., '123' for '112233').
 *
 * @return bool
 *   TRUE if $hex is valid or FALSE if it is not.
 */
public static function validateHex($hex) {
  // Must be a string.
  $valid = is_string($hex);
  // Hash prefix is optional.
  $hex = ltrim($hex, '#');
  // Must be either RGB or RRGGBB.
  $length = mb_strlen($hex);
  $valid = $valid && ($length === 3 || $length === 6);
  // Must be a valid hex value.
  $valid = $valid && ctype_xdigit($hex);
  return $valid;
}

Proposed resolution

Decide if this is the correct behavior.
Correct if it's an error.

Remaining tasks

Add a test coverage.

Comments

Krzysztof Domański created an issue. See original summary.

krzysztof domański’s picture

Status: Active » Needs review
StatusFileSize
new1.66 KB
new2.36 KB
johnwebdev’s picture

Nice with test coverage :)

  1. +++ b/core/lib/Drupal/Component/Utility/Color.php
    @@ -20,8 +20,10 @@ class Color {
    +    if (substr($hex, 0, 1) == '#') {
    

    Let's use === instead.

  2. +++ b/core/tests/Drupal/Tests/Component/Utility/ColorTest.php
    @@ -12,6 +12,61 @@
    +   * Tests validate Hex color.
    

    We could use the @covers annotation here.

  3. +++ b/core/tests/Drupal/Tests/Component/Utility/ColorTest.php
    @@ -12,6 +12,61 @@
    +   * @return array
    +   *   An array of test data.
    

    We can omit this @return.

The last submitted patch, 2: 3056454-test-only.patch, failed testing. View results

krzysztof domański’s picture

StatusFileSize
new1.29 KB
new2.31 KB

Status: Needs review » Needs work

The last submitted patch, 5: 3056454-5.patch, failed testing. View results

krzysztof domański’s picture

StatusFileSize
new508 bytes
new2.34 KB
krzysztof domański’s picture

Status: Needs work » Needs review
krzysztof domański’s picture

StatusFileSize
new936 bytes
new2.48 KB

We can do the validation with a regural expression.

   public static function validateHex($hex) {
-    // Must be a string.
-    $valid = is_string($hex);
-    // Hash prefix is optional.
-    $hex = ltrim($hex, '#');
-    // Must be either RGB or RRGGBB.
-    $length = mb_strlen($hex);
-    $valid = $valid && ($length === 3 || $length === 6);
-    // Must be a valid hex value.
-    $valid = $valid && ctype_xdigit($hex);
-    return $valid;
+    if (!is_string($hex)) {
+      return FALSE;
+    }
+    return preg_match('/^[#]?([0-9a-fA-F]{3}){1,2}$/', $hex);
   }
john cook’s picture

Status: Needs review » Needs work
Issue tags: +Novice

This looks really good @Krzysztof Domański.

Adding test coverage where there wasn't any before is alway good.

The regex expression is simple enough so it does not need to be commented.

There isn't a test for this code path.

+++ b/core/lib/Drupal/Component/Utility/Color.php
@@ -18,16 +18,10 @@ class Color {
+    if (!is_string($hex)) {
+      return FALSE;
+    }

Adding a test of [FALSE, 123456] (as an integer) to providerTestValidateHex() would then ensure that this code is covered.

Going back to 'needs work' with the 'novice' tag for adding the extra test.

krzysztof domański’s picture

Status: Needs work » Needs review
StatusFileSize
new561 bytes
new1.7 KB
new2.53 KB

The last submitted patch, 11: 3056454-11-test-only.patch, failed testing. View results

john cook’s picture

Status: Needs review » Reviewed & tested by the community
Issue tags: -Novice

Thanks for adding the extra test @Krzysztof Domański.

Everything looks good so I'm removing the tags that are no longer required and setting to RTBC.

The last submitted patch, 11: 3056454-11-test-only.patch, failed testing. View results

krzysztof domański’s picture

StatusFileSize
new497 bytes
new2.54 KB

The validateHex() function should return TRUE or FALSE but the preg_match() function returns 1, 0 or FALSE.

 * @return bool
 *   TRUE if $hex is valid or FALSE if it is not.
 */
public static function validateHex($hex) {
 * @return int|false <b>preg_match</b> returns 1 if the <i>pattern</i>
 * matches given <i>subject</i>, 0 if it does not, or <b>FALSE</b>
 * if an error occurred.
 * @since 4.0
 * @since 5.0
 */
function preg_match ($pattern, $subject, array &$matches = null, $flags = 0, $offset = 0) {}
john cook’s picture

Status: Reviewed & tested by the community » Needs work

Good catch @Krzysztof Domański.

+++ b/core/tests/Drupal/Tests/Component/Utility/ColorTest.php
@@ -13,6 +13,60 @@
+    $this->assertEquals($expected, Color::validateHex($value));

If assertEquals() is changed to assertSame() we can make sure that the returned value is of correct type as well.

Going back to needs work to fix this.

Otherwise it'll be ready for RTBC.

krzysztof domański’s picture

Status: Needs work » Reviewed & tested by the community
StatusFileSize
new585 bytes
new2.54 KB
john cook’s picture

The patch in #17 fixes all the points mentioned here.

The fix for the bug has resulted in shorter code as an understandable regular expression. And good tests covering a range of possible situations has been added to ensure the correct results in the future.

I'm happy for this issue to be RTBC.

larowlan’s picture

adding issue credits

  • larowlan committed de56b25 on 8.8.x
    Issue #3056454 by Krzysztof Domański, John Cook, johndevman: Hexadecimal...

  • larowlan committed 7d1eff9 on 8.7.x
    Issue #3056454 by Krzysztof Domański, John Cook, johndevman: Hexadecimal...
larowlan’s picture

Status: Reviewed & tested by the community » Fixed

Committed de56b25 and pushed to 8.8.x. Thanks!

c/p to 8.7.x

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.