vendor/symfony/src/Symfony/Component/CssSelector/Node/AttribNode.php
changeset 0 7f95f8617b0b
equal deleted inserted replaced
-1:000000000000 0:7f95f8617b0b
       
     1 <?php
       
     2 
       
     3 /*
       
     4  * This file is part of the Symfony package.
       
     5  *
       
     6  * (c) Fabien Potencier <fabien@symfony.com>
       
     7  *
       
     8  * For the full copyright and license information, please view the LICENSE
       
     9  * file that was distributed with this source code.
       
    10  */
       
    11 
       
    12 namespace Symfony\Component\CssSelector\Node;
       
    13 
       
    14 use Symfony\Component\CssSelector\XPathExpr;
       
    15 use Symfony\Component\CssSelector\Exception\ParseException;
       
    16 
       
    17 /**
       
    18  * AttribNode represents a "selector[namespace|attrib operator value]" node.
       
    19  *
       
    20  * This component is a port of the Python lxml library,
       
    21  * which is copyright Infrae and distributed under the BSD license.
       
    22  *
       
    23  * @author Fabien Potencier <fabien@symfony.com>
       
    24  */
       
    25 class AttribNode implements NodeInterface
       
    26 {
       
    27     protected $selector;
       
    28     protected $namespace;
       
    29     protected $attrib;
       
    30     protected $operator;
       
    31     protected $value;
       
    32 
       
    33     /**
       
    34      * Constructor.
       
    35      *
       
    36      * @param NodeInterface $selector The XPath selector
       
    37      * @param string $namespace The namespace
       
    38      * @param string $attrib The attribute
       
    39      * @param string $operator The operator
       
    40      * @param string $value The value
       
    41      */
       
    42     public function __construct($selector, $namespace, $attrib, $operator, $value)
       
    43     {
       
    44         $this->selector = $selector;
       
    45         $this->namespace = $namespace;
       
    46         $this->attrib = $attrib;
       
    47         $this->operator = $operator;
       
    48         $this->value = $value;
       
    49     }
       
    50 
       
    51     /**
       
    52      * {@inheritDoc}
       
    53      */
       
    54     public function __toString()
       
    55     {
       
    56         if ($this->operator == 'exists') {
       
    57             return sprintf('%s[%s[%s]]', __CLASS__, $this->selector, $this->formatAttrib());
       
    58         }
       
    59 
       
    60         return sprintf('%s[%s[%s %s %s]]', __CLASS__, $this->selector, $this->formatAttrib(), $this->operator, $this->value);
       
    61     }
       
    62 
       
    63     /**
       
    64      * {@inheritDoc}
       
    65      */
       
    66     public function toXpath()
       
    67     {
       
    68         $path = $this->selector->toXpath();
       
    69         $attrib = $this->xpathAttrib();
       
    70         $value = $this->value;
       
    71         if ($this->operator == 'exists') {
       
    72             $path->addCondition($attrib);
       
    73         } elseif ($this->operator == '=') {
       
    74             $path->addCondition(sprintf('%s = %s', $attrib, XPathExpr::xpathLiteral($value)));
       
    75         } elseif ($this->operator == '!=') {
       
    76             // FIXME: this seems like a weird hack...
       
    77             if ($value) {
       
    78                 $path->addCondition(sprintf('not(%s) or %s != %s', $attrib, $attrib, XPathExpr::xpathLiteral($value)));
       
    79             } else {
       
    80                 $path->addCondition(sprintf('%s != %s', $attrib, XPathExpr::xpathLiteral($value)));
       
    81             }
       
    82             // path.addCondition('%s != %s' % (attrib, xpathLiteral(value)))
       
    83         } elseif ($this->operator == '~=') {
       
    84             $path->addCondition(sprintf("contains(concat(' ', normalize-space(%s), ' '), %s)", $attrib, XPathExpr::xpathLiteral(' '.$value.' ')));
       
    85         } elseif ($this->operator == '|=') {
       
    86             // Weird, but true...
       
    87             $path->addCondition(sprintf('%s = %s or starts-with(%s, %s)', $attrib, XPathExpr::xpathLiteral($value), $attrib, XPathExpr::xpathLiteral($value.'-')));
       
    88         } elseif ($this->operator == '^=') {
       
    89             $path->addCondition(sprintf('starts-with(%s, %s)', $attrib, XPathExpr::xpathLiteral($value)));
       
    90         } elseif ($this->operator == '$=') {
       
    91             // Oddly there is a starts-with in XPath 1.0, but not ends-with
       
    92             $path->addCondition(sprintf('substring(%s, string-length(%s)-%s) = %s', $attrib, $attrib, strlen($value) - 1, XPathExpr::xpathLiteral($value)));
       
    93         } elseif ($this->operator == '*=') {
       
    94             // FIXME: case sensitive?
       
    95             $path->addCondition(sprintf('contains(%s, %s)', $attrib, XPathExpr::xpathLiteral($value)));
       
    96         } else {
       
    97             throw new ParseException(sprintf('Unknown operator: %s', $this->operator));
       
    98         }
       
    99 
       
   100         return $path;
       
   101     }
       
   102 
       
   103     /**
       
   104      * Returns the XPath Attribute
       
   105      *
       
   106      * @return string The XPath attribute
       
   107      */
       
   108     protected function xpathAttrib()
       
   109     {
       
   110         // FIXME: if attrib is *?
       
   111         if ($this->namespace == '*') {
       
   112             return '@'.$this->attrib;
       
   113         }
       
   114 
       
   115         return sprintf('@%s:%s', $this->namespace, $this->attrib);
       
   116     }
       
   117 
       
   118     /**
       
   119      * Returns a formatted attribute
       
   120      *
       
   121      * @return string The formatted attribute
       
   122      */
       
   123     protected function formatAttrib()
       
   124     {
       
   125         if ($this->namespace == '*') {
       
   126             return $this->attrib;
       
   127         }
       
   128 
       
   129         return sprintf('%s|%s', $this->namespace, $this->attrib);
       
   130     }
       
   131 }