protected function matchExtends($selector, &$out, $from = 0, $initial = true)
{
foreach ($selector as $i => $part) {
if ($i < $from) {
continue;
}
if ($this->matchExtendsSingle($part, $origin)) {
$after = array_slice($selector, $i + 1);
$before = array_slice($selector, 0, $i);
list($before, $nonBreakableBefore) = $this->extractRelationshipFromFragment($before);
foreach ($origin as $new) {
$k = 0;
// remove shared parts
if ($initial) {
while ($k < $i && isset($new[$k]) && $selector[$k] === $new[$k]) {
$k++;
}
}
$replacement = [];
$tempReplacement = $k > 0 ? array_slice($new, $k) : $new;
for ($l = count($tempReplacement) - 1; $l >= 0; $l--) {
$slice = $tempReplacement[$l];
array_unshift($replacement, $slice);
if (!$this->isImmediateRelationshipCombinator(end($slice))) {
break;
}
}
$afterBefore = $l != 0 ? array_slice($tempReplacement, 0, $l) : [];
// Merge shared direct relationships.
$mergedBefore = $this->mergeDirectRelationships($afterBefore, $nonBreakableBefore);
$result = array_merge($before, $mergedBefore, $replacement, $after);
if ($result === $selector) {
continue;
}
$out[] = $result;
// recursively check for more matches
$this->matchExtends($result, $out, count($before) + count($mergedBefore), false);
// selector sequence merging
if (!empty($before) && count($new) > 1) {
$sharedParts = $k > 0 ? array_slice($before, 0, $k) : [];
$postSharedParts = $k > 0 ? array_slice($before, $k) : $before;
list($injectBetweenSharedParts, $nonBreakable2) = $this->extractRelationshipFromFragment($afterBefore);
$result2 = array_merge($sharedParts, $injectBetweenSharedParts, $postSharedParts, $nonBreakable2, $nonBreakableBefore, $replacement, $after);
$out[] = $result2;
}
}
}
}
}