/**
  * Tries to match the beginning of the property path at the
  * current position against the children of the scope.
  *
  * If a matching child is found, it is returned. Otherwise
  * null is returned.
  *
  * @param FormInterface                 $form The form to search.
  * @param PropertyPathIteratorInterface $it   The iterator at its current position.
  *
  * @return null|FormInterface The found match or null.
  */
 private function matchChild(FormInterface $form, PropertyPathIteratorInterface $it)
 {
     // Remember at what property path underneath "data"
     // we are looking. Check if there is a child with that
     // path, otherwise increase path by one more piece
     $chunk = '';
     $foundChild = null;
     $foundAtIndex = 0;
     // Construct mapping rules for the given form
     $rules = array();
     foreach ($form->getConfig()->getOption('error_mapping') as $propertyPath => $targetPath) {
         // Dot rules are considered at the very end
         if ('.' !== $propertyPath) {
             $rules[] = new MappingRule($form, $propertyPath, $targetPath);
         }
     }
     // Ignore virtual forms when iterating the children
     $childIterator = new \RecursiveIteratorIterator(new VirtualFormAwareIterator($form->all()));
     // Make the path longer until we find a matching child
     while (true) {
         if (!$it->valid()) {
             return null;
         }
         if ($it->isIndex()) {
             $chunk .= '[' . $it->current() . ']';
         } else {
             $chunk .= ('' === $chunk ? '' : '.') . $it->current();
         }
         // Test mapping rules as long as we have any
         foreach ($rules as $key => $rule) {
             /* @var MappingRule $rule */
             // Mapping rule matches completely, terminate.
             if (null !== ($form = $rule->match($chunk))) {
                 return $form;
             }
             // Keep only rules that have $chunk as prefix
             if (!$rule->isPrefix($chunk)) {
                 unset($rules[$key]);
             }
         }
         // Test children unless we already found one
         if (null === $foundChild) {
             foreach ($childIterator as $child) {
                 /* @var FormInterface $child */
                 $childPath = (string) $child->getPropertyPath();
                 // Child found, mark as return value
                 if ($chunk === $childPath) {
                     $foundChild = $child;
                     $foundAtIndex = $it->key();
                 }
             }
         }
         // Add element to the chunk
         $it->next();
         // If we reached the end of the path or if there are no
         // more matching mapping rules, return the found child
         if (null !== $foundChild && (!$it->valid() || count($rules) === 0)) {
             // Reset index in case we tried to find mapping
             // rules further down the path
             $it->seek($foundAtIndex);
             return $foundChild;
         }
     }
     return null;
 }
Beispiel #2
0
 /**
  * Tries to match the beginning of the property path at the
  * current position against the children of the scope.
  *
  * If a matching child is found, it is returned. Otherwise
  * null is returned.
  *
  * @param PropertyPathIteratorInterface $it The iterator at its current position.
  *
  * @return null|FormInterface The found match or null.
  */
 private function matchChild(PropertyPathIteratorInterface $it)
 {
     // Remember at what property path underneath "data"
     // we are looking. Check if there is a child with that
     // path, otherwise increase path by one more piece
     $chunk = '';
     $foundChild = null;
     $foundAtIndex = 0;
     // Make the path longer until we find a matching child
     while (true) {
         if (!$it->valid()) {
             return null;
         }
         if ($it->isIndex()) {
             $chunk .= '[' . $it->current() . ']';
         } else {
             $chunk .= ('' === $chunk ? '' : '.') . $it->current();
         }
         // Test mapping rules as long as we have any
         foreach ($this->rules as $key => $rule) {
             /* @var MappingRule $rule */
             // Mapping rule matches completely, terminate.
             if (null !== ($form = $rule->match($chunk))) {
                 return $form;
             }
             // Keep only rules that have $chunk as prefix
             if (!$rule->isPrefix($chunk)) {
                 unset($this->rules[$key]);
             }
         }
         // Test children unless we already found one
         if (null === $foundChild) {
             foreach ($this->children as $child) {
                 /* @var FormInterface $child */
                 $childPath = (string) $child->getPropertyPath();
                 // Child found, move scope inwards
                 if ($chunk === $childPath) {
                     $foundChild = $child;
                     $foundAtIndex = $it->key();
                 }
             }
         }
         // Add element to the chunk
         $it->next();
         // If we reached the end of the path or if there are no
         // more matching mapping rules, return the found child
         if (null !== $foundChild && (!$it->valid() || count($this->rules) === 0)) {
             // Reset index in case we tried to find mapping
             // rules further down the path
             $it->seek($foundAtIndex);
             return $foundChild;
         }
     }
     return null;
 }