kekrozsak/vendor/symfony/symfony/src/Symfony/Component/CssSelector/Node/AttribNode.php
Polonkai Gergely 082a0130c2 Initial commit with Symfony 2.1+Vendors
Signed-off-by: Gergely POLONKAI (W00d5t0ck) <polesz@w00d5t0ck.info>
2012-07-01 09:52:20 +02:00

132 lines
4.4 KiB
PHP

<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\CssSelector\Node;
use Symfony\Component\CssSelector\XPathExpr;
use Symfony\Component\CssSelector\Exception\ParseException;
/**
* AttribNode represents a "selector[namespace|attrib operator value]" node.
*
* This component is a port of the Python lxml library,
* which is copyright Infrae and distributed under the BSD license.
*
* @author Fabien Potencier <fabien@symfony.com>
*/
class AttribNode implements NodeInterface
{
protected $selector;
protected $namespace;
protected $attrib;
protected $operator;
protected $value;
/**
* Constructor.
*
* @param NodeInterface $selector The XPath selector
* @param string $namespace The namespace
* @param string $attrib The attribute
* @param string $operator The operator
* @param string $value The value
*/
public function __construct($selector, $namespace, $attrib, $operator, $value)
{
$this->selector = $selector;
$this->namespace = $namespace;
$this->attrib = $attrib;
$this->operator = $operator;
$this->value = $value;
}
/**
* {@inheritDoc}
*/
public function __toString()
{
if ($this->operator == 'exists') {
return sprintf('%s[%s[%s]]', __CLASS__, $this->selector, $this->formatAttrib());
}
return sprintf('%s[%s[%s %s %s]]', __CLASS__, $this->selector, $this->formatAttrib(), $this->operator, $this->value);
}
/**
* {@inheritDoc}
*/
public function toXpath()
{
$path = $this->selector->toXpath();
$attrib = $this->xpathAttrib();
$value = $this->value;
if ($this->operator == 'exists') {
$path->addCondition($attrib);
} elseif ($this->operator == '=') {
$path->addCondition(sprintf('%s = %s', $attrib, XPathExpr::xpathLiteral($value)));
} elseif ($this->operator == '!=') {
// FIXME: this seems like a weird hack...
if ($value) {
$path->addCondition(sprintf('not(%s) or %s != %s', $attrib, $attrib, XPathExpr::xpathLiteral($value)));
} else {
$path->addCondition(sprintf('%s != %s', $attrib, XPathExpr::xpathLiteral($value)));
}
// path.addCondition('%s != %s' % (attrib, xpathLiteral(value)))
} elseif ($this->operator == '~=') {
$path->addCondition(sprintf("contains(concat(' ', normalize-space(%s), ' '), %s)", $attrib, XPathExpr::xpathLiteral(' '.$value.' ')));
} elseif ($this->operator == '|=') {
// Weird, but true...
$path->addCondition(sprintf('%s = %s or starts-with(%s, %s)', $attrib, XPathExpr::xpathLiteral($value), $attrib, XPathExpr::xpathLiteral($value.'-')));
} elseif ($this->operator == '^=') {
$path->addCondition(sprintf('starts-with(%s, %s)', $attrib, XPathExpr::xpathLiteral($value)));
} elseif ($this->operator == '$=') {
// Oddly there is a starts-with in XPath 1.0, but not ends-with
$path->addCondition(sprintf('substring(%s, string-length(%s)-%s) = %s', $attrib, $attrib, strlen($value) - 1, XPathExpr::xpathLiteral($value)));
} elseif ($this->operator == '*=') {
// FIXME: case sensitive?
$path->addCondition(sprintf('contains(%s, %s)', $attrib, XPathExpr::xpathLiteral($value)));
} else {
throw new ParseException(sprintf('Unknown operator: %s', $this->operator));
}
return $path;
}
/**
* Returns the XPath Attribute
*
* @return string The XPath attribute
*/
protected function xpathAttrib()
{
// FIXME: if attrib is *?
if ($this->namespace == '*') {
return '@'.$this->attrib;
}
return sprintf('@%s:%s', $this->namespace, $this->attrib);
}
/**
* Returns a formatted attribute
*
* @return string The formatted attribute
*/
protected function formatAttrib()
{
if ($this->namespace == '*') {
return $this->attrib;
}
return sprintf('%s|%s', $this->namespace, $this->attrib);
}
}