/** * Checks if the given value is valid according to the property validators. * * @param mixed $object The value that should be validated * @return void * @api */ protected function isValid($object) { $messages = new \TYPO3\Flow\Error\Result(); foreach ($this->propertyValidators as $propertyName => $validators) { $propertyValue = $this->getPropertyValue($object, $propertyName); $result = $this->checkProperty($propertyValue, $validators); if ($result !== null) { $messages->forProperty($propertyName)->merge($result); } } $this->result = $messages; }
/** * @test */ public function assignErrorsConvertsErrorsToExtJSFormat() { $propertyError = new \TYPO3\Flow\Error\Error('Some error', 12345678); $errors = new \TYPO3\Flow\Error\Result(); $errors->forProperty('title')->addError($propertyError); $expected = array('errors' => array('title' => 'Some error'), 'success' => FALSE); $mockResponse = $this->getMock('TYPO3\\ExtJS\\ExtDirect\\TransactionResponse'); $mockResponse->expects($this->atLeastOnce())->method('setResult')->with($expected); $mockControllerContext = $this->getMock('TYPO3\\Flow\\Mvc\\Controller\\ControllerContext', array('getResponse'), array(), '', FALSE); $mockControllerContext->expects($this->any())->method('getResponse')->will($this->returnValue($mockResponse)); $view = $this->getMock('TYPO3\\ExtJS\\ExtDirect\\View', array('loadConfigurationFromYamlFile')); $view->setControllerContext($mockControllerContext); $view->expects($this->any())->method('loadConfigurationFromYamlFile')->will($this->returnValue(array())); $view->assignErrors($errors); $view->render(); }
/** * Get all property mapping / validation errors * * @return \TYPO3\Flow\Error\Result */ public function getValidationResults() { $results = new \TYPO3\Flow\Error\Result(); foreach ($this as $argument) { $argumentValidationResults = $argument->getValidationResults(); if ($argumentValidationResults === null) { continue; } $results->forProperty($argument->getName())->merge($argumentValidationResults); } return $results; }
/** * Validate a dictionary value with the given schema * * The following properties are handled in given $schema: * - properties : array of keys and schemas that have to validate * - formatProperties : dictionary of schemas, the schemas are used to validate all keys that match the string-format * - patternProperties : dictionary of schemas, the schemas are used to validate all keys that match the string-pattern * - additionalProperties : if FALSE is given all additionalProperties are forbidden, if a schema is given all additional properties have to match the schema * * @param mixed $value * @param array $schema * @return \TYPO3\Flow\Error\Result */ protected function validateDictionaryType($value, array $schema) { $result = new \TYPO3\Flow\Error\Result(); if (is_array($value) === false || $this->isDictionary($value) === false) { $result->addError($this->createError('type=dictionary', 'type=' . gettype($value))); return $result; } $propertyKeysToHandle = array_keys($value); if (isset($schema['properties'])) { foreach ($schema['properties'] as $propertyName => $propertySchema) { if (array_key_exists($propertyName, $value)) { $propertyValue = $value[$propertyName]; $subresult = $this->validate($propertyValue, $propertySchema); if ($subresult->hasErrors()) { $result->forProperty($propertyName)->merge($subresult); } $propertyKeysToHandle = array_diff($propertyKeysToHandle, array($propertyName)); } else { // is subproperty required if (is_array($propertySchema) && $this->isSchema($propertySchema) && isset($propertySchema['required']) && $propertySchema['required'] === true) { $result->addError($this->createError('Property ' . $propertyName . ' is required')); } } } } if (isset($schema['patternProperties']) && count($propertyKeysToHandle) > 0 && $this->isDictionary($schema['patternProperties'])) { foreach (array_values($propertyKeysToHandle) as $propertyKey) { foreach ($schema['patternProperties'] as $propertyPattern => $propertySchema) { $keyResult = $this->validateStringType($propertyKey, array('pattern' => $propertyPattern)); if ($keyResult->hasErrors() === false) { $subresult = $this->validate($value[$propertyKey], $propertySchema); if ($subresult->hasErrors()) { $result->forProperty($propertyKey)->merge($subresult); } $propertyKeysToHandle = array_diff($propertyKeysToHandle, array($propertyKey)); } } } } if (isset($schema['formatProperties']) && count($propertyKeysToHandle) > 0 && $this->isDictionary($schema['formatProperties'])) { foreach (array_values($propertyKeysToHandle) as $propertyKey) { foreach ($schema['formatProperties'] as $propertyPattern => $propertySchema) { $keyResult = $this->validateStringType($propertyKey, array('format' => $propertyPattern)); if ($keyResult->hasErrors() === false) { $subresult = $this->validate($value[$propertyKey], $propertySchema); if ($subresult->hasErrors()) { $result->forProperty($propertyKey)->merge($subresult); } $propertyKeysToHandle = array_diff($propertyKeysToHandle, array($propertyKey)); } } } } if (isset($schema['additionalProperties']) && $schema['additionalProperties'] !== true && count($propertyKeysToHandle) > 0) { if ($schema['additionalProperties'] === false) { foreach ($propertyKeysToHandle as $propertyKey) { $result->forProperty($propertyKey)->addError($this->createError('This property is not allowed here, check the spelling if you think it belongs here.')); } } else { foreach ($propertyKeysToHandle as $propertyKey) { $subresult = $this->validate($value[$propertyKey], $schema['additionalProperties']); if ($subresult->hasErrors()) { $result->forProperty($propertyKey)->merge($subresult); } } } } return $result; }
/** * @test */ public function mergeShouldMergeTwoResults() { $notice1 = $this->getMockMessage('Notice'); $notice2 = $this->getMockMessage('Notice'); $notice3 = $this->getMockMessage('Notice'); $warning1 = $this->getMockMessage('Warning'); $warning2 = $this->getMockMessage('Warning'); $warning3 = $this->getMockMessage('Warning'); $error1 = $this->getMockMessage('Error'); $error2 = $this->getMockMessage('Error'); $error3 = $this->getMockMessage('Error'); $otherResult = new \TYPO3\Flow\Error\Result(); $otherResult->addNotice($notice1); $otherResult->forProperty('foo.bar')->addNotice($notice2); $this->result->forProperty('foo')->addNotice($notice3); $otherResult->addWarning($warning1); $this->result->addWarning($warning2); $this->result->addWarning($warning3); $otherResult->forProperty('foo')->addError($error1); $otherResult->forProperty('foo')->addError($error2); $otherResult->addError($error3); $this->result->merge($otherResult); $this->assertSame(array($notice1), $this->result->getNotices(), 'Notices are not merged correctly without recursion'); $this->assertSame(array($notice3), $this->result->forProperty('foo')->getNotices(), 'Original sub-notices are overridden.'); $this->assertSame(array($notice2), $this->result->forProperty('foo')->forProperty('bar')->getNotices(), 'Sub-notices are not copied.'); $this->assertSame(array($warning2, $warning3, $warning1), $this->result->getWarnings()); $this->assertSame(array($error3), $this->result->getErrors()); $this->assertSame(array($error1, $error2), $this->result->forProperty('foo')->getErrors()); }
/** * @param \TYPO3\Form\Core\Model\Page $page * @return \TYPO3\Flow\Error\Result * @internal */ protected function mapAndValidatePage(\TYPO3\Form\Core\Model\Page $page) { $result = new \TYPO3\Flow\Error\Result(); $requestArguments = $this->request->getArguments(); $propertyPathsForWhichPropertyMappingShouldHappen = array(); $registerPropertyPaths = function ($propertyPath) use(&$propertyPathsForWhichPropertyMappingShouldHappen) { $propertyPathParts = explode('.', $propertyPath); $accumulatedPropertyPathParts = array(); foreach ($propertyPathParts as $propertyPathPart) { $accumulatedPropertyPathParts[] = $propertyPathPart; $temporaryPropertyPath = implode('.', $accumulatedPropertyPathParts); $propertyPathsForWhichPropertyMappingShouldHappen[$temporaryPropertyPath] = $temporaryPropertyPath; } }; foreach ($page->getElementsRecursively() as $element) { $value = \TYPO3\Flow\Utility\Arrays::getValueByPath($requestArguments, $element->getIdentifier()); $element->onSubmit($this, $value); $this->formState->setFormValue($element->getIdentifier(), $value); $registerPropertyPaths($element->getIdentifier()); } // The more parts the path has, the more early it is processed usort($propertyPathsForWhichPropertyMappingShouldHappen, function ($a, $b) { return substr_count($b, '.') - substr_count($a, '.'); }); $processingRules = $this->formDefinition->getProcessingRules(); foreach ($propertyPathsForWhichPropertyMappingShouldHappen as $propertyPath) { if (isset($processingRules[$propertyPath])) { $processingRule = $processingRules[$propertyPath]; $value = $this->formState->getFormValue($propertyPath); try { $value = $processingRule->process($value); } catch (\TYPO3\Flow\Property\Exception $exception) { throw new \TYPO3\Form\Exception\PropertyMappingException('Failed to process FormValue at "' . $propertyPath . '" from "' . gettype($value) . '" to "' . $processingRule->getDataType() . '"', 1355218921, $exception); } $result->forProperty($propertyPath)->merge($processingRule->getProcessingMessages()); $this->formState->setFormValue($propertyPath, $value); } } return $result; }