Test if Something is an Integer
Posted: Mon Apr 23, 2007 5:11 am
So I was going to write a validation to test if something was an integer and I ended up writing this massive thing.
I'm curious, is there any way this could be improved?and the unit testTests were written first.
I'm curious, is there any way this could be improved?
Code: Select all
<?php
require_once 'Tilling/Validation/Exception.php';
/**
* Validation to test if a string is intergal
*/
class Tilling_Validation_Test_Intergal
{
/**
* @var int|string
*/
private $_maxInt = PHP_INT_MAX;
/**
* Test whether a value is an integer
*
* @param array $testSubjects strings to test
* @param bool $signed set to false if only unsigned is allowed
* @param int|string $maxInt the maximum integer size, if you do not have BC math installed this cannot be larger than PHP_INT_MAX
* @return bool
*/
public function invoke(array $testSubjects, $signed = false, $maxInt = PHP_INT_MAX)
{
$this->_maxInt = $maxInt;
$call = $signed ? '_signed' : '_unsigned';
foreach ($testSubjects as $testSubject) {
if (!$this->$call((string)$testSubject)) {
return false;
}
}
return true;
}
/**
* Test if a signed integer string is intergal
*
* @uses _unsigned()
* @param string $testSubject
* @return bool
*/
private function _signed($testSubject)
{
if ($this->_unsigned($testSubject)) {
return true;
}
// Multibyte safe: Testing for single byte character
if ($testSubject[0] == '-' && $this->_unsigned(substr($testSubject, 1))) {
return true;
}
return false;
}
/**
* Test if a unsigned integer string is intergal
*
* @throws Tilling_Validation_Exception if bcmath is required but no available
* @param string $testSubject
* @return bool
*/
private function _unsigned($testSubject)
{
if (!ctype_digit($testSubject)) {
// its obviously false if it contains non-digit characters
return false;
}
if (is_int($this->_maxInt) && $this->_maxInt < PHP_INT_MAX) {
// normal comparison is fine
return $testSubject <= $this->_maxInt;
}
if ($this->_maxInt == PHP_INT_MAX) { // different rules for checking overflow
// if its got the value of PHP_INT_MAX as a string then it's fine
if ((string)$this->_maxInt === (string)$testSubject) {
return true;
}
// if when cast to an integer it becomes PHP_INT_MAX this is an
// indication that it was formerly out of range
if ((int)$testSubject === $this->_maxInt) {
return false;
}
return true;
}
// $this->_maxInt is greater than PHP natively handles
// so we have to use bcmath
if (!extension_loaded('bcmath')) {
$errStr = 'Cannot compare number greater than PHP_INT_MAX without bcmath loaded';
throw new Tilling_Validation_Exception($errStr);
}
return bccomp($testSubject, $this->_maxInt, 0) < 1; // 0 or -1 are valid
}
}Code: Select all
<?php
require_once 'Tilling/Validation/Test/Intergal.php';
class Tilling_Validation_Test_Intergal_Test extends Tilling_Test_Case
{
/**
* @var Tilling_Validation_Test_Intergal
*/
public $inst;
public function setUp()
{
$this->inst = new Tilling_Validation_Test_Intergal();
}
public function testDigitsOnly()
{
$this->assertTrue($this->inst->invoke(array('1', '5', '94254334534'), false));
$this->assertFalse($this->inst->invoke(array('1', '5', '9a'), false));
$this->assertTrue($this->inst->invoke(array('1', '5', '94254334534'), true));
$this->assertFalse($this->inst->invoke(array('1', '5', '9a'), true));
}
public function testSignChar()
{
$this->assertFalse($this->inst->invoke(array('-1'), false));
$this->assertFalse($this->inst->invoke(array('1-'), false));
$this->assertTrue($this->inst->invoke(array('-1'), true));
$this->assertFalse($this->inst->invoke(array('1-'), true));
}
public function testWithinStorableRange()
{
$this->assertFalse($this->inst->invoke(array('99999999999999999999999')));
$this->assertFalse($this->inst->invoke(array('-99999999999999999999999'), true));
$this->assertTrue($this->inst->invoke(array(PHP_INT_MAX)));
$this->assertTrue($this->inst->invoke(array(-PHP_INT_MAX), true));
}
public function testCustomMaxLessThanPHP_INT_MAX()
{
$this->assertFalse($this->inst->invoke(array(500), false, 499));
$this->assertFalse($this->inst->invoke(array(-1), false, 499));
$this->assertTrue($this->inst->invoke(array(499), false, 499));
$this->assertFalse($this->inst->invoke(array(-499), false, 499));
$this->assertTrue($this->inst->invoke(array(-499), true, 499));
$this->assertFalse($this->inst->invoke(array(-500), true, 499));
$this->assertFalse($this->inst->invoke(array(500), true, 499));
}
public function testCustomMaxMoreThanPHP_INT_MAX()
{
if (extension_loaded('bcmath')) {
$this->assertTrue($this->inst->invoke(array('9999999999999'), false, $max = '9999999999999'));
$this->assertTrue($this->inst->invoke(array('9999999999998'), false, $max));
$this->assertFalse($this->inst->invoke(array('10000000000000'), false, $max));
} else {
$this->expectException();
$this->inst->invoke(array(1), false, '999999999999999');
}
}
}