Skip to content
Merged
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
46 changes: 46 additions & 0 deletions docs/validators.md
Original file line number Diff line number Diff line change
Expand Up @@ -496,6 +496,52 @@ this string is 28 characters
Result was valid
```

### IntString

Validates that input is a integer string. For an input to be considered valid it MUST be a string, and that string
MUST be an integer.

For non-numeric strings refer to [IsString](#isstring).

For non-string numbers, refer to [IsFloat](#isfloat), [IsInt](#isint) and [IsNumber](#isnumber).

**Example**

```php
<?php
use Membrane\Validator\String\IntString;

$examples = [
'1',
'1.0',
'five',
5,
];

$intString = new IntString()

foreach ($examples as $example) {
$result = $intString->validate($example);

echo "json_encode($result->value) is" . ($result->isValid() ? 'valid' : 'invalid') . "\n";
foreach($result->messageSets[0]->messages as $message) {
echo "\t $message->rendered() \n";
}
}
```

The above example will output:

```text
"1" is valid
"1.0" is invalid
- String value must be an integer.
"five" is invalid
- String value must be an integer.
5 is invalid
- string value expected, integer provided
```

### NumericString

Validates that input is a numeric string. For an input to be considered valid it MUST be a string, and that string
Expand Down
38 changes: 38 additions & 0 deletions src/Validator/String/IntString.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
<?php

declare(strict_types=1);

namespace Membrane\Validator\String;

use Membrane\Result\Message;
use Membrane\Result\MessageSet;
use Membrane\Result\Result;
use Membrane\Validator;

class IntString implements Validator
{
public function __toString(): string
{
return 'is a string of an integer';
}

public function __toPHP(): string
{
return sprintf('new %s()', self::class);
}

public function validate(mixed $value): Result
{
if (!is_string($value)) {
$message = new Message('String value expected, %s provided.', [gettype($value)]);
return Result::invalid($value, new MessageSet(null, $message));
}

if (!is_numeric($value) || $value !== (string)(int)$value) {
$message = new Message('String value must be an integer.', []);
return Result::invalid($value, new MessageSet(null, $message));
}

return Result::valid($value);
}
}
80 changes: 80 additions & 0 deletions tests/Validator/String/IntStringTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
<?php

declare(strict_types=1);

namespace Validator\String;

use Membrane\Result\Message;
use Membrane\Result\MessageSet;
use Membrane\Result\Result;
use Membrane\Validator\String\IntString;
use PHPUnit\Framework\Attributes\CoversClass;
use PHPUnit\Framework\Attributes\DataProvider;
use PHPUnit\Framework\Attributes\Test;
use PHPUnit\Framework\Attributes\TestDox;
use PHPUnit\Framework\Attributes\UsesClass;
use PHPUnit\Framework\TestCase;

#[CoversClass(IntString::class)]
#[UsesClass(Result::class)]
#[UsesClass(MessageSet::class)]
#[UsesClass(Message::class)]
class IntStringTest extends TestCase
{
#[Test]
public function toStringTest(): void
{
self::assertSame('is a string of an integer', (new IntString())->__toString());
}

#[Test]
public function toPHPTest(): void
{
$sut = new IntString();

$actual = $sut->__toPHP();

self::assertEquals($sut, eval('return ' . $actual . ';'));
}

public static function provideValuesToValidate(): array
{
$notStringTestCase = fn(mixed $value) => [
Result::invalid(
$value,
new MessageSet(null, new Message('String value expected, %s provided.', [gettype($value)]))
),
$value,
];

$notIntStringCase = fn(string $value) => [
Result::invalid(
$value,
new MessageSet(null, new Message('String value must be an integer.', []))
),
$value,
];

return [
'boolean' => $notStringTestCase(true),
'null' => $notStringTestCase(null),
'integer' => $notStringTestCase(5),
'float' => $notStringTestCase(5.5),
'array' => $notStringTestCase(['5.5']),
'alphabetical string' => $notIntStringCase('abcdefghijklmnopqrstuvwxyz'),
'boolean string' => $notIntStringCase('false'),
'float string with non-numeric prefix' => $notIntStringCase('Sir 4'),
'float string with non-numeric suffix' => $notIntStringCase('4 Bsc (Hons)'),
'float string' => $notIntStringCase('5.5'),
'float, that is equivalent to an integer, string' => $notIntStringCase('5.0'),
'integer string' => [Result::valid('5'), '5'],
];
}

#[Test, TestDox('Only strings of floating point numbers will be considered valid')]
#[DataProvider('provideValuesToValidate')]
public function validatesFloatStrings(Result $expected, mixed $value): void
{
self::assertEquals($expected, (new IntString())->validate($value));
}
}