Skip to content

Commit

Permalink
Refactoring
Browse files Browse the repository at this point in the history
  • Loading branch information
Imangazaliev committed Jul 26, 2021
1 parent 8de492c commit dda9476
Show file tree
Hide file tree
Showing 2 changed files with 66 additions and 64 deletions.
119 changes: 60 additions & 59 deletions src/DiDom/Query.php
Original file line number Diff line number Diff line change
Expand Up @@ -293,7 +293,7 @@ public static function buildXpath(array $segments, $prefix = '//')

// if the pseudo class specified
if (isset($segments['pseudo'])) {
$expression = isset($segments['expr']) ? trim($segments['expr']) : '';
$expression = isset($segments['pseudo-expression']) ? trim($segments['pseudo-expression']) : '';

$parameters = explode(',', $expression);
$parameters = array_map('trim', $parameters);
Expand Down Expand Up @@ -327,7 +327,7 @@ protected static function convertAttribute($name, $value)

if ($isSimpleSelector) {
// if specified only the attribute name
$xpath = $value === null ? '@'.$name : sprintf('@%s="%s"', $name, $value);
$xpath = $value === null ? '@' . $name : sprintf('@%s="%s"', $name, $value);

return $xpath;
}
Expand Down Expand Up @@ -458,85 +458,86 @@ public static function getSegments($selector)
$selector = trim($selector);

if ($selector === '') {
throw new InvalidSelectorException('The selector must not be empty');
throw new InvalidSelectorException('The selector must not be empty.');
}

$tag = '(?P<tag>[\*|\w|\-]+)?';
$id = '(?:#(?P<id>[\w|\-]+))?';
$classes = '(?P<classes>\.[\w|\-|\.]+)*';
$attrs = '(?P<attrs>(?:\[.+?\])*)?';
$name = '(?P<pseudo>[\w\-]+)';
$expr = '(?:\((?P<expr>[^\)]+)\))';
$pseudo = '(?::'.$name.$expr.'?)?';
$rel = '\s*(?P<rel>>)?';
$pregMatchResult = preg_match(self::getSelectorRegex(), $selector, $segments);

$regexp = '/'.$tag.$id.$classes.$attrs.$pseudo.$rel.'/is';

if (preg_match($regexp, $selector, $segments)) {
if ($segments[0] === '') {
throw new InvalidSelectorException(sprintf('Invalid selector "%s"', $selector));
}

$result['selector'] = $segments[0];
if ($pregMatchResult === false || $pregMatchResult === 0 || $segments[0] === '') {
throw new InvalidSelectorException(sprintf('Invalid selector "%s".', $selector));
}

if (isset($segments['tag']) && $segments['tag'] !== '') {
$result['tag'] = $segments['tag'];
}
$result = ['selector' => $segments[0]];

// if the id attribute specified
if (isset($segments['id']) && $segments['id'] !== '') {
$result['id'] = $segments['id'];
}
if (isset($segments['tag']) && $segments['tag'] !== '') {
$result['tag'] = $segments['tag'];
}

// if the attributes specified
if (isset($segments['attrs'])) {
$attributes = trim($segments['attrs'], '[]');
$attributes = explode('][', $attributes);
// if the id attribute specified
if (isset($segments['id']) && $segments['id'] !== '') {
$result['id'] = $segments['id'];
}

foreach ($attributes as $attribute) {
if ($attribute !== '') {
list($name, $value) = array_pad(explode('=', $attribute, 2), 2, null);
// if the attributes specified
if (isset($segments['attrs'])) {
$attributes = trim($segments['attrs'], '[]');
$attributes = explode('][', $attributes);

if ($name === '') {
throw new InvalidSelectorException(sprintf('Invalid selector "%s": attribute name must not be empty', $selector));
}
foreach ($attributes as $attribute) {
if ($attribute !== '') {
list($name, $value) = array_pad(explode('=', $attribute, 2), 2, null);

// equal null if specified only the attribute name
$result['attributes'][$name] = is_string($value) ? trim($value, '\'"') : null;
if ($name === '') {
throw new InvalidSelectorException(sprintf('Invalid selector "%s": attribute name must not be empty', $selector));
}
}
}

// if the class attribute specified
if (isset($segments['classes'])) {
$classes = trim($segments['classes'], '.');
$classes = explode('.', $classes);

foreach ($classes as $class) {
if ($class !== '') {
$result['classes'][] = $class;
}
// equal null if specified only the attribute name
$result['attributes'][$name] = is_string($value) ? trim($value, '\'"') : null;
}
}
}

// if the pseudo class specified
if (isset($segments['pseudo']) && $segments['pseudo'] !== '') {
$result['pseudo'] = $segments['pseudo'];
// if the class attribute specified
if (isset($segments['classes'])) {
$classes = trim($segments['classes'], '.');
$classes = explode('.', $classes);

if (isset($segments['expr']) && $segments['expr'] !== '') {
$result['expr'] = $segments['expr'];
foreach ($classes as $class) {
if ($class !== '') {
$result['classes'][] = $class;
}
}
}

// if it is a direct descendant
if (isset($segments['rel'])) {
$result['rel'] = $segments['rel'];
// if the pseudo class specified
if (isset($segments['pseudo']) && $segments['pseudo'] !== '') {
$result['pseudo'] = $segments['pseudo'];

if (isset($segments['pseudoExpr']) && $segments['pseudoExpr'] !== '') {
$result['pseudo-expression'] = $segments['pseudoExpr'];
}
}

return $result;
// if it is a direct descendant
if (isset($segments['rel'])) {
$result['rel'] = $segments['rel'];
}

throw new InvalidSelectorException(sprintf('Invalid selector "%s"', $selector));
return $result;
}

private static function getSelectorRegex()
{
$tag = '(?P<tag>[\*|\w|\-]+)?';
$id = '(?:#(?P<id>[\w|\-]+))?';
$classes = '(?P<classes>\.[\w|\-|\.]+)*';
$attrs = '(?P<attrs>(?:\[.+?\])*)?';
$pseudoType = '(?P<pseudo>[\w\-]+)';
$pseudoExpr = '(?:\((?P<pseudoExpr>[^\)]+)\))';
$pseudo = '(?::' . $pseudoType . $pseudoExpr . '?)?';
$rel = '\s*(?P<rel>>)?';

return '/' . $tag . $id . $classes . $attrs . $pseudo . $rel . '/is';
}

/**
Expand Down
11 changes: 6 additions & 5 deletions tests/QueryTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ public function testCompileWithEmptyCssExpression()

/**
* @expectedException \DiDom\Exceptions\InvalidSelectorException
* @expectedExceptionMessage The selector must not be empty
* @expectedExceptionMessage The selector must not be empty.
*/
public function testGetSegmentsWithEmptySelector()
{
Expand Down Expand Up @@ -177,7 +177,7 @@ public function testUnknownNthExpression()

/**
* @expectedException \DiDom\Exceptions\InvalidSelectorException
* @expectedExceptionMessage Invalid selector "."
* @expectedExceptionMessage Invalid selector ".".
*/
public function testGetSegmentsWithEmptyClassName()
{
Expand All @@ -186,7 +186,7 @@ public function testGetSegmentsWithEmptyClassName()

/**
* @expectedException \DiDom\Exceptions\InvalidSelectorException
* @expectedExceptionMessage Invalid selector "."
* @expectedExceptionMessage Invalid selector ".".
*/
public function testCompilehWithEmptyClassName()
{
Expand Down Expand Up @@ -239,7 +239,8 @@ public function compileCssTests()
['foo bar baz', '//foo//bar//baz'],
['foo > bar > baz', '//foo/bar/baz'],
['#foo', '//*[@id="foo"]'],
['.bar', '//*[contains(concat(" ", normalize-space(@class), " "), " bar ")]'],
['.foo', '//*[contains(concat(" ", normalize-space(@class), " "), " foo ")]'],
['.foo.bar', '//*[(contains(concat(" ", normalize-space(@class), " "), " foo ")) and (contains(concat(" ", normalize-space(@class), " "), " bar "))]'],
['*[foo=bar]', '//*[@foo="bar"]'],
['*[foo="bar"]', '//*[@foo="bar"]'],
['*[foo=\'bar\']', '//*[@foo="bar"]'],
Expand Down Expand Up @@ -418,7 +419,7 @@ public function getSegmentsTests()
['selector' => 'li:first-child', 'tag' => 'li', 'pseudo' => 'first-child'],
['selector' => 'ul >', 'tag' => 'ul', 'rel' => '>'],
['selector' => '#id.foo[name=value]:first-child >', 'id' => 'id', 'classes' => ['foo'], 'attributes' => ['name' => 'value'], 'pseudo' => 'first-child', 'rel' => '>'],
['selector' => 'li.bar:nth-child(2n)', 'tag' => 'li', 'classes' => ['bar'], 'pseudo' => 'nth-child', 'expr' => '2n'],
['selector' => 'li.bar:nth-child(2n)', 'tag' => 'li', 'classes' => ['bar'], 'pseudo' => 'nth-child', 'pseudo-expression' => '2n'],
];

$parameters = [];
Expand Down

0 comments on commit dda9476

Please sign in to comment.