[BUGFIX] EXT:form - Validation of radiogroup/ checkboxgroup elements 10/43710/10
authorRalf Zimmermann <ralf.zimmermann@tritum.de>
Fri, 30 Oct 2015 10:16:48 +0000 (11:16 +0100)
committerChristian Kuhn <lolli@schwarzbu.ch>
Sat, 31 Oct 2015 13:36:23 +0000 (14:36 +0100)
The "required" validator has to check array values.

Resolves: #70210
Releases: master
Change-Id: I58b8fb93d7e684854d1834c7994c837922467f82
Reviewed-on: https://review.typo3.org/43710
Reviewed-by: Wouter Wolters <typo3@wouterwolters.nl>
Tested-by: Wouter Wolters <typo3@wouterwolters.nl>
Reviewed-by: Christian Kuhn <lolli@schwarzbu.ch>
Tested-by: Christian Kuhn <lolli@schwarzbu.ch>
typo3/sysext/form/Classes/Domain/Validator/RequiredValidator.php
typo3/sysext/form/Classes/Utility/CompatibilityLayerUtility.php
typo3/sysext/form/Resources/Private/Partials/Compatibility/Show/ContainerElements/Checkboxgroup.html
typo3/sysext/form/Resources/Private/Partials/Compatibility/Show/ContainerElements/Radiogroup.html
typo3/sysext/form/Resources/Private/Partials/Default/Show/ContainerElements/Checkboxgroup.html
typo3/sysext/form/Resources/Private/Partials/Default/Show/ContainerElements/Radiogroup.html
typo3/sysext/form/Tests/Unit/Validator/RequiredValidatorTest.php

index 09560c2..e899c0e 100755 (executable)
@@ -24,6 +24,11 @@ class RequiredValidator extends AbstractValidator
     const LOCALISATION_OBJECT_NAME = 'tx_form_system_validate_required';
 
     /**
     const LOCALISATION_OBJECT_NAME = 'tx_form_system_validate_required';
 
     /**
+     * @var bool
+     */
+    protected $allFieldsAreEmpty = true;
+
+    /**
      * Check if $value is valid. If it is not valid, needs to add an error
      * to result.
      *
      * Check if $value is valid. If it is not valid, needs to add an error
      * to result.
      *
@@ -32,19 +37,66 @@ class RequiredValidator extends AbstractValidator
      */
     public function isValid($value)
     {
      */
     public function isValid($value)
     {
-        if (
-            empty($value)
-            && $value !== 0
-            && $value !== '0'
-        ) {
-            $this->addError(
-                $this->renderMessage(
-                    $this->options['errorMessage'][0],
-                    $this->options['errorMessage'][1],
-                    'error'
-                ),
-                1441980673
+        if (is_array($value)) {
+            array_walk_recursive($value, function ($value, $key, $validator) {
+                    if (!empty($value) || $value === '0' || $value === 0) {
+                        $validator->setAllFieldsAreEmpty(false);
+                    }
+                },
+                $this
             );
             );
+            if ($this->getAllFieldsAreEmpty()) {
+                $this->addError(
+                    $this->renderMessage(
+                        $this->options['errorMessage'][0],
+                        $this->options['errorMessage'][1],
+                        'error'
+                    ),
+                    1441980673
+                );
+            }
+        } else {
+            if (
+                empty($value)
+                && $value !== 0
+                && $value !== '0'
+            ) {
+                $this->addError(
+                    $this->renderMessage(
+                        $this->options['errorMessage'][0],
+                        $this->options['errorMessage'][1],
+                        'error'
+                    ),
+                    144198067
+                );
+            }
         }
     }
         }
     }
+
+    /**
+     * A helper method for the array_walk_recursive callback in the
+     * function isValid().
+     * If the callback detect a empty value, the
+     * property allFieldsAreEmpty is set to TRUE.
+     *
+     * @param bool $allFieldsAreEmpty
+     * @return void
+     */
+    protected function setAllFieldsAreEmpty($allFieldsAreEmpty = true)
+    {
+        $this->allFieldsAreEmpty = $allFieldsAreEmpty;
+    }
+
+    /**
+     * A helper method for the array_walk_recursive callback in the
+     * function isValid().
+     * If the callback detect a empty value, the
+     * property allFieldsAreEmpty is set to TRUE.
+     *
+     * @return bool
+     */
+    protected function getAllFieldsAreEmpty()
+    {
+        return $this->allFieldsAreEmpty;
+    }
 }
 }
index 900c08f..d8eb566 100644 (file)
@@ -169,7 +169,9 @@ class CompatibilityLayerUtility
                     }
                     break;
                 case 'LEGEND':
                     }
                     break;
                 case 'LEGEND':
-                    if ($action !== 'process') {
+                    if ($action === 'show') {
+                        $layout = '<legend><legendvalue /><mandatory /><error /></legend>';
+                    } elseif ($action === 'confirmation') {
                         $layout = '<legend><legendvalue /></legend>';
                     } else {
                         $layout = '<thead><tr><th colspan="2" align="left"><legendvalue /></th></tr></thead>';
                         $layout = '<legend><legendvalue /></legend>';
                     } else {
                         $layout = '<thead><tr><th colspan="2" align="left"><legendvalue /></th></tr></thead>';
@@ -297,59 +299,22 @@ class CompatibilityLayerUtility
                 if ($elementWrap['html'] !== '') {
                     /* layout.label */
                     if (!in_array($element->getElementType(), $this->elementsWithoutLabel, true)) {
                 if ($elementWrap['html'] !== '') {
                     /* layout.label */
                     if (!in_array($element->getElementType(), $this->elementsWithoutLabel, true)) {
-                        $labelLayout = $this->getGlobalLayoutByElementType('LABEL');
-                        $mandatoryLayout = '';
-                        $errorLayout = '';
-                        if ($this->formBuilder->getControllerAction() === 'show') {
-                            /* layout.mandatory */
-                            $mandatoryMessages = $this->formBuilder->getValidationBuilder()->getMandatoryValidationMessagesByElementName($element->getName());
-                            if (!empty($mandatoryMessages)) {
-                                $mandatoryLayout = $this->replaceLabelContent('mandatory', $mandatoryMessages);
-                            }
-                            /* layout.error */
-                            $errorMessages = $element->getValidationErrorMessages();
-                            if (!empty($errorMessages)) {
-                                $errorLayout = $this->replaceLabelContent('error', $errorMessages);
-                            }
-                        }
-                        /* Replace the mandatory and error messages */
-                        $mandatoryReturn = $this->replaceTagWithMarker('mandatory', 'body', $labelLayout);
-                        $labelContainContent = false;
-                        if ($mandatoryReturn['html'] !== '') {
-                            if (!empty($mandatoryLayout)) {
-                                $labelContainContent = true;
-                            }
-                            $labelLayout = str_replace($mandatoryReturn['marker'], $mandatoryLayout, $mandatoryReturn['html']);
-                        }
-                        $errorReturn = $this->replaceTagWithMarker('error', 'body', $labelLayout);
-                        if ($errorReturn['html'] !== '') {
-                            if (!empty($errorLayout)) {
-                                $labelContainContent = true;
-                            }
-                            $labelLayout = str_replace($errorReturn['marker'], $errorLayout, $errorReturn['html']);
-                        }
-                        /* Replace the label value */
-                        $labelValueReturn = $this->replaceTagWithMarker('labelvalue', 'body', $labelLayout);
-                        if ($labelValueReturn['html'] !== '') {
-                            if (!empty($element->getAdditionalArgument('label'))) {
-                                $labelContainContent = true;
-                            }
-                            $labelLayout = str_replace($labelValueReturn['marker'], $element->getAdditionalArgument('label'), $labelValueReturn['html']);
-                        }
-                        if (!$labelContainContent) {
-                            $labelLayout = '';
+                        $descriptionElementLayouts = $this->getDescriptionElementLayouts($element);
+
+                        if (!$descriptionElementLayouts['labelContainContent']) {
+                            $descriptionElementLayouts['labelLayout'] = '';
                         } else {
                             $libxmlUseInternalErrors = libxml_use_internal_errors(true);
                             $dom = new \DOMDocument('1.0', 'utf-8');
                             $dom->formatOutput = true;
                             $dom->preserveWhiteSpace = false;
                         } else {
                             $libxmlUseInternalErrors = libxml_use_internal_errors(true);
                             $dom = new \DOMDocument('1.0', 'utf-8');
                             $dom->formatOutput = true;
                             $dom->preserveWhiteSpace = false;
-                            if ($dom->loadXML($labelLayout)) {
+                            if ($dom->loadXML($descriptionElementLayouts['labelLayout'])) {
                                 $nodes = $dom->getElementsByTagName('label');
                                 if ($nodes->length) {
                                     $node = $nodes->item(0);
                                     if ($node) {
                                         $node->setAttribute('for', $element->getId());
                                 $nodes = $dom->getElementsByTagName('label');
                                 if ($nodes->length) {
                                     $node = $nodes->item(0);
                                     if ($node) {
                                         $node->setAttribute('for', $element->getId());
-                                        $labelLayout = $dom->saveXML($dom->firstChild);
+                                        $descriptionElementLayouts['labelLayout'] = $dom->saveXML($dom->firstChild);
                                     }
                                 }
                             }
                                     }
                                 }
                             }
@@ -358,15 +323,15 @@ class CompatibilityLayerUtility
                         /* Replace <label />, <error /> and <mandatory /> in the element wrap html */
                         $labelReturn = $this->replaceTagWithMarker('label', 'body', $elementWrap['html']);
                         if ($labelReturn['html'] !== '') {
                         /* Replace <label />, <error /> and <mandatory /> in the element wrap html */
                         $labelReturn = $this->replaceTagWithMarker('label', 'body', $elementWrap['html']);
                         if ($labelReturn['html'] !== '') {
-                            $elementWrap['html'] = str_replace($labelReturn['marker'], $labelLayout, $labelReturn['html']);
+                            $elementWrap['html'] = str_replace($labelReturn['marker'], $descriptionElementLayouts['labelLayout'], $labelReturn['html']);
                         }
                         $errorReturn = $this->replaceTagWithMarker('error', 'body', $elementWrap['html']);
                         if ($errorReturn['html'] !== '') {
                         }
                         $errorReturn = $this->replaceTagWithMarker('error', 'body', $elementWrap['html']);
                         if ($errorReturn['html'] !== '') {
-                            $elementWrap['html'] = str_replace($errorReturn['marker'], $errorLayout, $errorReturn['html']);
+                            $elementWrap['html'] = str_replace($errorReturn['marker'], $descriptionElementLayouts['errorLayout'], $errorReturn['html']);
                         }
                         $mandatoryReturn = $this->replaceTagWithMarker('mandatory', 'body', $elementWrap['html']);
                         if ($mandatoryReturn['html'] !== '') {
                         }
                         $mandatoryReturn = $this->replaceTagWithMarker('mandatory', 'body', $elementWrap['html']);
                         if ($mandatoryReturn['html'] !== '') {
-                            $elementWrap['html'] = str_replace($mandatoryReturn['marker'], $mandatoryLayout, $mandatoryReturn['html']);
+                            $elementWrap['html'] = str_replace($mandatoryReturn['marker'], $descriptionElementLayouts['mandatoryLayout'], $mandatoryReturn['html']);
                         }
                     }
                     $elementWrap = explode($elementWrap['marker'], $elementWrap['html']);
                         }
                     }
                     $elementWrap = explode($elementWrap['marker'], $elementWrap['html']);
@@ -444,39 +409,21 @@ class CompatibilityLayerUtility
             if (in_array($element->getElementType(), $this->containerElements)) {
                 $elementWrap = $this->determineElementOuterWraps($element->getElementType(), $elementLayout);
                 /* Replace the legend value */
             if (in_array($element->getElementType(), $this->containerElements)) {
                 $elementWrap = $this->determineElementOuterWraps($element->getElementType(), $elementLayout);
                 /* Replace the legend value */
-                $legendLayout = $this->getGlobalLayoutByElementType('LEGEND');
-                $legendValueReturn = $this->replaceTagWithMarker('legendvalue', 'body', $legendLayout);
-                $legendContainContent = false;
-                if ($legendValueReturn['html'] !== '') {
-                    if (!empty($element->getAdditionalArgument('legend'))) {
-                        $legendContainContent = true;
-                    }
-                    $legendLayout = str_replace($legendValueReturn['marker'], $element->getAdditionalArgument('legend'), $legendValueReturn['html']);
-                }
-                /* remove <mandatory /> and <error /> from legend */
-                $mandatoryReturn = $this->replaceTagWithMarker('mandatory', 'body', $legendLayout);
-                if (!empty($mandatoryReturn['html'])) {
-                    $legendLayout = str_replace($mandatoryReturn['marker'], '', $mandatoryReturn['html']);
-                }
-                $errorReturn = $this->replaceTagWithMarker('error', 'body', $legendLayout);
-                if (!empty($errorReturn['html'])) {
-                    $legendLayout = str_replace($errorReturn['marker'], '', $errorReturn['html']);
-                }
-
-                if (!$legendContainContent) {
-                    $legendLayout = '';
+                $descriptionElementLayouts = $this->getDescriptionElementLayouts($element, 'legend');
+                if (!$descriptionElementLayouts['labelContainContent']) {
+                    $descriptionElementLayouts['labelLayout'] = '';
                 }
                 /* No fieldset tag exist.
                  * Ignore CONTAINERWRAP
                  * */
                 if ($elementWrap['html'] === '') {
                     $containerWrapReturn = $this->replaceTagWithMarker('elements', 'body', $elementLayout);
                 }
                 /* No fieldset tag exist.
                  * Ignore CONTAINERWRAP
                  * */
                 if ($elementWrap['html'] === '') {
                     $containerWrapReturn = $this->replaceTagWithMarker('elements', 'body', $elementLayout);
-                    $legendReturn = $this->replaceTagWithMarker('legend', 'body', $containerWrapReturn['html']);
-
-                    if ($legendReturn['html'] !== '') {
-                        $containerWrapReturn['html'] = str_replace($legendReturn['marker'], $legendLayout, $legendReturn['html']);
-                    }
                     if ($containerWrapReturn['marker'] && $containerWrapReturn['html']) {
                     if ($containerWrapReturn['marker'] && $containerWrapReturn['html']) {
+                        /* Replace <legend /> in the element wrap html */
+                        $legendReturn = $this->replaceTagWithMarker('legend', 'body', $containerWrapReturn['html']);
+                        if ($legendReturn['html'] !== '') {
+                            $containerWrapReturn['html'] = str_replace($legendReturn['marker'], $descriptionElementLayouts['labelLayout'], $legendReturn['html']);
+                        }
                         $containerWrap = explode($containerWrapReturn['marker'], $containerWrapReturn['html']);
                     } else {
                         $containerWrap = array('', '');
                         $containerWrap = explode($containerWrapReturn['marker'], $containerWrapReturn['html']);
                     } else {
                         $containerWrap = array('', '');
@@ -485,14 +432,9 @@ class CompatibilityLayerUtility
                     $layout = $element->getLayout();
                     $layout['containerInnerWrap'] = $containerWrap;
                     $layout['noFieldsetTag'] = true;
                     $layout = $element->getLayout();
                     $layout['containerInnerWrap'] = $containerWrap;
                     $layout['noFieldsetTag'] = true;
+                    $layout['legend'] = $descriptionElementLayouts['labelLayout'];
                     $element->setLayout($layout);
                 } else {
                     $element->setLayout($layout);
                 } else {
-                    $legendReturn = $this->replaceTagWithMarker('legend', 'body', $elementWrap['html']);
-
-                    if ($legendReturn['html'] !== '') {
-                        $elementWrap['html'] = str_replace($legendReturn['marker'], $legendLayout, $legendReturn['html']);
-                    }
-
                     /* set the wraps */
                     $containerOuterWrap = array('', '');
                     $containerOuterWrap = explode($elementWrap['marker'], $elementWrap['html']);
                     /* set the wraps */
                     $containerOuterWrap = array('', '');
                     $containerOuterWrap = explode($elementWrap['marker'], $elementWrap['html']);
@@ -506,6 +448,7 @@ class CompatibilityLayerUtility
 
                     $layout = $element->getLayout();
                     $layout['containerInnerWrap'] = $containerWrap;
 
                     $layout = $element->getLayout();
                     $layout['containerInnerWrap'] = $containerWrap;
+                    $layout['legend'] = $descriptionElementLayouts['labelLayout'];
                     $element->setLayout($layout);
                     $classFromLayout = $this->getElementClassFromLayout('fieldset');
                     if (!empty($classFromLayout)) {
                     $element->setLayout($layout);
                     $classFromLayout = $this->getElementClassFromLayout('fieldset');
                     if (!empty($classFromLayout)) {
@@ -544,7 +487,7 @@ class CompatibilityLayerUtility
      *
      * @param string $scope
      * @param array $messages
      *
      * @param string $scope
      * @param array $messages
-     * @return string $html
+     * @return string
      */
     protected function replaceLabelContent($scope = '', array $messages)
     {
      */
     protected function replaceLabelContent($scope = '', array $messages)
     {
@@ -555,6 +498,67 @@ class CompatibilityLayerUtility
     }
 
     /**
     }
 
     /**
+     * Replace <labelvalue /> or <legendvalue />, <mandatory />
+     * and <error /> in a label / legend with the associated content.
+     * Return the replaced <label /> / <legend /> layout and the replaced
+     * <mandatory /> and <error /> layout.
+     *
+     * @param \TYPO3\CMS\Form\Domain\Model\Element $element
+     * @param string $scope
+     * @return array
+     */
+    protected function getDescriptionElementLayouts(Element $element, $scope = 'label')
+    {
+        $labelLayout = $this->getGlobalLayoutByElementType(strtoupper($scope));
+        $labelContainContent = false;
+        $mandatoryLayout = '';
+        $errorLayout = '';
+        if ($this->formBuilder->getControllerAction() === 'show') {
+            /* Replace the mandatory and error messages */
+            /* layout.mandatory */
+            $mandatoryMessages = $this->formBuilder->getValidationBuilder()->getMandatoryValidationMessagesByElementName($element->getName());
+            if (!empty($mandatoryMessages)) {
+                $mandatoryLayout = $this->replaceLabelContent('mandatory', $mandatoryMessages);
+            }
+            $mandatoryReturn = $this->replaceTagWithMarker('mandatory', 'body', $labelLayout);
+            if (!empty($mandatoryReturn['html'])) {
+                if (!empty($mandatoryLayout)) {
+                    $labelContainContent = true;
+                }
+                $labelLayout = str_replace($mandatoryReturn['marker'], $mandatoryLayout, $mandatoryReturn['html']);
+            }
+
+            /* layout.error */
+            $errorMessages = $element->getValidationErrorMessages();
+            if (!empty($errorMessages)) {
+                $errorLayout = $this->replaceLabelContent('error', $errorMessages);
+            }
+            $errorReturn = $this->replaceTagWithMarker('error', 'body', $labelLayout);
+            if (!empty($errorReturn['html'])) {
+                if (!empty($errorLayout)) {
+                    $labelContainContent = true;
+                }
+                $labelLayout = str_replace($errorReturn['marker'], $errorLayout, $errorReturn['html']);
+            }
+        }
+        /* Replace the label value */
+        $labelValueReturn = $this->replaceTagWithMarker($scope . 'value', 'body', $labelLayout);
+        if (!empty($labelValueReturn['html'])) {
+            if (!empty($element->getAdditionalArgument($scope))) {
+                $labelContainContent = true;
+            }
+            $labelLayout = str_replace($labelValueReturn['marker'], $element->getAdditionalArgument($scope), $labelValueReturn['html']);
+        }
+
+        return array(
+            'labelContainContent' => $labelContainContent,
+            'labelLayout' => $labelLayout,
+            'errorLayout' => $errorLayout,
+            'mandatoryLayout' => $mandatoryLayout
+        );
+    }
+
+    /**
      * Return the class attribute for a element defined by layout.
      *
      * @param string $elementType
      * Return the class attribute for a element defined by layout.
      *
      * @param string $elementType
index 1477fb8..9b02383 100644 (file)
@@ -17,8 +17,8 @@
                                                {htmAttributeKey}="{htmAttributeValue}"
                                        </f:for>
                                        >
                                                {htmAttributeKey}="{htmAttributeValue}"
                                        </f:for>
                                        >
-                                               <f:if condition="{model.additionalArguments.legend}">
-                                                       <legend>{model.additionalArguments.legend}</legend>
+                                               <f:if condition="{model.layout.legend}">
+                                                       <f:format.raw>{model.layout.legend}</f:format.raw>
                                                </f:if>
 
                                                <f:format.raw>{model.layout.containerInnerWrap.0}</f:format.raw>
                                                </f:if>
 
                                                <f:format.raw>{model.layout.containerInnerWrap.0}</f:format.raw>
index 1477fb8..9b02383 100644 (file)
@@ -17,8 +17,8 @@
                                                {htmAttributeKey}="{htmAttributeValue}"
                                        </f:for>
                                        >
                                                {htmAttributeKey}="{htmAttributeValue}"
                                        </f:for>
                                        >
-                                               <f:if condition="{model.additionalArguments.legend}">
-                                                       <legend>{model.additionalArguments.legend}</legend>
+                                               <f:if condition="{model.layout.legend}">
+                                                       <f:format.raw>{model.layout.legend}</f:format.raw>
                                                </f:if>
 
                                                <f:format.raw>{model.layout.containerInnerWrap.0}</f:format.raw>
                                                </f:if>
 
                                                <f:format.raw>{model.layout.containerInnerWrap.0}</f:format.raw>
index 8921d4f..cdc702d 100644 (file)
@@ -7,7 +7,15 @@
                        </f:for>
                        >
                                <f:if condition="{model.additionalArguments.legend}">
                        </f:for>
                        >
                                <f:if condition="{model.additionalArguments.legend}">
-                                       <legend>{model.additionalArguments.legend}</legend>
+                                       <legend>
+                                               {model.additionalArguments.legend}
+                                               <f:if condition="{model.mandatoryValidationMessages}">
+                                                       <em><f:for each="{model.mandatoryValidationMessages}" as="mandatoryValidationMessage" iteration="iterator">{mandatoryValidationMessage}<f:if condition="{iterator.isLast}"><f:else> - </f:else></f:if></f:for></em>
+                                               </f:if>
+                                               <f:if condition="{model.validationErrorMessages}">
+                                                       <strong><f:for each="{model.validationErrorMessages}" as="errorValidationMessage" iteration="iterator">{errorValidationMessage}<f:if condition="{iterator.isLast}"><f:else> - </f:else></f:if></f:for></strong>
+                                               </f:if>
+                                       </legend>
                                </f:if>
                                <ol>
                                        <f:for each="{model.childElements}" as="element">
                                </f:if>
                                <ol>
                                        <f:for each="{model.childElements}" as="element">
index 8921d4f..2c24465 100644 (file)
@@ -2,12 +2,20 @@
        <f:then>
                <li class="csc-form-{model.elementCounter} csc-form-element csc-form-element-{model.elementTypeLowerCase}">
                        <fieldset
        <f:then>
                <li class="csc-form-{model.elementCounter} csc-form-element csc-form-element-{model.elementTypeLowerCase}">
                        <fieldset
-                       <f:for each="{model.htmlAttributes}" as="htmAttributeValue" key="htmAttributeKey">
-                               {htmAttributeKey}="{htmAttributeValue}"
-                       </f:for>
+                               <f:for each="{model.htmlAttributes}" as="htmAttributeValue" key="htmAttributeKey">
+                                       {htmAttributeKey}="{htmAttributeValue}"
+                               </f:for>
                        >
                                <f:if condition="{model.additionalArguments.legend}">
                        >
                                <f:if condition="{model.additionalArguments.legend}">
-                                       <legend>{model.additionalArguments.legend}</legend>
+                                       <legend>
+                                               {model.additionalArguments.legend}
+                                               <f:if condition="{model.mandatoryValidationMessages}">
+                                                       <em><f:for each="{model.mandatoryValidationMessages}" as="mandatoryValidationMessage" iteration="iterator">{mandatoryValidationMessage}<f:if condition="{iterator.isLast}"><f:else> - </f:else></f:if></f:for></em>
+                                               </f:if>
+                                               <f:if condition="{model.validationErrorMessages}">
+                                                       <strong><f:for each="{model.validationErrorMessages}" as="errorValidationMessage" iteration="iterator">{errorValidationMessage}<f:if condition="{iterator.isLast}"><f:else> - </f:else></f:if></f:for></strong>
+                                               </f:if>
+                                       </legend>
                                </f:if>
                                <ol>
                                        <f:for each="{model.childElements}" as="element">
                                </f:if>
                                <ol>
                                        <f:for each="{model.childElements}" as="element">
index 376b3f4..e08c500 100644 (file)
@@ -30,10 +30,18 @@ class RequiredValidatorTest extends AbstractValidatorTest
     public function validDataProvider()
     {
         return array(
     public function validDataProvider()
     {
         return array(
-            'a'   => array('a'),
-            'a b' => array('a b'),
-            '"0"' => array('0'),
-            '0'   => array(0)
+            'string "a"'   => array('a'),
+            'string "a b"' => array('a b'),
+            'string "0"'   => array('0'),
+            'value 0'      => array(0),
+            'array with string "a"'   => array(array('a')),
+            'array with string "a b"' => array(array('a b')),
+            'array with string "0"'   => array(array('0')),
+            'array with value 0'      => array(array(0)),
+            'array with strings "a" and "b"' => array(array('a', 'b')),
+            'array with empty string and "a"' => array(array('', 'a')),
+            'array with empty string and "0"' => array(array('', "0")),
+            'array with empty string and 0' => array(array('', 0)),
         );
     }
 
         );
     }
 
@@ -43,7 +51,9 @@ class RequiredValidatorTest extends AbstractValidatorTest
     public function invalidDataProvider()
     {
         return array(
     public function invalidDataProvider()
     {
         return array(
-            'empty string'  => array(''),
+            'empty string'            => array(''),
+            'array with empty string' => array(array('')),
+            'array with empty strings' => array(array('', ''))
         );
     }
 
         );
     }