diff --git a/QuickForm2.php b/QuickForm2.php index 6a181b6c..0623aaca 100644 --- a/QuickForm2.php +++ b/QuickForm2.php @@ -194,5 +194,22 @@ public function __toString() { throw new HTML_QuickForm2_Exception('Not implemented'); } + + /** + * Performs the server-side validation + * + * @return boolean Whether all form's elements are valid + */ + public function validate() + { + $isSubmitted = false; + foreach ($this->datasources as $ds) { + if ($ds instanceof HTML_QuickForm2_DataSource_Submit) { + $isSubmitted = true; + break; + } + } + return $isSubmitted? parent::validate(): false; + } } ?> diff --git a/QuickForm2/Container.php b/QuickForm2/Container.php index 0758e66d..f0429385 100644 --- a/QuickForm2/Container.php +++ b/QuickForm2/Container.php @@ -403,6 +403,23 @@ protected function updateValue() $child->updateValue(); } } + + + /** + * Performs the server-side validation + * + * This method also calls validate() on all contained elements. + * + * @return boolean Whether the container and all contained elements are valid + */ + protected function validate() + { + $valid = parent::validate(); + foreach ($this as $child) { + $valid = $child->validate() && $valid; + } + return $valid; + } } /** diff --git a/tests/QuickForm2/ContainerTest.php b/tests/QuickForm2/ContainerTest.php index 78023e2d..0845e845 100644 --- a/tests/QuickForm2/ContainerTest.php +++ b/tests/QuickForm2/ContainerTest.php @@ -46,10 +46,19 @@ * Container class */ require_once 'HTML/QuickForm2/Container.php'; + +/** + * Base class for "scalar" elements + */ require_once 'HTML/QuickForm2/Element.php'; /** - * PHPUnit2 Test Case + * Base class for HTML_QuickForm2 rules + */ +require_once 'HTML/QuickForm2/Rule.php'; + +/** + * PHPUnit Test Case */ require_once 'PHPUnit/Framework/TestCase.php'; @@ -81,12 +90,15 @@ public function setValue($value) * A non-abstract subclass of Container * * Container class is still abstract, we should "implement" the remaining methods + * and also make validate() public to be able to test it. */ class HTML_QuickForm2_ContainerImpl extends HTML_QuickForm2_Container { public function getType() { return 'concrete'; } public function setValue($value) { return ''; } public function __toString() { return ''; } + + public function validate() { return parent::validate(); } } /** @@ -428,5 +440,37 @@ public function testGetValue() 'baz' => 'yet another value' ), $c1->getValue()); } + + public function testValidate() + { + $cValidate = new HTML_QuickForm2_ContainerImpl('validate'); + $el1 = $cValidate->appendChild(new HTML_QuickForm2_ElementImpl2('foo')); + $el2 = $cValidate->appendChild(new HTML_QuickForm2_ElementImpl2('bar')); + + $ruleTrue1 = $this->getMock( + 'HTML_QuickForm2_Rule', array('checkValue'), + array($cValidate, 'irrelevant message') + ); + $ruleTrue1->expects($this->once())->method('checkValue') + ->will($this->returnValue(true)); + $ruleFalse = $this->getMock( + 'HTML_QuickForm2_Rule', array('checkValue'), + array($el1, 'some error') + ); + $ruleFalse->expects($this->once())->method('checkValue') + ->will($this->returnValue(false)); + $ruleTrue2 = $this->getMock( + 'HTML_QuickForm2_Rule', array('checkValue'), + array($el2, 'irrelevant message') + ); + $ruleTrue2->expects($this->once())->method('checkValue') + ->will($this->returnValue(true)); + + $cValidate->addRule($ruleTrue1); + $el1->addRule($ruleFalse); + $el2->addRule($ruleTrue2); + $this->assertFalse($cValidate->validate()); + $this->assertEquals('', $cValidate->getError()); + } } ?> diff --git a/tests/QuickForm2Test.php b/tests/QuickForm2Test.php index b81b7210..51af9b49 100644 --- a/tests/QuickForm2Test.php +++ b/tests/QuickForm2Test.php @@ -173,6 +173,15 @@ public function testSetDataSources() $this->fail('Expected HTML_QuickForm2_InvalidArgumentException was not thrown'); } + public function testValidateChecksWhetherFormIsSubmitted() + { + $form1 = new HTML_QuickForm2('notrack', 'post'); + $this->assertFalse($form1->validate()); + + $form2 = new HTML_QuickForm2('track', 'post'); + $this->assertTrue($form2->validate()); + } + public function tearDown() { $_REQUEST = $this->request;