vendor/symfony/src/Symfony/Component/DomCrawler/Crawler.php
author ymh <ymh.work@gmail.com>
Sat, 24 Sep 2011 15:40:41 +0200
changeset 0 7f95f8617b0b
permissions -rwxr-xr-x
first commit
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
0
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
     1
<?php
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
     2
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
     3
/*
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
     4
 * This file is part of the Symfony package.
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
     5
 *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
     6
 * (c) Fabien Potencier <fabien@symfony.com>
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
     7
 *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
     8
 * For the full copyright and license information, please view the LICENSE
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
     9
 * file that was distributed with this source code.
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    10
 */
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    11
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    12
namespace Symfony\Component\DomCrawler;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    13
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    14
use Symfony\Component\CssSelector\CssSelector;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    15
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    16
/**
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    17
 * Crawler eases navigation of a list of \DOMNode objects.
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    18
 *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    19
 * @author Fabien Potencier <fabien@symfony.com>
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    20
 *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    21
 * @api
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    22
 */
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    23
class Crawler extends \SplObjectStorage
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    24
{
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    25
    private $uri;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    26
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    27
    /**
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    28
     * Constructor.
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    29
     *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    30
     * @param mixed  $node A Node to use as the base for the crawling
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    31
     * @param string $uri  The current URI or the base href value
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    32
     *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    33
     * @api
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    34
     */
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    35
    public function __construct($node = null, $uri = null)
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    36
    {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    37
        $this->uri = $uri;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    38
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    39
        $this->add($node);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    40
    }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    41
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    42
    /**
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    43
     * Removes all the nodes.
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    44
     *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    45
     * @api
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    46
     */
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    47
    public function clear()
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    48
    {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    49
        $this->removeAll($this);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    50
    }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    51
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    52
    /**
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    53
     * Adds a node to the current list of nodes.
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    54
     *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    55
     * This method uses the appropriate specialized add*() method based
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    56
     * on the type of the argument.
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    57
     *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    58
     * @param null|\DOMNodeList|array|\DOMNode $node A node
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    59
     *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    60
     * @api
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    61
     */
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    62
    public function add($node)
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    63
    {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    64
        if ($node instanceof \DOMNodeList) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    65
            $this->addNodeList($node);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    66
        } elseif (is_array($node)) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    67
            $this->addNodes($node);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    68
        } elseif (is_string($node)) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    69
            $this->addContent($node);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    70
        } elseif (is_object($node)) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    71
            $this->addNode($node);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    72
        }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    73
    }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    74
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    75
    /**
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    76
     * Adds HTML/XML content.
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    77
     *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    78
     * @param string $content A string to parse as HTML/XML
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    79
     * @param string $type    The content type of the string
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    80
     */
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    81
    public function addContent($content, $type = null)
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    82
    {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    83
        if (empty($type)) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    84
            $type = 'text/html';
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    85
        }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    86
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    87
        // DOM only for HTML/XML content
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    88
        if (!preg_match('/(x|ht)ml/i', $type, $matches)) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    89
            return null;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    90
        }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    91
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    92
        $charset = 'ISO-8859-1';
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    93
        if (false !== $pos = strpos($type, 'charset=')) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    94
            $charset = substr($type, $pos + 8);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    95
            if (false !== $pos = strpos($charset, ';')) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    96
                $charset = substr($charset, 0, $pos);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    97
            }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    98
        }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    99
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   100
        if ('x' === $matches[1]) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   101
            $this->addXmlContent($content, $charset);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   102
        } else {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   103
            $this->addHtmlContent($content, $charset);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   104
        }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   105
    }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   106
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   107
    /**
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   108
     * Adds an HTML content to the list of nodes.
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   109
     *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   110
     * @param string $content The HTML content
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   111
     * @param string $charset The charset
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   112
     *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   113
     * @api
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   114
     */
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   115
    public function addHtmlContent($content, $charset = 'UTF-8')
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   116
    {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   117
        $dom = new \DOMDocument('1.0', $charset);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   118
        $dom->validateOnParse = true;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   119
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   120
        @$dom->loadHTML($content);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   121
        $this->addDocument($dom);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   122
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   123
        $base = $this->filter('base')->extract(array('href'));
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   124
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   125
        if (count($base)) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   126
            $this->uri = current($base);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   127
        }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   128
    }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   129
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   130
    /**
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   131
     * Adds an XML content to the list of nodes.
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   132
     *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   133
     * @param string $content The XML content
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   134
     * @param string $charset The charset
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   135
     *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   136
     * @api
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   137
     */
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   138
    public function addXmlContent($content, $charset = 'UTF-8')
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   139
    {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   140
        $dom = new \DOMDocument('1.0', $charset);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   141
        $dom->validateOnParse = true;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   142
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   143
        // remove the default namespace to make XPath expressions simpler
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   144
        @$dom->loadXML(str_replace('xmlns', 'ns', $content));
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   145
        $this->addDocument($dom);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   146
    }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   147
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   148
    /**
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   149
     * Adds a \DOMDocument to the list of nodes.
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   150
     *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   151
     * @param \DOMDocument $dom A \DOMDocument instance
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   152
     *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   153
     * @api
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   154
     */
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   155
    public function addDocument(\DOMDocument $dom)
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   156
    {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   157
        if ($dom->documentElement) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   158
            $this->addNode($dom->documentElement);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   159
        }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   160
    }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   161
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   162
    /**
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   163
     * Adds a \DOMNodeList to the list of nodes.
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   164
     *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   165
     * @param \DOMNodeList $nodes A \DOMNodeList instance
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   166
     *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   167
     * @api
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   168
     */
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   169
    public function addNodeList(\DOMNodeList $nodes)
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   170
    {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   171
        foreach ($nodes as $node) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   172
            $this->addNode($node);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   173
        }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   174
    }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   175
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   176
    /**
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   177
     * Adds an array of \DOMNode instances to the list of nodes.
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   178
     *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   179
     * @param array $nodes An array of \DOMNode instances
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   180
     *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   181
     * @api
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   182
     */
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   183
    public function addNodes(array $nodes)
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   184
    {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   185
        foreach ($nodes as $node) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   186
            $this->add($node);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   187
        }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   188
    }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   189
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   190
    /**
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   191
     * Adds a \DOMNode instance to the list of nodes.
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   192
     *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   193
     * @param \DOMNode $node A \DOMNode instance
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   194
     *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   195
     * @api
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   196
     */
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   197
    public function addNode(\DOMNode $node)
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   198
    {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   199
        if ($node instanceof \DOMDocument) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   200
            $this->attach($node->documentElement);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   201
        } else {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   202
            $this->attach($node);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   203
        }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   204
    }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   205
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   206
    /**
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   207
     * Returns a node given its position in the node list.
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   208
     *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   209
     * @param integer $position The position
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   210
     *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   211
     * @return A new instance of the Crawler with the selected node, or an empty Crawler if it does not exist.
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   212
     *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   213
     * @api
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   214
     */
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   215
    public function eq($position)
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   216
    {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   217
        foreach ($this as $i => $node) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   218
            if ($i == $position) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   219
                return new static($node, $this->uri);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   220
            }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   221
        }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   222
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   223
        return new static(null, $this->uri);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   224
    }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   225
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   226
    /**
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   227
     * Calls an anonymous function on each node of the list.
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   228
     *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   229
     * The anonymous function receives the position and the node as arguments.
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   230
     *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   231
     * Example:
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   232
     *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   233
     *     $crawler->filter('h1')->each(function ($node, $i)
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   234
     *     {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   235
     *       return $node->nodeValue;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   236
     *     });
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   237
     *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   238
     * @param \Closure $closure An anonymous function
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   239
     *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   240
     * @return array An array of values returned by the anonymous function
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   241
     *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   242
     * @api
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   243
     */
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   244
    public function each(\Closure $closure)
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   245
    {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   246
        $data = array();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   247
        foreach ($this as $i => $node) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   248
            $data[] = $closure($node, $i);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   249
        }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   250
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   251
        return $data;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   252
    }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   253
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   254
    /**
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   255
     * Reduces the list of nodes by calling an anonymous function.
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   256
     *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   257
     * To remove a node from the list, the anonymous function must return false.
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   258
     *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   259
     * @param \Closure $closure An anonymous function
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   260
     *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   261
     * @return Crawler A Crawler instance with the selected nodes.
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   262
     *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   263
     * @api
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   264
     */
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   265
    public function reduce(\Closure $closure)
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   266
    {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   267
        $nodes = array();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   268
        foreach ($this as $i => $node) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   269
            if (false !== $closure($node, $i)) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   270
                $nodes[] = $node;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   271
            }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   272
        }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   273
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   274
        return new static($nodes, $this->uri);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   275
    }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   276
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   277
    /**
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   278
     * Returns the first node of the current selection
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   279
     *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   280
     * @return Crawler A Crawler instance with the first selected node
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   281
     *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   282
     * @api
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   283
     */
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   284
    public function first()
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   285
    {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   286
        return $this->eq(0);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   287
    }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   288
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   289
    /**
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   290
     * Returns the last node of the current selection
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   291
     *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   292
     * @return Crawler A Crawler instance with the last selected node
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   293
     *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   294
     * @api
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   295
     */
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   296
    public function last()
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   297
    {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   298
        return $this->eq(count($this) - 1);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   299
    }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   300
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   301
    /**
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   302
     * Returns the siblings nodes of the current selection
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   303
     *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   304
     * @return Crawler A Crawler instance with the sibling nodes
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   305
     *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   306
     * @throws \InvalidArgumentException When current node is empty
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   307
     *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   308
     * @api
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   309
     */
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   310
    public function siblings()
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   311
    {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   312
        if (!count($this)) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   313
            throw new \InvalidArgumentException('The current node list is empty.');
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   314
        }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   315
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   316
        return new static($this->sibling($this->getNode(0)->parentNode->firstChild), $this->uri);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   317
    }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   318
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   319
    /**
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   320
     * Returns the next siblings nodes of the current selection
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   321
     *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   322
     * @return Crawler A Crawler instance with the next sibling nodes
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   323
     *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   324
     * @throws \InvalidArgumentException When current node is empty
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   325
     *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   326
     * @api
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   327
     */
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   328
    public function nextAll()
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   329
    {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   330
        if (!count($this)) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   331
            throw new \InvalidArgumentException('The current node list is empty.');
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   332
        }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   333
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   334
        return new static($this->sibling($this->getNode(0)), $this->uri);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   335
    }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   336
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   337
    /**
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   338
     * Returns the previous sibling nodes of the current selection
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   339
     *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   340
     * @return Crawler A Crawler instance with the previous sibling nodes
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   341
     *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   342
     * @api
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   343
     */
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   344
    public function previousAll()
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   345
    {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   346
        if (!count($this)) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   347
            throw new \InvalidArgumentException('The current node list is empty.');
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   348
        }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   349
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   350
        return new static($this->sibling($this->getNode(0), 'previousSibling'), $this->uri);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   351
    }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   352
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   353
    /**
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   354
     * Returns the parents nodes of the current selection
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   355
     *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   356
     * @return Crawler A Crawler instance with the parents nodes of the current selection
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   357
     *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   358
     * @throws \InvalidArgumentException When current node is empty
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   359
     *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   360
     * @api
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   361
     */
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   362
    public function parents()
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   363
    {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   364
        if (!count($this)) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   365
            throw new \InvalidArgumentException('The current node list is empty.');
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   366
        }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   367
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   368
        $node = $this->getNode(0);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   369
        $nodes = array();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   370
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   371
        while ($node = $node->parentNode) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   372
            if (1 === $node->nodeType && '_root' !== $node->nodeName) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   373
                $nodes[] = $node;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   374
            }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   375
        }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   376
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   377
        return new static($nodes, $this->uri);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   378
    }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   379
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   380
    /**
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   381
     * Returns the children nodes of the current selection
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   382
     *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   383
     * @return Crawler A Crawler instance with the children nodes
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   384
     *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   385
     * @throws \InvalidArgumentException When current node is empty
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   386
     *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   387
     * @api
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   388
     */
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   389
    public function children()
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   390
    {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   391
        if (!count($this)) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   392
            throw new \InvalidArgumentException('The current node list is empty.');
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   393
        }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   394
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   395
        return new static($this->sibling($this->getNode(0)->firstChild), $this->uri);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   396
    }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   397
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   398
    /**
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   399
     * Returns the attribute value of the first node of the list.
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   400
     *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   401
     * @param string $attribute The attribute name
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   402
     *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   403
     * @return string The attribute value
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   404
     *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   405
     * @throws \InvalidArgumentException When current node is empty
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   406
     *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   407
     * @api
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   408
     */
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   409
    public function attr($attribute)
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   410
    {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   411
        if (!count($this)) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   412
            throw new \InvalidArgumentException('The current node list is empty.');
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   413
        }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   414
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   415
        return $this->getNode(0)->getAttribute($attribute);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   416
    }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   417
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   418
    /**
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   419
     * Returns the node value of the first node of the list.
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   420
     *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   421
     * @return string The node value
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   422
     *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   423
     * @throws \InvalidArgumentException When current node is empty
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   424
     *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   425
     * @api
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   426
     */
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   427
    public function text()
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   428
    {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   429
        if (!count($this)) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   430
            throw new \InvalidArgumentException('The current node list is empty.');
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   431
        }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   432
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   433
        return $this->getNode(0)->nodeValue;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   434
    }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   435
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   436
    /**
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   437
     * Extracts information from the list of nodes.
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   438
     *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   439
     * You can extract attributes or/and the node value (_text).
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   440
     *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   441
     * Example:
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   442
     *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   443
     * $crawler->filter('h1 a')->extract(array('_text', 'href'));
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   444
     *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   445
     * @param array $attributes An array of attributes
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   446
     *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   447
     * @return array An array of extracted values
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   448
     *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   449
     * @api
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   450
     */
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   451
    public function extract($attributes)
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   452
    {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   453
        $attributes = (array) $attributes;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   454
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   455
        $data = array();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   456
        foreach ($this as $node) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   457
            $elements = array();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   458
            foreach ($attributes as $attribute) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   459
                if ('_text' === $attribute) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   460
                    $elements[] = $node->nodeValue;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   461
                } else {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   462
                    $elements[] = $node->getAttribute($attribute);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   463
                }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   464
            }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   465
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   466
            $data[] = count($attributes) > 1 ? $elements : $elements[0];
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   467
        }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   468
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   469
        return $data;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   470
    }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   471
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   472
    /**
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   473
     * Filters the list of nodes with an XPath expression.
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   474
     *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   475
     * @param string $xpath An XPath expression
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   476
     *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   477
     * @return Crawler A new instance of Crawler with the filtered list of nodes
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   478
     *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   479
     * @api
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   480
     */
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   481
    public function filterXPath($xpath)
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   482
    {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   483
        $document = new \DOMDocument('1.0', 'UTF-8');
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   484
        $root = $document->appendChild($document->createElement('_root'));
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   485
        foreach ($this as $node) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   486
            $root->appendChild($document->importNode($node, true));
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   487
        }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   488
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   489
        $domxpath = new \DOMXPath($document);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   490
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   491
        return new static($domxpath->query($xpath), $this->uri);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   492
    }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   493
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   494
    /**
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   495
     * Filters the list of nodes with a CSS selector.
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   496
     *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   497
     * This method only works if you have installed the CssSelector Symfony Component.
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   498
     *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   499
     * @param string $selector A CSS selector
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   500
     *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   501
     * @return Crawler A new instance of Crawler with the filtered list of nodes
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   502
     *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   503
     * @throws \RuntimeException if the CssSelector Component is not available
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   504
     *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   505
     * @api
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   506
     */
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   507
    public function filter($selector)
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   508
    {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   509
        if (!class_exists('Symfony\\Component\\CssSelector\\CssSelector')) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   510
            // @codeCoverageIgnoreStart
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   511
            throw new \RuntimeException('Unable to filter with a CSS selector as the Symfony CssSelector is not installed (you can use filterXPath instead).');
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   512
            // @codeCoverageIgnoreEnd
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   513
        }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   514
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   515
        return $this->filterXPath(CssSelector::toXPath($selector));
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   516
    }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   517
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   518
    /**
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   519
     * Selects links by name or alt value for clickable images.
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   520
     *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   521
     * @param  string $value The link text
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   522
     *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   523
     * @return Crawler A new instance of Crawler with the filtered list of nodes
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   524
     *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   525
     * @api
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   526
     */
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   527
    public function selectLink($value)
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   528
    {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   529
        $xpath  = sprintf('//a[contains(concat(\' \', normalize-space(string(.)), \' \'), %s)] ', static::xpathLiteral(' '.$value.' ')).
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   530
                            sprintf('| //a/img[contains(concat(\' \', normalize-space(string(@alt)), \' \'), %s)]/ancestor::a', static::xpathLiteral(' '.$value.' '));
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   531
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   532
        return $this->filterXPath($xpath);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   533
    }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   534
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   535
    /**
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   536
     * Selects a button by name or alt value for images.
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   537
     *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   538
     * @param  string $value The button text
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   539
     *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   540
     * @return Crawler A new instance of Crawler with the filtered list of nodes
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   541
     *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   542
     * @api
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   543
     */
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   544
    public function selectButton($value)
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   545
    {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   546
        $xpath = sprintf('//input[((@type="submit" or @type="button") and contains(concat(\' \', normalize-space(string(@value)), \' \'), %s)) ', static::xpathLiteral(' '.$value.' ')).
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   547
                         sprintf('or (@type="image" and contains(concat(\' \', normalize-space(string(@alt)), \' \'), %s)) or @id="%s" or @name="%s"] ', static::xpathLiteral(' '.$value.' '), $value, $value).
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   548
                         sprintf('| //button[contains(concat(\' \', normalize-space(string(.)), \' \'), %s) or @id="%s" or @name="%s"]', static::xpathLiteral(' '.$value.' '), $value, $value);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   549
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   550
        return $this->filterXPath($xpath);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   551
    }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   552
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   553
    /**
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   554
     * Returns a Link object for the first node in the list.
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   555
     *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   556
     * @param  string $method The method for the link (get by default)
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   557
     *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   558
     * @return Link   A Link instance
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   559
     *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   560
     * @throws \InvalidArgumentException If the current node list is empty
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   561
     *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   562
     * @api
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   563
     */
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   564
    public function link($method = 'get')
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   565
    {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   566
        if (!count($this)) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   567
            throw new \InvalidArgumentException('The current node list is empty.');
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   568
        }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   569
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   570
        $node = $this->getNode(0);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   571
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   572
        return new Link($node, $this->uri, $method);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   573
    }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   574
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   575
    /**
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   576
     * Returns an array of Link objects for the nodes in the list.
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   577
     *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   578
     * @return array An array of Link instances
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   579
     *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   580
     * @api
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   581
     */
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   582
    public function links()
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   583
    {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   584
        $links = array();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   585
        foreach ($this as $node) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   586
            $links[] = new Link($node, $this->uri, 'get');
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   587
        }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   588
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   589
        return $links;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   590
    }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   591
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   592
    /**
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   593
     * Returns a Form object for the first node in the list.
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   594
     *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   595
     * @param  array  $values An array of values for the form fields
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   596
     * @param  string $method The method for the form
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   597
     *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   598
     * @return Form   A Form instance
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   599
     *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   600
     * @throws \InvalidArgumentException If the current node list is empty
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   601
     *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   602
     * @api
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   603
     */
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   604
    public function form(array $values = null, $method = null)
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   605
    {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   606
        if (!count($this)) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   607
            throw new \InvalidArgumentException('The current node list is empty.');
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   608
        }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   609
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   610
        $form = new Form($this->getNode(0), $this->uri, $method);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   611
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   612
        if (null !== $values) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   613
            $form->setValues($values);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   614
        }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   615
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   616
        return $form;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   617
    }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   618
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   619
    static public function xpathLiteral($s)
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   620
    {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   621
        if (false === strpos($s, "'")) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   622
            return sprintf("'%s'", $s);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   623
        }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   624
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   625
        if (false === strpos($s, '"')) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   626
            return sprintf('"%s"', $s);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   627
        }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   628
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   629
        $string = $s;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   630
        $parts = array();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   631
        while (true) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   632
            if (false !== $pos = strpos($string, "'")) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   633
                $parts[] = sprintf("'%s'", substr($string, 0, $pos));
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   634
                $parts[] = "\"'\"";
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   635
                $string = substr($string, $pos + 1);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   636
            } else {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   637
                $parts[] = "'$string'";
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   638
                break;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   639
            }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   640
        }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   641
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   642
        return sprintf("concat(%s)", implode($parts, ', '));
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   643
    }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   644
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   645
    private function getNode($position)
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   646
    {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   647
        foreach ($this as $i => $node) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   648
            if ($i == $position) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   649
                return $node;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   650
            }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   651
        // @codeCoverageIgnoreStart
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   652
        }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   653
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   654
        return null;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   655
        // @codeCoverageIgnoreEnd
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   656
    }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   657
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   658
    private function sibling($node, $siblingDir = 'nextSibling')
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   659
    {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   660
        $nodes = array();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   661
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   662
        do {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   663
            if ($node !== $this->getNode(0) && $node->nodeType === 1) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   664
                $nodes[] = $node;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   665
            }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   666
        } while ($node = $node->$siblingDir);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   667
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   668
        return $nodes;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   669
    }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   670
}