Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- <!doctype html>
- <html>
- <head>
- <meta charset="utf-8">
- <title>Boolean Loose Casting Function Tests</title>
- <style>
- table {
- width: 100%;
- }
- td {
- width: 50%;
- border-bottom: 1px solid #ccc;
- }
- td.type {
- width: auto;
- font-weight: bold;
- color: #ccc;
- }
- section {
- margin-bottom: 10em;
- }
- section h1 {
- background-color: #eee;
- }
- .truthy {
- color: limegreen;
- }
- .falsy {
- color: red;
- }
- .null {
- color: orange;
- }
- </style>
- </head>
- <body>
- <h1>Boolean Loose Casting Function Tests</h1>
- <h2>PHP Version <?php echo phpversion(); ?></h2>
- <?php
- error_reporting(-1);
- /**
- * some dummy classes used to create test objects
- */
- class StringyThing {
- private $value;
- public function __construct($value) {
- $this->value = $value;
- }
- public function __toString() {
- return (string) $this->value;
- }
- }
- class CountableThing implements Countable {
- private $values = array();
- public function __construct($values) {
- $this->values = $values;
- }
- public function count() {
- return count($this->values);
- }
- }
- class StringyAndCountableThing implements Countable {
- private $values = array();
- private $value;
- public function __construct($stringy_value, $countable_values) {
- $this->value = $stringy_value;
- $this->values = $countable_values;
- }
- public function count() {
- return count($this->values);
- }
- public function __toString() {
- return (string) $this->value;
- }
- }
- /**
- * runs a test function on all test data, outputting tables of results
- */
- function run_test($test) {
- global $test_data;
- echo '<section>';
- echo '<h1>'.$test.'</h1>';
- foreach($test_data as $set_name => $set) {
- echo '<h2>'.$set_name.'</h2>';
- echo '<table>';
- foreach($set as $index => $value) {
- echo '<tr>';
- echo '<td class="type">';
- echo gettype($value);
- echo '</td>';
- echo '<td class="test-value">';
- // be clever with test values
- if(is_string($index)) {
- // use the index as a placeholder representation
- echo $index;
- } else if(is_resource($value)) {
- echo get_resource_type($value);
- } else {
- var_export($value);
- }
- echo '</td>';
- $result = $test($value);
- $class = ($result ? 'truthy' : 'falsy');
- if(is_null($result)) $class .= ' null';
- echo '<td class="test-result '.$class.'">';
- var_export($result);
- echo '</td>';
- echo '</tr>';
- }
- echo '</table>';
- }
- echo '</section>';
- };
- /**
- * data to run through for all tests
- * string keys in subarrays can be used to represent values in test output
- */
- $test_data = array(
- 'ought to be true' => array(
- true,
- 1,
- 'true',
- 'yes',
- 'YES',
- 'on',
- '1',
- 'y',
- 'this should probably be TRUE',
- 'รก',
- 100,
- 0.1,
- -1,
- INF,
- -INF,
- // for performance testing more than anything else
- // depending on the length used, may hit PHP's memory limit
- // http://www.php.net/manual/en/ini.core.php#ini.memory-limit
- // '(A VERY LONG STRING)' => str_repeat('.', 100000000),
- array(1),
- array('a key' => true),
- array(null => true),
- simplexml_load_string('<test>i have content</test>'),
- new StringyThing(true),
- new StringyThing('true'),
- new StringyThing('a string'),
- new CountableThing(array(1, 2, 3)),
- new CountableThing('count() returns 1 for this'),
- new StringyAndCountableThing(true, array(true)),
- ),
- 'ought to be false' => array(
- false,
- 0,
- 0.0,
- (float) '-0',
- '0',
- '',
- 'no',
- 'off',
- 'OFF',
- 'false',
- array(),
- // this is explicitly mentioned to be false in the manual:
- // http://www.php.net/manual/en/language.types.boolean.php#language.types.boolean.casting
- simplexml_load_string('<test></test>'),
- new StringyThing(false),
- new StringyThing('no'),
- new StringyThing(''),
- new CountableThing(array()),
- new StringyAndCountableThing(false, array()),
- ),
- 'iffy' => array(
- null,
- NAN,
- // the list of things like this could go on forever (not even taking translations into account)
- 'null',
- 'n',
- 'unset',
- 'nothing',
- 'nil',
- 'nope',
- // equivalent to an empty string in ini directives
- 'none',
- 'NONE',
- // this is not falsy in PHP (even though '0' is)
- '0.0',
- '0x0',
- ' ',
- 'PHP_EOL' => PHP_EOL,
- '"\t"' => "\t",
- // mixed signals, should countability or string value take precedence (or should these be null)?
- new StringyAndCountableThing(false, array(true)),
- new StringyAndCountableThing('yes', array()),
- // in PHP4 this would have been consider falsy
- new stdClass(),
- // could check for a ->scalar property to handle this case
- (object) false,
- array(false),
- array(null),
- array('a key' => false),
- array(null => false),
- // give these readable keys since var_export is not helpful for anonymous functions
- 'function() {}' => function() {},
- 'function() { return false; }' => function() { return false; },
- 'function() { return true; }' => function() { return true; },
- "function() { return 'no'; }" => function() { return 'no'; },
- "function() { return 'on'; }" => function() { return 'on'; },
- "function() { return 'something completely different'; }" => function() { return 'something completely different'; },
- // resources
- xml_parser_create(),
- fopen(__FILE__, 'r'),
- ),
- );
- /**
- * functions to run tests with
- */
- // PHP's built in behavior for things like if($value)
- function typecast($value) {
- return (boolean) $value;
- }
- function filter_var_bool($value) {
- return filter_var($value, FILTER_VALIDATE_BOOLEAN, FILTER_NULL_ON_FAILURE);
- }
- // see http://us2.php.net/manual/en/filter.filters.validate.php#108218
- // and https://bugs.php.net/bug.php?id=49510
- function filter_var_bool_with_null_fallback($value) {
- $filtered = filter_var($value, FILTER_VALIDATE_BOOLEAN, FILTER_NULL_ON_FAILURE);
- if(is_null($filtered)) return (boolean) $value;
- else return $filtered;
- }
- // from http://www.php.net/manual/en/function.is-bool.php#93165
- function kim_s_solution($var){
- if(is_bool($var)){
- return $var;
- } else if($var === NULL || $var === 'NULL' || $var === 'null'){
- return false;
- } else if(is_string($var)){
- $var = trim($var);
- if($var=='false'){ return false;
- } else if($var=='true'){ return true;
- } else if($var=='no'){ return false;
- } else if($var=='yes'){ return true;
- } else if($var=='off'){ return false;
- } else if($var=='on'){ return true;
- } else if($var==''){ return false;
- } else if(ctype_digit($var)){
- if((int) $var)
- return true;
- else
- return false;
- } else { return true; }
- /* NOTE: i changed these lines from the original code. string casting results in an error for some objects, and handling floats correctly is a good idea anyway.
- } else if(ctype_digit((string) $var)){
- if((int) $var)
- */
- } else if(is_numeric($var)){
- if((float) $var)
- /* end of changed lines */
- return true;
- else
- return false;
- } else if(is_array($var)){
- if(count($var))
- return true;
- else
- return false;
- } else if(is_object($var)){
- return true;// No reason to (bool) an object, we assume OK for crazy logic
- } else {
- return true;// Whatever came though must be something, OK for crazy logic
- }
- }
- function custom_solution($value) {
- // FIXME? if an object is both countable and string-castable, this will favor the count over the string value.
- // which should take precedence (if any)? maybe it should return null if there are mixed signals? or true?
- if(is_array($value) || $value instanceof Countable) {
- return (boolean) count($value);
- } else if(is_string($value) || is_object($value) && method_exists($value, '__toString')) {
- $value = (string) $value;
- // see http://www.php.net/manual/en/filter.filters.validate.php#108218
- // see https://bugs.php.net/bug.php?id=49510
- $filtered = filter_var($value, FILTER_VALIDATE_BOOLEAN, FILTER_NULL_ON_FAILURE);
- if(!is_null($filtered)) {
- return $filtered;
- } else {
- // "none" gets special treatment to be consistent with ini file behavior.
- // see documentation in php.ini for more information, in part it says:
- // "An empty string can be denoted by simply not writing anything after
- // the equal sign, or by using the None keyword".
- if(strtolower($value) === 'none') {
- $value = '';
- }
- return (boolean) $value;
- }
- } else {
- return (boolean) $value;
- }
- }
- /**
- * test the various solutions
- */
- run_test('typecast');
- run_test('filter_var_bool');
- run_test('filter_var_bool_with_null_fallback');
- run_test('kim_s_solution');
- run_test('custom_solution');
- ?>
- </body>
- </html>
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement