Skip to content

Commit 4836d87

Browse files
author
Michael Petri
committed
Initial commit
0 parents  commit 4836d87

9 files changed

+267
-0
lines changed

.gitignore

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
vendor
2+
composer.lock

.gitlab-ci.yml

+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
image: php:7
2+
3+
cache:
4+
paths:
5+
- vendor/
6+
7+
before_script:
8+
- apt-get update -yqq
9+
- apt-get install -yqq git zip gzip
10+
# Install & enable Xdebug for code coverage reports
11+
- pecl install xdebug
12+
- docker-php-ext-enable xdebug
13+
# Install and run Composer
14+
- curl -sS https://getcomposer.org/installer | php
15+
- php composer.phar install
16+
17+
test:
18+
script:
19+
- vendor/bin/phpunit --configuration phpunit.xml --coverage-text --colors=never

LICENSE.md

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
MIT License
2+
3+
Copyright (c) 2020 Michael Petri
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.

README.md

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
# Typed Input
2+
3+
Installation:
4+
```
5+
composer require michaelpetri/typed-input
6+
```
7+
8+
Usage:
9+
```
10+
$typedInput = TypedInput::fromInput($input);
11+
12+
echo $typedInput->getOption('my-option')->asNonEmptyString();
13+
echo $typedInput->getArgument('my-argument')->asInteger();
14+
```

composer.json

+30
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
{
2+
"name": "michaelpetri/typed-input",
3+
"description": "Type safe input wrapper for symfony input",
4+
"authors": [
5+
{
6+
"name": "Michael Petri",
7+
"email": "[email protected]"
8+
}
9+
],
10+
"license": "MIT",
11+
"require": {
12+
"php": "^7.0",
13+
"symfony/console": "^4.0",
14+
"webmozart/assert": "^1.8"
15+
},
16+
"require-dev": {
17+
"phpunit/phpunit": "^9.2",
18+
"roave/security-advisories": "dev-master"
19+
},
20+
"autoload": {
21+
"psr-4": {
22+
"MichaelPetri\\TypedInput\\": "src/"
23+
}
24+
},
25+
"autoload-dev": {
26+
"psr-4": {
27+
"MichaelPetri\\TypedInput\\Tests\\": "tests/"
28+
}
29+
}
30+
}

phpunit.xml

+26
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
3+
<!-- https://phpunit.de/manual/current/en/appendixes.configuration.html -->
4+
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
5+
xsi:noNamespaceSchemaLocation="vendor/phpunit/phpunit/phpunit.xsd"
6+
backupGlobals="false"
7+
colors="true"
8+
failOnWarning="true"
9+
failOnRisky="true"
10+
>
11+
<php>
12+
<ini name="error_reporting" value="-1"/>
13+
</php>
14+
15+
<testsuites>
16+
<testsuite name="all">
17+
<directory>tests/</directory>
18+
</testsuite>
19+
</testsuites>
20+
21+
<filter>
22+
<whitelist>
23+
<directory>src</directory>
24+
</whitelist>
25+
</filter>
26+
</phpunit>

src/TypedInput.php

+33
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
<?php
2+
3+
namespace MichaelPetri\TypedInput;
4+
5+
use Symfony\Component\Console\Input\InputInterface;
6+
7+
final class TypedInput
8+
{
9+
/**
10+
* @var InputInterface
11+
*/
12+
private $input;
13+
14+
private function __construct(InputInterface $input)
15+
{
16+
$this->input = $input;
17+
}
18+
19+
public static function fromInput(InputInterface $input): self
20+
{
21+
return new self($input);
22+
}
23+
24+
public function getOption(string $name): Value
25+
{
26+
return new Value($this->input->getOption($name));
27+
}
28+
29+
public function getArgument(string $name): Value
30+
{
31+
return new Value($this->input->getArgument($name));
32+
}
33+
}

src/Value.php

+55
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
<?php
2+
3+
namespace MichaelPetri\TypedInput;
4+
5+
use Webmozart\Assert\Assert;
6+
7+
final class Value
8+
{
9+
private $value;
10+
11+
public function __construct($value)
12+
{
13+
$this->value = $value;
14+
}
15+
16+
public function asInteger(): int
17+
{
18+
$value = (int) $this->value;
19+
Assert::integer($value);
20+
21+
return $value;
22+
}
23+
24+
/**
25+
* @return array<int, string>|string[]
26+
*/
27+
public function asNonEmptyStrings(): array
28+
{
29+
$values = array_map(
30+
static function ($value): string {
31+
return (string) $value;
32+
},
33+
$this->value
34+
);
35+
Assert::allStringNotEmpty($values);
36+
37+
return $values;
38+
}
39+
40+
public function asNonEmptyString(): string
41+
{
42+
$value = (string) $this->value;
43+
Assert::stringNotEmpty($value);
44+
45+
return $value;
46+
}
47+
48+
public function asString(): string
49+
{
50+
$value = (string) $this->value;
51+
Assert::string($value);
52+
53+
return $value;
54+
}
55+
}

tests/ValueTest.php

+67
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace MichaelPetri\TypedInput\Tests;
6+
7+
use InvalidArgumentException;
8+
use MichaelPetri\TypedInput\Value;
9+
use PHPUnit\Framework\TestCase;
10+
11+
final class ValueTest extends TestCase
12+
{
13+
14+
public function testAsNonEmptyString()
15+
{
16+
$raw = 'non-empty-string';
17+
$value = new Value($raw);
18+
self::assertEquals($raw, $value->asNonEmptyString());
19+
20+
$raw = ' ';
21+
$value = new Value($raw);
22+
self::assertEquals($raw, $value->asNonEmptyString());
23+
}
24+
25+
public function testFailAsNonEmptyString()
26+
{
27+
$value = new Value('');
28+
$this->expectException(InvalidArgumentException::class);
29+
$value->asNonEmptyString();
30+
}
31+
32+
public function testAsNonEmptyStrings()
33+
{
34+
$raws = ['non-empty-string-1', 'non-empty-string-2'];
35+
$value = new Value($raws);
36+
self::assertEquals($raws, $value->asNonEmptyStrings());
37+
}
38+
39+
public function testFailAsNonEmptyStrings()
40+
{
41+
$value = new Value(['non-empty-string', '']);
42+
$this->expectException(InvalidArgumentException::class);
43+
$value->asNonEmptyStrings();
44+
}
45+
46+
public function testAsString()
47+
{
48+
$raw = '';
49+
$value = new Value($raw);
50+
self::assertEquals($raw, $value->asString());
51+
52+
$raw = 'non-empty-string';
53+
$value = new Value($raw);
54+
self::assertEquals($raw, $value->asString());
55+
56+
$raw = 1;
57+
$value = new Value($raw);
58+
self::assertEquals((string) $raw, $value->asString());
59+
}
60+
61+
public function testAsInteger()
62+
{
63+
$raw = 1;
64+
$value = new Value($raw);
65+
self::assertEquals($raw, $value->asInteger());
66+
}
67+
}

0 commit comments

Comments
 (0)