webmozarts / assert

Assertions to validate method input/output with nice error messages.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Add a `oneOf` assertion

Taluu opened this issue · comments

As we have all* assertions, having oneOf* assertions could be useful, as in detecting if one element in the collection can be asserted to the given assert.

WDYT ? I'd be glad to make a PR for that.

IMHO I think this should be implemented, yes. I've been working the last couple of weeks on a small project where - unfortunately - I need to handle some validation/checks where (due to some processes that are beyond my source code) might return 2 or 3 potential values, so implement a method like oneOf could simplify these checks.

The already implemented Assert::oneOf($value, $values); asserts in_array($value, $values, true), which is not similar to the all* mechanism (implemented with magic __callStatic) like the README example Assert::allIsInstanceOf($employees, 'Acme\Employee'); (basically equivalent to Assert::isIterable($employees); foreach ($employees as $employee) { Assert::isInstanceOf($employee, 'Acme\Employee'); }).

I guess you rather want an any* mechanism (implemented similar to all*), which would let you test for example Assert::anyIsInstanceOf($objects, 'Acme\Employee');. Something like (inserted here):

        if ('any' === substr($name, 0, 3)) {
            static::isIterable($arguments[0]);

            $method = lcfirst(substr($name, 3));
            $args = $arguments;

            $hasAtLeastOneElement = false;
            $invalidArgumentException = null;

            foreach ($arguments[0] as $entry) {
                $args[0] = $entry;

                $hasAtLeastOneElement = true;

                try {
                    call_user_func_array(array('static', $method), $args);

                    return;
                } catch (InvalidArgumentException $e) {
                    $invalidArgumentException = $e;
                }
            }

            if (!$hasAtLeastOneElement ) {
                static::reportInvalidArgument('Expected at least one element.');
            }

            throw $invalidArgumentException;
        }

I think this is too much of a niche for this library.

However, it is possible to extend the Assert class, and override __callStatic, and add somemething like @guilliamxavier suggested.