public function __construct(FieldConfigInterface $fieldConfig, ValuesBag $valuesBag, $maxCount = 100, $groupIdx = 0, $level = 0) { $this->config = $fieldConfig; $this->valuesBag = $valuesBag; $this->maxCount = $maxCount; $this->groupIdx = $groupIdx; $this->level = $level; $this->count = $valuesBag->count(); }
/** * @param ValuesBag $valuesBag * * @return string */ protected function exportValues(ValuesBag $valuesBag, FieldConfigInterface $field) { $exportedValues = []; foreach ($valuesBag->getSimpleValues() as $value) { $exportedValues['single-values'][] = $this->normToView($value, $field); } foreach ($valuesBag->getExcludedSimpleValues() as $value) { $exportedValues['excluded-values'][] = $this->normToView($value, $field); } foreach ($valuesBag->get(Range::class) as $value) { $exportedValues['ranges'][] = $this->exportRangeValue($value, $field); } foreach ($valuesBag->get(ExcludedRange::class) as $value) { $exportedValues['excluded-ranges'][] = $this->exportRangeValue($value, $field); } foreach ($valuesBag->get(Compare::class) as $value) { $exportedValues['comparisons'][] = ['operator' => $value->getOperator(), 'value' => $this->normToView($value->getValue(), $field)]; } foreach ($valuesBag->get(PatternMatch::class) as $value) { $exportedValues['pattern-matchers'][] = ['type' => $this->getPatternMatchType($value), 'value' => $value->getValue(), 'case-insensitive' => $value->isCaseInsensitive()]; } return $exportedValues; }
/** * @param ValuesBag $valuesBag * * @return string */ private function exportValues(ValuesBag $valuesBag, FieldConfigInterface $field) { $exportedValues = ''; foreach ($valuesBag->getSimpleValues() as $value) { $exportedValues .= $this->exportValuePart($this->normToView($value, $field)) . ', '; } foreach ($valuesBag->getExcludedSimpleValues() as $value) { $exportedValues .= '!' . $this->exportValuePart($this->normToView($value, $field)) . ', '; } foreach ($valuesBag->get(Range::class) as $value) { $exportedValues .= $this->exportRangeValue($value, $field) . ', '; } foreach ($valuesBag->get(ExcludedRange::class) as $value) { $exportedValues .= '!' . $this->exportRangeValue($value, $field) . ', '; } foreach ($valuesBag->get(Compare::class) as $value) { $exportedValues .= $value->getOperator() . $this->exportValuePart($this->normToView($value->getValue(), $field)) . ', '; } foreach ($valuesBag->get(PatternMatch::class) as $value) { $exportedValues .= $this->getPatternMatchOperator($value) . $this->exportValuePart($value->getValue()) . ', '; } return rtrim($exportedValues, ', '); }
/** * @param ValuesBag $valuesBag * @param \DOMNode $parent * * @return \DOMNode */ private function exportValuesToNode(ValuesBag $valuesBag, \DOMNode $parent, FieldConfigInterface $field) { if ($valuesBag->hasSimpleValues()) { $valuesNode = $this->document->createElement('single-values'); foreach ($valuesBag->getSimpleValues() as $value) { $element = $this->document->createElement('value'); $element->appendChild($this->document->createTextNode($this->normToView($value, $field))); $valuesNode->appendChild($element); } $parent->appendChild($valuesNode); } if ($valuesBag->hasExcludedSimpleValues()) { $valuesNode = $this->document->createElement('excluded-values'); foreach ($valuesBag->getExcludedSimpleValues() as $value) { $element = $this->document->createElement('value'); $element->appendChild($this->document->createTextNode($this->normToView($value, $field))); $valuesNode->appendChild($element); } $parent->appendChild($valuesNode); } if ($valuesBag->has(Range::class)) { $valuesNode = $this->document->createElement('ranges'); foreach ($valuesBag->get(Range::class) as $value) { $this->exportRangeValueToNode($valuesNode, $value, $field); } $parent->appendChild($valuesNode); } if ($valuesBag->has(ExcludedRange::class)) { $valuesNode = $this->document->createElement('excluded-ranges'); foreach ($valuesBag->get(ExcludedRange::class) as $value) { $this->exportRangeValueToNode($valuesNode, $value, $field); } $parent->appendChild($valuesNode); } if ($valuesBag->has(Compare::class)) { $valuesNode = $this->document->createElement('comparisons'); foreach ($valuesBag->get(Compare::class) as $value) { $element = $this->document->createElement('compare'); $element->setAttribute('operator', $value->getOperator()); $element->appendChild($this->document->createTextNode($this->normToView($value->getValue(), $field))); $valuesNode->appendChild($element); } $parent->appendChild($valuesNode); } if ($valuesBag->has(PatternMatch::class)) { $valuesNode = $this->document->createElement('pattern-matchers'); foreach ($valuesBag->get(PatternMatch::class) as $value) { $element = $this->document->createElement('pattern-matcher'); $element->setAttribute('type', strtolower($this->getPatternMatchType($value))); $element->setAttribute('case-insensitive', $value->isCaseInsensitive() ? 'true' : 'false'); $element->appendChild($this->document->createTextNode($value->getValue())); $valuesNode->appendChild($element); } $parent->appendChild($valuesNode); } }
protected function assertValueBagsEqual(ValuesBag $expected, ValuesBag $result) { $expectedArray = ['single' => $expected->getSimpleValues(), 'excluded' => $expected->getExcludedSimpleValues(), 'ranges' => $expected->get(Range::class), 'excludedRanges' => $expected->get(ExcludedRange::class), 'compares' => $expected->get(Compare::class), 'matchers' => $expected->get(PatternMatch::class)]; // use array_merge to renumber indexes and prevent mismatches $resultArray = ['single' => array_merge([], $result->getSimpleValues()), 'excluded' => array_merge([], $result->getExcludedSimpleValues()), 'ranges' => array_merge([], $result->get(Range::class)), 'excludedRanges' => array_merge([], $result->get(ExcludedRange::class)), 'compares' => array_merge([], $result->get(Compare::class)), 'matchers' => array_merge([], $result->get(PatternMatch::class))]; $this->assertEquals($expectedArray, $resultArray); }
/** * @param ValuesBag $valuesBag * @param ValueComparisonInterface $comparison * @param array $options */ private function removeDuplicateMatchers(ValuesBag $valuesBag, ValueComparisonInterface $comparison, array $options) { /** @var PatternMatch[] $matchers */ $matchers = $valuesBag->get(PatternMatch::class); foreach ($matchers as $i => $value) { foreach ($matchers as $c => $value2) { if ($i === $c) { continue; } if ($value->isCaseInsensitive() === $value2->isCaseInsensitive() && $value->getType() === $value2->getType() && $comparison->isEqual($value->getValue(), $value2->getValue(), $options)) { $valuesBag->remove(PatternMatch::class, $i); unset($matchers[$i]); } } } }
/** * Optimizes connected ranges. * * A range is connected when the upper-bound is equal to the lower-bound of the * second range, but only when the bounds inclusiveness are equal they can be optimized. * * @param Range[] $ranges * @param ValuesBag $valuesBag * @param ValueComparisonInterface $comparison * @param array $options */ private function optimizeConnectedRanges(array $ranges, ValuesBag $valuesBag, ValueComparisonInterface $comparison, array $options, $exclude = false) { $class = $exclude ? ExcludedRange::class : Range::class; foreach ($ranges as $i => $range) { // If the range is already removed just ignore it. if (!isset($ranges[$i])) { continue; } foreach ($ranges as $c => $value) { if ($i === $c) { continue; } if ($range->isLowerInclusive() !== $value->isLowerInclusive() || $range->isUpperInclusive() !== $value->isUpperInclusive()) { continue; } if ($comparison->isEqual($range->getUpper(), $value->getLower(), $options)) { $newRange = new $class($range->getLower(), $value->getUpper(), $range->isLowerInclusive(), $range->isUpperInclusive(), $range->getViewLower(), $value->getViewUpper()); $valuesBag->remove($class, $i); $valuesBag->remove($class, $c); $valuesBag->add($newRange); unset($ranges[$i], $ranges[$c]); } } } }
/** * Converts a list of values to ranges. * * @param array $values * @param ValuesBag $valuesBag * @param FieldConfigInterface $config * @param bool $exclude */ private function listToRanges($values, ValuesBag $valuesBag, FieldConfigInterface $config, $exclude = false) { $class = $exclude ? ExcludedRange::class : Range::class; /** @var ValueIncrementerInterface $comparison */ $comparison = $config->getValueComparison(); $options = $config->getOptions(); $prevIndex = null; $prevValue = null; $rangeLower = null; $rangeUpper = null; $valuesCount = count($values); $curCount = 0; foreach ($values as $valIndex => $value) { ++$curCount; if (null === $prevValue) { $prevIndex = $valIndex; $prevValue = $value; continue; } $unsetIndex = null; $increasedValue = $comparison->getIncrementedValue($prevValue, $options); if ($comparison->isEqual($value, $increasedValue, $options)) { if (null === $rangeLower) { $rangeLower = $prevValue; } $rangeUpper = $value; } if (null !== $rangeUpper) { $unsetIndex = $prevIndex; if ($curCount === $valuesCount || !$comparison->isEqual($value, $increasedValue, $options)) { $range = new $class($rangeLower, $rangeUpper, true, true); $valuesBag->add($range); $unsetIndex = $prevIndex; if ($curCount === $valuesCount) { $unsetIndex = $valIndex; } $rangeLower = $rangeUpper = null; } $prevIndex = $valIndex; $prevValue = $value; } if (null !== $unsetIndex) { if ($exclude) { $valuesBag->removeExcludedSimpleValue($unsetIndex); } else { $valuesBag->removeSimpleValue($unsetIndex); } } } }