Skip to content
Open
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
23 changes: 19 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ Assertion::nullOrMax(1337, 42); // exception
### All helper

The `Assertion::all*` method checks if all provided values hold for the
assertion. It will throw an exception of the assertion does not hold for one of
assertion. It will throw an exception if the assertion does not hold for one of
the values:

```php
Expand All @@ -91,6 +91,18 @@ Assertion::allIsInstanceOf(array(new \stdClass, new \stdClass), 'stdClass'); //
Assertion::allIsInstanceOf(array(new \stdClass, new \stdClass), 'PDO'); // exception
```

### Some helper

The `Assertion::some*` method checks if at least one of provided values holds
for the assertion. It will throw an exception if the assertion does not hold for
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It will throw an exception if the assertion does not hold for any of the values

all the values:

```php
<?php
Assertion::someIsInstanceOf(array(new \Foo\Bar, new \stdClass), 'stdClass'); // success
Assertion::someIsInstanceOf(array(new \stdClass, new \stdClass), 'PDO'); // exception
```

### Assert::that() Chaining

Using the static API on values is very verbose when checking values against multiple assertions.
Expand All @@ -103,10 +115,12 @@ on the fluent interface. You only have to specify the `$value` once.
Assert::that($value)->notEmpty()->integer();
Assert::that($value)->nullOr()->string()->startsWith("Foo");
Assert::that($values)->all()->float();
Assert::that($values)->some()->boolean();
```

There are also two shortcut function `Assert::thatNullOr()` and `Assert::thatAll()` enabling
the "nullOr" or "all" helper respectively.
There are also shortcut function `Assert::thatNullOr()`, `Assert::thatAll()`
and `Assert::thatSome()` enabling the "nullOr", "all" or "some" helper
respectively.

### Lazy Assertions

Expand Down Expand Up @@ -167,6 +181,7 @@ The following functions exist as aliases to `Assert` static constructors:

- `Assert\that()`
- `Assert\thatAll()`
- `Assert\thatSome()`
- `Assert\thatNullOr()`
- `Assert\lazy()`

Expand Down Expand Up @@ -219,7 +234,7 @@ Assertion::ipv6(string $value, int $flag = null);
Assertion::isArray(mixed $value);
Assertion::isArrayAccessible(mixed $value);
Assertion::isCallable(mixed $value);
Assertion::isCountable(array|Countable|ResourceBundle|SimpleXMLElement $value);
Assertion::isCountable(mixed $value);
Assertion::isInstanceOf(mixed $value, string $className);
Assertion::isJsonString(mixed $value);
Assertion::isObject(mixed $value);
Expand Down
3 changes: 2 additions & 1 deletion bin/MethodDocGenerator.php
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ private function generateMethodDocs($methods, $format, $skipParameterTest, $pref
}
}

if ($prefix === 'all' && strpos($type, 'null') === false && $parameterIndex === 0) {
if (($prefix === 'all' || $prefix === 'some') && strpos($type, 'null') === false && $parameterIndex === 0) {
$type = str_replace('|', '[]|', $type).'[]';
}

Expand Down Expand Up @@ -186,6 +186,7 @@ public function generateAssertionDocs()

$docs = array_merge(
$this->generateMethodDocs($this->gatherAssertions(), ' * @method static bool %s(%s) %s for all values.', $skipParameterTest, 'all'),
$this->generateMethodDocs($this->gatherAssertions(), ' * @method static bool %s(%s) %s for at least one value.', $skipParameterTest, 'some'),
$this->generateMethodDocs($this->gatherAssertions(), ' * @method static bool %s(%s) %s or that the value is null.', $skipParameterTest, 'nullOr')
);

Expand Down
11 changes: 11 additions & 0 deletions lib/Assert/Assert.php
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,17 @@ public static function thatAll($values, $defaultMessage = null, string $defaultP
return static::that($values, $defaultMessage, $defaultPropertyPath)->all();
}

/**
* Start validation on a set of values, requiring at least one of them to be satisfied, returns {@link AssertionChain}.
*
* @param mixed $values
* @param string|callable|null $defaultMessage
*/
public static function thatSome($values, $defaultMessage = null, string $defaultPropertyPath = null): AssertionChain
{
return static::that($values, $defaultMessage, $defaultPropertyPath)->some();
}

/**
* Start validation and allow NULL, returns {@link AssertionChain}.
*
Expand Down
121 changes: 119 additions & 2 deletions lib/Assert/Assertion.php

Large diffs are not rendered by default.

19 changes: 19 additions & 0 deletions lib/Assert/AssertionChain.php
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,13 @@ class AssertionChain
*/
private $all = false;

/**
* Perform assertion on elements of array or traversable until one that satisfies the assertion is found.
*
* @var bool
*/
private $some = false;

/** @var string|Assertion Class to use for assertion calls */
private $assertionClassName = 'Assert\Assertion';

Expand Down Expand Up @@ -196,6 +203,8 @@ public function __call($methodName, $args): AssertionChain

if ($this->all) {
$methodName = 'all'.$methodName;
} elseif ($this->some) {
$methodName = 'some'.$methodName;
}

\call_user_func_array([$this->assertionClassName, $methodName], $args);
Expand All @@ -213,6 +222,16 @@ public function all(): AssertionChain
return $this;
}

/**
* Switch chain into validation mode for an array of values, requiring at least one of them to be satisfied.
*/
public function some(): AssertionChain
{
$this->some = true;

return $this;
}

/**
* Switch chain into mode allowing nulls, ignoring further assertions.
*/
Expand Down
1 change: 1 addition & 0 deletions lib/Assert/LazyAssertion.php
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@
* @method LazyAssertion writeable(string|callable $message = null, string $propertyPath = null) Assert that the value is something writeable.
* @method LazyAssertion all() Switch chain into validation mode for an array of values.
* @method LazyAssertion nullOr() Switch chain into mode allowing nulls, ignoring further assertions.
* @method LazyAssertion some() Switch chain into validation mode for an array of values, requiring at least one of them to be satisfied.
*/
class LazyAssertion
{
Expand Down
12 changes: 12 additions & 0 deletions lib/Assert/functions.php
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,18 @@ function thatAll($values, $defaultMessage = null, string $defaultPropertyPath =
return Assert::thatAll($values, $defaultMessage, $defaultPropertyPath);
}

/**
* Start validation on a set of values, requiring at least one of them to be satisfied, returns {@link AssertionChain}.
*
* @param mixed $values
* @param string|callable|null $defaultMessage
* @param string $defaultPropertyPath
*/
function thatSome($values, $defaultMessage = null, string $defaultPropertyPath = null): AssertionChain
{
return Assert::thatSome($values, $defaultMessage, $defaultPropertyPath);
}

/**
* Start validation and allow NULL, returns {@link AssertionChain}.
*
Expand Down
34 changes: 31 additions & 3 deletions tests/Assert/Tests/AssertTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -1350,9 +1350,8 @@ public function testAllWithComplexAssertionThrowsExceptionOnElementThatFailsAsse
$this->expectException('Assert\AssertionFailedException');
$this->expectExceptionCode(\Assert\Assertion::INVALID_INSTANCE_OF);
Assertion::allIsInstanceOf(
[new stdClass(), new stdClass()],
new class() {
},
[new stdClass(), new Exception()],
stdClass::class,
'Assertion failed',
'foos'
);
Expand All @@ -1364,6 +1363,35 @@ public function testAllWithNoValueThrows()
Assertion::allTrue();
}

public function testSomeWithSimpleAssertion()
{
$this->assertTrue(Assertion::someTrue([false, true, false]));
}

public function testSomeWithSimpleAssertionThrowsExceptionOnIterableThatFailsAssertion()
{
$this->expectException('Assert\AssertionFailedException');
$this->expectExceptionCode(\Assert\Assertion::INVALID_TRUE);
Assertion::someTrue([false, false]);
}

public function testSomeWithComplexAssertion()
{
$this->assertTrue(Assertion::someIsInstanceOf([new Exception(), new stdClass(), new Exception()], stdClass::class));
}

public function testSomeWithComplexAssertionThrowsExceptionOnIterableThatFailsAssertion()
{
$this->expectException('Assert\AssertionFailedException');
$this->expectExceptionCode(\Assert\Assertion::INVALID_INSTANCE_OF);
Assertion::allIsInstanceOf(
[new Exception(), new Exception()],
stdClass::class,
'Assertion failed',
'foos'
);
}

public function testValidCount()
{
$this->assertTrue(Assertion::count(['Hi'], 1));
Expand Down
5 changes: 5 additions & 0 deletions tests/Assert/Tests/AssertionChainFunctionsTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,11 @@ public function testAssertionChainFunctionsThatAllShortcut()
$this->assertInstanceOf(AssertionChain::class, \Assert\thatAll([1, 2, 3])->integer());
}

public function testAssertionChainFunctionsThatSomeShortcut()
{
$this->assertInstanceOf(AssertionChain::class, \Assert\thatSome([1, 2, 3])->integer());
}

public function testAssertionChainFunctionsNullOrShortcut()
{
$this->assertInstanceOf(AssertionChain::class, \Assert\thatNullOr(null)->integer()->eq(10));
Expand Down
5 changes: 5 additions & 0 deletions tests/Assert/Tests/AssertionChainTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,11 @@ public function testAssertionChainThatAllShortcut()
$this->assertInstanceOf(AssertionChain::class, Assert::thatAll([1, 2, 3])->integer());
}

public function testAssertionChainThatSomeShortcut()
{
$this->assertInstanceOf(AssertionChain::class, Assert::thatSome([1, 2, 3])->integer());
}

public function testAssertionChainNullOrShortcut()
{
$this->assertInstanceOf(AssertionChain::class, Assert::thatNullOr(null)->integer()->eq(10));
Expand Down