public static function getSegments($selector)
{
$selector = trim($selector);
if ($selector === '') {
throw new InvalidArgumentException('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>>)?';
$regexp = '/' . $tag . $id . $classes . $attrs . $pseudo . $rel . '/is';
if (preg_match($regexp, $selector, $segments)) {
if ($segments[0] === '') {
throw new RuntimeException('Invalid selector');
}
$result['selector'] = $segments[0];
if (isset($segments['tag']) and $segments['tag'] !== '') {
$result['tag'] = $segments['tag'];
}
// if the id attribute specified
if (isset($segments['id']) and $segments['id'] !== '') {
$result['id'] = $segments['id'];
}
// if the attributes specified
if (isset($segments['attrs'])) {
$attributes = trim($segments['attrs'], '[]');
$attributes = explode('][', $attributes);
foreach ($attributes as $attribute) {
if ($attribute !== '') {
list($name, $value) = array_pad(explode('=', $attribute, 2), 2, null);
if ($name === '') {
throw new RuntimeException('Invalid selector: attribute name must not be empty');
}
// equal null if specified only the attribute name
$result['attributes'][$name] = is_string($value) ? trim($value, '\'"') : null;
}
}
}
// 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;
}
}
}
// if the pseudo class specified
if (isset($segments['pseudo']) and $segments['pseudo'] !== '') {
$result['pseudo'] = $segments['pseudo'];
if (isset($segments['expr']) and $segments['expr'] !== '') {
$result['expr'] = $segments['expr'];
}
}
// if it is a direct descendant
if (isset($segments['rel'])) {
$result['rel'] = $segments['rel'];
}
return $result;
}
throw new RuntimeException('Invalid selector');
}