Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
[Form] Renamed FormMapping to MappingRule and moved some logic there …
…to make rules more extendable
  • Loading branch information
webmozart committed May 22, 2012
1 parent d0d1fe6 commit c8b61d5
Show file tree
Hide file tree
Showing 3 changed files with 120 additions and 103 deletions.

This file was deleted.

@@ -0,0 +1,107 @@
<?php

/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace Symfony\Component\Form\Extension\Validator\ViolationMapper;

use Symfony\Component\Form\FormInterface;
use Symfony\Component\Form\Util\PropertyPathInterface;
use Symfony\Component\Form\Exception\ErrorMappingException;

/**
* @author Bernhard Schussek <bschussek@gmail.com>
*/
class MappingRule
{
/**
* @var FormInterface
*/
private $origin;

/**
* @var string
*/
private $propertyPath;

/**
* @var string
*/
private $targetPath;

public function __construct(FormInterface $origin, $propertyPath, $targetPath)
{
$this->origin = $origin;
$this->propertyPath = $propertyPath;
$this->targetPath = $targetPath;
}

/**
* @return FormInterface
*/
public function getOrigin()
{
return $this->origin;
}

/**
* Matches a property path against the rule path.
*
* If the rule matches, the form mapped by the rule is returned.
* Otherwise this method returns false.
*
* @param string $propertyPath The property path to match against the rule.
*
* @return Boolean|FormInterface The mapped form or false.
*/
public function match($propertyPath)
{
if ($propertyPath === (string) $this->propertyPath) {
return $this->getTarget();
}

return false;
}

/**
* Matches a property path against a prefix of the rule path.
*
* @param string $propertyPath The property path to match against the rule.
*
* @return Boolean Whether the property path is a prefix of the rule or not.
*/
public function isPrefix($propertyPath)
{
$length = strlen($propertyPath);
$prefix = substr($this->propertyPath, 0, $length);
$next = isset($this->propertyPath[$length]) ? $this->propertyPath[$length] : null;

return $prefix === $propertyPath && ('[' === $next || '.' === $next);
}

/**
* @return FormInterface
*
* @throws ErrorMappingException
*/
private function getTarget()
{
$childNames = explode('.', $this->targetPath);
$target = $this->origin;

foreach ($childNames as $childName) {
if (!$target->has($childName)) {
throw new ErrorMappingException(sprintf('The child "%s" of "%s" mapped by the rule "%s" in "%s" does not exist.', $childName, $target->getName(), $this->targetPath, $this->origin->getName()));
}
$target = $target->get($childName);
}

return $target;
}
}
Expand Up @@ -75,16 +75,18 @@ public function mapViolation(ConstraintViolation $violation, FormInterface $form
// mapped form of the violation path
// e.g. "children[foo].children[bar].data.baz"
// Here the innermost directly mapped child is "bar"
$this->setScope($form);

$it = new ViolationPathIterator($violationPath);
// The overhead of setScope() is not needed anymore here
$this->scope = $form;

while ($it->valid() && $it->mapsForm()) {
if (!$this->scope->has($it->current())) {
// Break if we find a reference to a non-existing child
break;
}

$this->setScope($this->scope->get($it->current()));
$this->scope = $this->scope->get($it->current());
$it->next();
}
}
Expand Down Expand Up @@ -129,16 +131,17 @@ private function matchChild(PropertyPathIteratorInterface $it)
}

// Test mapping rules as long as we have any
foreach ($this->rules as $path => $mapping) {
foreach ($this->rules as $key => $rule) {
/* @var MappingRule $rule */

// Mapping rule matches completely, terminate.
if ($chunk === $path) {
/* @var FormMapping $mapping */
return $mapping->getTarget();
if (false !== ($form = $rule->match($chunk))) {
return $form;
}

// Keep only rules that have $chunk as prefix
if (!$this->isPrefixPath($chunk, $path)) {
unset($this->rules[$path]);
if (!$rule->isPrefix($chunk)) {
unset($this->rules[$key]);
}
}

Expand Down Expand Up @@ -249,25 +252,8 @@ private function setScope(FormInterface $form)
$this->children = new \RecursiveIteratorIterator(
new VirtualFormAwareIterator($form->getChildren())
);
foreach ($form->getAttribute('error_mapping') as $propertyPath => $childPath) {
$this->rules[$propertyPath] = new FormMapping($form, $childPath);
foreach ($form->getAttribute('error_mapping') as $propertyPath => $targetPath) {
$this->rules[] = new MappingRule($form, $propertyPath, $targetPath);
}
}

/**
* Tests whether $needle is a prefix path of $haystack.
*
* @param string $needle
* @param string $haystack
*
* @return Boolean
*/
private function isPrefixPath($needle, $haystack)
{
$length = strlen($needle);
$prefix = substr($haystack, 0, $length);
$next = isset($haystack[$length]) ? $haystack[$length] : null;

return $prefix === $needle && ('[' === $next || '.' === $next);
}
}

0 comments on commit c8b61d5

Please sign in to comment.