/** * 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); } } // Skip forms inheriting their parent data when iterating the children $childIterator = new \RecursiveIteratorIterator(new InheritDataAwareIterator($form)); // 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; }
/** * 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) { $target = null; $chunk = ''; $foundAtIndex = null; // 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); } } $children = iterator_to_array(new \RecursiveIteratorIterator(new InheritDataAwareIterator($form)), false); while ($it->valid()) { 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]); } } /** @var FormInterface $child */ foreach ($children as $i => $child) { $childPath = (string) $child->getPropertyPath(); if ($childPath === $chunk) { $target = $child; $foundAtIndex = $it->key(); } elseif (0 === strpos($childPath, $chunk)) { continue; } unset($children[$i]); } $it->next(); } if (null !== $foundAtIndex) { $it->seek($foundAtIndex); } return $target; }