diff --git a/src/utils/__tests__/PhutilUtilsTestCase.php b/src/utils/__tests__/PhutilUtilsTestCase.php --- a/src/utils/__tests__/PhutilUtilsTestCase.php +++ b/src/utils/__tests__/PhutilUtilsTestCase.php @@ -1008,7 +1008,8 @@ array(null, false, false, false, 'literal null'), array('', false, false, false, 'empty string'), array('x', true, true, true, 'nonempty string'), - array(false, null, null, null, 'bool'), + array(false, null, null, false, 'false bool'), + array(true, null, null, true, 'true bool'), array(1, null, null, true, 'integer'), array($uri, null, true, true, 'uri object'), array(2.5, null, null, true, 'float'), diff --git a/src/utils/utils.php b/src/utils/utils.php --- a/src/utils/utils.php +++ b/src/utils/utils.php @@ -2184,6 +2184,9 @@ * string other than the empty string, integers, and floats are considered * scalar. * + * Note that booleans are also valid scalars, where false is considered empty, + * and true is non-empty since if you cast true to string, it's non-empty. + * * This method raises an exception if passed any other value. * * @param Value to test. @@ -2202,6 +2205,14 @@ return true; } + // Booleans are also valid scalars by PHP. Inventing the opposite can be + // too much esoteric and problematic. + // false: empty, because casted to string becomes '' (empty) + // true: non-empty, because casted to string becomes '1' (non-empty) + if ($value === false || $value === true) { + return $value; + } + if (is_object($value)) { try { $string = phutil_string_cast($value);