Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Loading…

[stdlib] Add guard utils and traits #5365

Merged
merged 1 commit into from

6 participants

@texdc

The check for array or Traversable code is littered throughout the framework. This is a prime opportunity for a trait. Included a couple extra traits for good measure.

For example, https://github.com/zendframework/zf2/blob/master/library/Zend/Form/Fieldset.php#L297 could be:

class Fieldset extends Element implements FieldsetInterface
{
    use \Zend\Stdlib\Guard\ArrayOrTraversableGuardTrait;

    // ...

    public function setMessages($messages)
    {
        // php 5.4
        $this->guardForArrayOrTraversable(
            $messages, 'Messages', 'Zend\Form\Exception\InvalidArgumentException'
        );

        // or php 5.3
        \Zend\Stdlib\Guard\GuardUtils::guardForArrayOrTraversable(
            $messages, 'Messages', 'Zend\Form\Exception\InvalidArgumentException'
        );

        foreach ($messages as $elementName => $elementMessages) {
            $this->get($elementName)->setMessages($elementMessages);
        }

        return $this;
    }

    // ...

}

Please see http://verraes.net/2013/09/extract-till-you-drop/
Note: resubmitting to clean up failed rebase.

@texdc texdc Add Guard Traits
The GuardUtils can be used now.  The traits are for php >= 5.4 only.
b393e2f
@macnibblet

Zend framework has a minimum requirement of PHP 5.3, introducing traits in core components will cause a BC which is not accepted until zf3

@ClemensSahs

He write this for 5.3 too. the \Zend\Stdlib\Guard\GuardUtils is for php5.3 implementation.

:thumbsup:

@ClemensSahs

@texdc
I currently implement some more guard method's and I think we need perhaps a custom message as argument.
example case:

if (!extension_loaded('gd')) {
   throw new Exception\ExtensionNotLoadedException(
      'GD extension is required to use numeric font'
   );
}

here we want say why we required this Extension. But if we use custom messages will we want format the message with sprintf, too? If yes we need a "position specifier" for each guardMethode.

like:


    /**
     * Verifies that the data is an array or Traversable
     *
     * $message has tow placeholder:
     * - %1$s give the $dataName
     * - %2$s give the class or the type of $data
     *
     * @param  mixed  $data           the data to verify
     * @param  string $dataName       the data name
     * @param  string $exceptionClass FQCN for the exception
     * @param  string $message      Message format string
     * @throws \Exception
     */
    protected function guardForArrayOrTraversable(
        $data,
        $dataName = 'Argument',
        $exceptionClass = 'Zend\Stdlib\Exception\InvalidArgumentException',
        $message = '%1$s must be an array or Traversable, [%2$s] given'
    ) {
        if (!is_array($data) && !($data instanceof \Traversable)) {
            $message = sprintf(
                $message,
                $dataName,
                is_object($data) ? get_class($data) : gettype($data)
            );
            throw new $exceptionClass($message);
        }
    }
@texdc
@weierophinney weierophinney commented on the diff
library/Zend/Stdlib/Guard/NullGuardTrait.php
((16 lines not shown))
+{
+
+ /**
+ * Verify that the data is not null
+ *
+ * @param mixed $data the data to verify
+ * @param string $dataName the data name
+ * @param string $exceptionClass FQCN for the exception
+ * @throws \Exception
+ */
+ protected function guardAgainstNull(
+ $data,
+ $dataName = 'Argument',
+ $exceptionClass = 'Zend\Stdlib\Exception\InvalidArgumentException'
+ ) {
+ if (is_null($data)) {
@weierophinney Owner

use null === $data here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
@weierophinney weierophinney commented on the diff
...ry/Zend/Stdlib/Guard/ArrayOrTraversableGuardTrait.php
((16 lines not shown))
+{
+
+ /**
+ * Verifies that the data is an array or Traversable
+ *
+ * @param mixed $data the data to verify
+ * @param string $dataName the data name
+ * @param string $exceptionClass FQCN for the exception
+ * @throws \Exception
+ */
+ protected function guardForArrayOrTraversable(
+ $data,
+ $dataName = 'Argument',
+ $exceptionClass = 'Zend\Stdlib\Exception\InvalidArgumentException'
+ ) {
+ if (!is_array($data) && !($data instanceof \Traversable)) {
@weierophinney Owner

Import Traversable so it does not need to be globally qualified here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
@weierophinney weierophinney commented on the diff
library/Zend/Stdlib/Guard/GuardUtils.php
((23 lines not shown))
+
+
+ /**
+ * Verifies that the data is an array or Traversable
+ *
+ * @param mixed $data the data to verify
+ * @param string $dataName the data name
+ * @param string $exceptionClass FQCN for the exception
+ * @throws \Exception
+ */
+ public static function guardForArrayOrTraversable(
+ $data,
+ $dataName = 'Argument',
+ $exceptionClass = self::DEFAULT_EXCEPTION_CLASS
+ ) {
+ if (!is_array($data) && !($data instanceof \Traversable)) {
@weierophinney Owner

Import Traversable

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
@weierophinney

Overall, I like this. I'm going to go ahead and merge, with changes as noted. @texdc -- would you be willing to start coming through individual components and submitting PRs that incorporate this? I like the idea of reducing boilerplate code. If you do, do a PR per component, as that will be easier to review.

@weierophinney weierophinney merged commit b393e2f into from
@weierophinney weierophinney was assigned
@texdc
@arekkas

Would guards against int, string, numeric make sense?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Oct 27, 2013
  1. @texdc

    Add Guard Traits

    texdc authored
    The GuardUtils can be used now.  The traits are for php >= 5.4 only.
This page is out of date. Refresh to see the latest.
View
22 library/Zend/Stdlib/Guard/AllGuardsTrait.php
@@ -0,0 +1,22 @@
+<?php
+/**
+ * Zend Framework (http://framework.zend.com/)
+ *
+ * @link http://github.com/zendframework/zf2 for the canonical source repository
+ * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license http://framework.zend.com/license/new-bsd New BSD License
+ */
+
+namespace Zend\Stdlib\Guard;
+
+/**
+ * An aggregate for all guard traits
+ */
+trait AllGuardsTrait
+{
+
+ use ArrayOrTraversableGuardTrait;
+ use EmptyGuardTrait;
+ use NullGuardTrait;
+
+}
View
41 library/Zend/Stdlib/Guard/ArrayOrTraversableGuardTrait.php
@@ -0,0 +1,41 @@
+<?php
+/**
+ * Zend Framework (http://framework.zend.com/)
+ *
+ * @link http://github.com/zendframework/zf2 for the canonical source repository
+ * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license http://framework.zend.com/license/new-bsd New BSD License
+ */
+
+namespace Zend\Stdlib\Guard;
+
+/**
+ * Provide a guard method for array or Traversable data
+ */
+trait ArrayOrTraversableGuardTrait
+{
+
+ /**
+ * Verifies that the data is an array or Traversable
+ *
+ * @param mixed $data the data to verify
+ * @param string $dataName the data name
+ * @param string $exceptionClass FQCN for the exception
+ * @throws \Exception
+ */
+ protected function guardForArrayOrTraversable(
+ $data,
+ $dataName = 'Argument',
+ $exceptionClass = 'Zend\Stdlib\Exception\InvalidArgumentException'
+ ) {
+ if (!is_array($data) && !($data instanceof \Traversable)) {
@weierophinney Owner

Import Traversable so it does not need to be globally qualified here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
+ $message = sprintf(
+ "%s must be an array or Traversable, [%s] given",
+ $dataName,
+ is_object($data) ? get_class($data) : gettype($data)
+ );
+ throw new $exceptionClass($message);
+ }
+ }
+
+}
View
37 library/Zend/Stdlib/Guard/EmptyGuardTrait.php
@@ -0,0 +1,37 @@
+<?php
+/**
+ * Zend Framework (http://framework.zend.com/)
+ *
+ * @link http://github.com/zendframework/zf2 for the canonical source repository
+ * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license http://framework.zend.com/license/new-bsd New BSD License
+ */
+
+namespace Zend\Stdlib\Guard;
+
+/**
+ * Provide a guard method against empty data
+ */
+trait EmptyGuardTrait
+{
+
+ /**
+ * Verify that the data is not empty
+ *
+ * @param mixed $data the data to verify
+ * @param string $dataName the data name
+ * @param string $exceptionClass FQCN for the exception
+ * @throws \Exception
+ */
+ protected function guardAgainstEmpty(
+ $data,
+ $dataName = 'Argument',
+ $exceptionClass = 'Zend\Stdlib\Exception\InvalidArgumentException'
+ ) {
+ if (empty($data)) {
+ $message = sprintf('%s cannot be empty', $dataName);
+ throw new $exceptionClass($message);
+ }
+ }
+
+}
View
86 library/Zend/Stdlib/Guard/GuardUtils.php
@@ -0,0 +1,86 @@
+<?php
+/**
+ * Zend Framework (http://framework.zend.com/)
+ *
+ * @link http://github.com/zendframework/zf2 for the canonical source repository
+ * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license http://framework.zend.com/license/new-bsd New BSD License
+ */
+
+namespace Zend\Stdlib\Guard;
+
+/**
+ * Static guard helper class
+ *
+ * Bridges the gap for allowing refactoring until traits can be used by default.
+ *
+ * @deprecated
+ */
+abstract class GuardUtils
+{
+
+ const DEFAULT_EXCEPTION_CLASS = 'Zend\Stdlib\Exception\InvalidArgumentException';
+
+
+ /**
+ * Verifies that the data is an array or Traversable
+ *
+ * @param mixed $data the data to verify
+ * @param string $dataName the data name
+ * @param string $exceptionClass FQCN for the exception
+ * @throws \Exception
+ */
+ public static function guardForArrayOrTraversable(
+ $data,
+ $dataName = 'Argument',
+ $exceptionClass = self::DEFAULT_EXCEPTION_CLASS
+ ) {
+ if (!is_array($data) && !($data instanceof \Traversable)) {
@weierophinney Owner

Import Traversable

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
+ $message = sprintf(
+ '%s must be an array or Traversable, [%s] given',
+ $dataName,
+ is_object($data) ? get_class($data) : gettype($data)
+ );
+ throw new $exceptionClass($message);
+ }
+ }
+
+ /**
+ * Verify that the data is not empty
+ *
+ * @param mixed $data the data to verify
+ * @param string $dataName the data name
+ * @param string $exceptionClass FQCN for the exception
+ * @throws \Exception
+ */
+ public static function guardAgainstEmpty(
+ $data,
+ $dataName = 'Argument',
+ $exceptionClass = self::DEFAULT_EXCEPTION_CLASS
+ ) {
+ if (empty($data)) {
+ $message = sprintf('%s cannot be empty', $dataName);
+ throw new $exceptionClass($message);
+ }
+ }
+
+ /**
+ * Verify that the data is not null
+ *
+ * @param mixed $data the data to verify
+ * @param string $dataName the data name
+ * @param string $exceptionClass FQCN for the exception
+ * @throws \Exception
+ */
+ public static function guardAgainstNull(
+ $data,
+ $dataName = 'Argument',
+ $exceptionClass = self::DEFAULT_EXCEPTION_CLASS
+ ) {
+ if (is_null($data)) {
+ $message = sprintf('%s cannot be null', $dataName);
+ throw new $exceptionClass($message);
+ }
+ }
+
+}
View
37 library/Zend/Stdlib/Guard/NullGuardTrait.php
@@ -0,0 +1,37 @@
+<?php
+/**
+ * Zend Framework (http://framework.zend.com/)
+ *
+ * @link http://github.com/zendframework/zf2 for the canonical source repository
+ * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license http://framework.zend.com/license/new-bsd New BSD License
+ */
+
+namespace Zend\Stdlib\Guard;
+
+/**
+ * Provide a guard method against null data
+ */
+trait NullGuardTrait
+{
+
+ /**
+ * Verify that the data is not null
+ *
+ * @param mixed $data the data to verify
+ * @param string $dataName the data name
+ * @param string $exceptionClass FQCN for the exception
+ * @throws \Exception
+ */
+ protected function guardAgainstNull(
+ $data,
+ $dataName = 'Argument',
+ $exceptionClass = 'Zend\Stdlib\Exception\InvalidArgumentException'
+ ) {
+ if (is_null($data)) {
@weierophinney Owner

use null === $data here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
+ $message = sprintf('%s cannot be null', $dataName);
+ throw new $exceptionClass($message);
+ }
+ }
+
+}
View
54 tests/ZendTest/Stdlib/Guard/ArrayOrTraversableGuardTraitTest.php
@@ -0,0 +1,54 @@
+<?php
+/**
+ * Zend Framework (http://framework.zend.com/)
+ *
+ * @link http://github.com/zendframework/zf2 for the canonical source repository
+ * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license http://framework.zend.com/license/new-bsd New BSD License
+ */
+
+namespace ZendTest\Stdlib\Guard;
+
+use PHPUnit_Framework_TestCase as TestCase;
+use ZendTest\Stdlib\TestAsset\GuardedObject;
+use Zend\Stdlib\ArrayObject;
+
+/**
+ * @requires PHP 5.4
+ * @group Zend_StdLib_Guard
+ * @covers Zend\Stdlib\Guard\ArrayOrTraversableGuardTrait
+ */
+class ArrayOrTraversableGuardTraitTest extends TestCase
+{
+
+ public function setUp()
+ {
+ if (version_compare(PHP_VERSION, '5.4.0', '<')) {
+ $this->markTestSkipped('Only valid for php >= 5.4');
+ }
+ }
+
+ public function testGuardForArrayOrTraversableThrowsException()
+ {
+ $object = new GuardedObject;
+ $this->setExpectedException(
+ 'Zend\Stdlib\Exception\InvalidArgumentException',
+ 'Argument must be an array or Traversable, [string] given'
+ );
+ $object->setArrayOrTraversable('');
+ }
+
+ public function testGuardForArrayOrTraversableAllowsArray()
+ {
+ $object = new GuardedObject;
+ $this->assertNull($object->setArrayOrTraversable(array()));
+ }
+
+ public function testGuardForArrayOrTraversableAllowsTraversable()
+ {
+ $object = new GuardedObject;
+ $traversable = new ArrayObject;
+ $this->assertNull($object->setArrayOrTraversable($traversable));
+ }
+
+}
View
46 tests/ZendTest/Stdlib/Guard/EmptyGuardTraitTest.php
@@ -0,0 +1,46 @@
+<?php
+/**
+ * Zend Framework (http://framework.zend.com/)
+ *
+ * @link http://github.com/zendframework/zf2 for the canonical source repository
+ * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license http://framework.zend.com/license/new-bsd New BSD License
+ */
+
+namespace ZendTest\Stdlib\Guard;
+
+use PHPUnit_Framework_TestCase as TestCase;
+use ZendTest\Stdlib\TestAsset\GuardedObject;
+
+/**
+ * @requires PHP 5.4
+ * @group Zend_StdLib_Guard
+ * @covers Zend\Stdlib\Guard\EmptyGuardTrait
+ */
+class EmptyGuardTraitTest extends TestCase
+{
+
+ public function setUp()
+ {
+ if (version_compare(PHP_VERSION, '5.4.0', '<')) {
+ $this->markTestSkipped('Only valid for php >= 5.4');
+ }
+ }
+
+ public function testGuardAgainstEmptyThrowsException()
+ {
+ $object = new GuardedObject;
+ $this->setExpectedException(
+ 'Zend\Stdlib\Exception\InvalidArgumentException',
+ 'Argument cannot be empty'
+ );
+ $object->setNotEmpty('');
+ }
+
+ public function testGuardAgainstEmptyAllowsNonEmptyString()
+ {
+ $object = new GuardedObject;
+ $this->assertNull($object->setNotEmpty('foo'));
+ }
+
+}
View
71 tests/ZendTest/Stdlib/Guard/GuardUtilsTest.php
@@ -0,0 +1,71 @@
+<?php
+/**
+ * Zend Framework (http://framework.zend.com/)
+ *
+ * @link http://github.com/zendframework/zf2 for the canonical source repository
+ * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license http://framework.zend.com/license/new-bsd New BSD License
+ */
+
+namespace ZendTest\Stdlib\Guard;
+
+use PHPUnit_Framework_TestCase as TestCase;
+use Zend\Stdlib\Guard\GuardUtils;
+use Zend\Stdlib\ArrayObject;
+
+/**
+ * @group Zend_StdLib_Guard
+ * @covers Zend\Stdlib\Guard\GuardUtils
+ */
+class GuardUtilsTest extends TestCase
+{
+
+ public function testGuardForArrayOrTraversableThrowsException()
+ {
+ $this->setExpectedException(
+ 'Zend\Stdlib\Exception\InvalidArgumentException',
+ 'Argument must be an array or Traversable, [string] given'
+ );
+ GuardUtils::guardForArrayOrTraversable('');
+ }
+
+ public function testGuardForArrayOrTraversableAllowsArray()
+ {
+ $this->assertNull(GuardUtils::guardForArrayOrTraversable(array()));
+ }
+
+ public function testGuardForArrayOrTraversableAllowsTraversable()
+ {
+ $traversable = new ArrayObject;
+ $this->assertNull(GuardUtils::guardForArrayOrTraversable($traversable));
+ }
+
+ public function testGuardAgainstEmptyThrowsException()
+ {
+ $this->setExpectedException(
+ 'Zend\Stdlib\Exception\InvalidArgumentException',
+ 'Argument cannot be empty'
+ );
+ GuardUtils::guardAgainstEmpty('');
+ }
+
+ public function testGuardAgainstEmptyAllowsNonEmptyString()
+ {
+ $this->assertNull(GuardUtils::guardAgainstEmpty('foo'));
+ }
+
+ public function testGuardAgainstNullThrowsException()
+ {
+ $this->setExpectedException(
+ 'Zend\Stdlib\Exception\InvalidArgumentException',
+ 'Argument cannot be null'
+ );
+ GuardUtils::guardAgainstNull(null);
+ }
+
+ public function testGuardAgainstNullAllowsNonNull()
+ {
+ $this->assertNull(GuardUtils::guardAgainstNull('foo'));
+ }
+
+}
View
46 tests/ZendTest/Stdlib/Guard/NullGuardTraitTest.php
@@ -0,0 +1,46 @@
+<?php
+/**
+ * Zend Framework (http://framework.zend.com/)
+ *
+ * @link http://github.com/zendframework/zf2 for the canonical source repository
+ * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license http://framework.zend.com/license/new-bsd New BSD License
+ */
+
+namespace ZendTest\Stdlib\Guard;
+
+use PHPUnit_Framework_TestCase as TestCase;
+use ZendTest\Stdlib\TestAsset\GuardedObject;
+
+/**
+ * @requires PHP 5.4
+ * @group Zend_StdLib_Guard
+ * @covers Zend\Stdlib\Guard\NullGuardTrait
+ */
+class NullGuardTraitTest extends TestCase
+{
+
+ public function setUp()
+ {
+ if (version_compare(PHP_VERSION, '5.4.0', '<')) {
+ $this->markTestSkipped('Only valid for php >= 5.4');
+ }
+ }
+
+ public function testGuardAgainstNullThrowsException()
+ {
+ $object = new GuardedObject;
+ $this->setExpectedException(
+ 'Zend\Stdlib\Exception\InvalidArgumentException',
+ 'Argument cannot be null'
+ );
+ $object->setNotNull(null);
+ }
+
+ public function testGuardAgainstNullAllowsNonNull()
+ {
+ $object = new GuardedObject;
+ $this->assertNull($object->setNotNull('foo'));
+ }
+
+}
View
37 tests/ZendTest/Stdlib/TestAsset/GuardedObject.php
@@ -0,0 +1,37 @@
+<?php
+/**
+ * Zend Framework (http://framework.zend.com/)
+ *
+ * @link http://github.com/zendframework/zf2 for the canonical source repository
+ * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license http://framework.zend.com/license/new-bsd New BSD License
+ */
+
+namespace ZendTest\Stdlib\TestAsset;
+
+use Zend\Stdlib\Guard\AllGuardsTrait;
+
+/**
+ * @group Zend_Stdlib_Guard
+ */
+class GuardedObject
+{
+
+ use AllGuardsTrait;
+
+ public function setArrayOrTraversable($value)
+ {
+ $this->guardForArrayOrTraversable($value);
+ }
+
+ public function setNotEmpty($value)
+ {
+ $this->guardAgainstEmpty($value);
+ }
+
+ public function setNotNull($value)
+ {
+ $this->guardAgainstNull($value);
+ }
+
+}
Something went wrong with that request. Please try again.