Mercurial > hg > cmmr2012-drupal-site
diff vendor/behat/mink/src/Selector/Xpath/Manipulator.php @ 0:c75dbcec494b
Initial commit from drush-created site
author | Chris Cannam |
---|---|
date | Thu, 05 Jul 2018 14:24:15 +0000 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vendor/behat/mink/src/Selector/Xpath/Manipulator.php Thu Jul 05 14:24:15 2018 +0000 @@ -0,0 +1,129 @@ +<?php + +/* + * This file is part of the Mink package. + * (c) Konstantin Kudryashov <ever.zet@gmail.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Mink\Selector\Xpath; + +/** + * XPath manipulation utility. + * + * @author Graham Bates + * @author Christophe Coevoet <stof@notk.org> + */ +class Manipulator +{ + /** + * Regex to find union operators not inside brackets. + */ + const UNION_PATTERN = '/\|(?![^\[]*\])/'; + + /** + * Prepends the XPath prefix to the given XPath. + * + * The returned XPath will match elements matching the XPath inside an element + * matching the prefix. + * + * @param string $xpath + * @param string $prefix + * + * @return string + */ + public function prepend($xpath, $prefix) + { + $expressions = array(); + + // If the xpath prefix contains a union we need to wrap it in parentheses. + if (preg_match(self::UNION_PATTERN, $prefix)) { + $prefix = '('.$prefix.')'; + } + + // Split any unions into individual expressions. + foreach ($this->splitUnionParts($xpath) as $expression) { + $expression = trim($expression); + $parenthesis = ''; + + // If the union is inside some braces, we need to preserve the opening braces and apply + // the prefix only inside it. + if (preg_match('/^[\(\s*]+/', $expression, $matches)) { + $parenthesis = $matches[0]; + $expression = substr($expression, strlen($parenthesis)); + } + + // add prefix before element selector + if (0 === strpos($expression, '/')) { + $expression = $prefix.$expression; + } else { + $expression = $prefix.'/'.$expression; + } + $expressions[] = $parenthesis.$expression; + } + + return implode(' | ', $expressions); + } + + /** + * Splits the XPath into parts that are separated by the union operator. + * + * @param string $xpath + * + * @return string[] + */ + private function splitUnionParts($xpath) + { + if (false === strpos($xpath, '|')) { + return array($xpath); // If there is no pipe in the string, we know for sure that there is no union + } + + $xpathLen = strlen($xpath); + $openedBrackets = 0; + // Consume whitespaces chars at the beginning of the string (this is the list of chars removed by trim() by default) + $startPosition = strspn($xpath, " \t\n\r\0\x0B"); + + $unionParts = array(); + + for ($i = $startPosition; $i <= $xpathLen; ++$i) { + // Consume all chars until we reach a quote, a bracket or a pipe + $i += strcspn($xpath, '"\'[]|', $i); + + if ($i < $xpathLen) { + switch ($xpath[$i]) { + case '"': + case "'": + // Move to the end of the string literal + if (false === $i = strpos($xpath, $xpath[$i], $i + 1)) { + return array($xpath); // The XPath expression is invalid, don't split it + } + continue 2; + case '[': + ++$openedBrackets; + continue 2; + case ']': + --$openedBrackets; + continue 2; + } + } + if ($openedBrackets) { + continue; + } + + $unionParts[] = substr($xpath, $startPosition, $i - $startPosition); + + if ($i === $xpathLen) { + return $unionParts; + } + + // Consume any whitespace chars after the pipe + $i += strspn($xpath, " \t\n\r\0\x0B", $i + 1); + $startPosition = $i + 1; + } + + return array($xpath); // The XPath expression is invalid + } + +}