/** * Returns DOMElement from crawler instance. * * @param Crawler $crawler * * @return \DOMElement * * @throws DriverException when the node does not exist */ private function getCrawlerNode(Crawler $crawler) { $node = null; if ($crawler instanceof \Iterator) { // for symfony 2.3 compatibility as getNode is not public before symfony 2.4 $crawler->rewind(); $node = $crawler->current(); } else { $node = $crawler->getNode(0); } if (null !== $node) { return $node; } throw new DriverException('The element does not exist'); }
/** * @param \Symfony\Component\DomCrawler\Crawler $node * * @return \Symfony\Component\DomCrawler\Form|\Symfony\Component\DomCrawler\Field\ChoiceFormField[]|\Symfony\Component\DomCrawler\Field\FileFormField[] */ protected function getFormFor($node) { $form = $node->parents()->filter('form')->first(); if (!$form) { $this->fail('The selected node does not have a form ancestor.'); } $action = $this->getFormUrl($form); if (isset($this->forms[$action])) { return $this->forms[$action]; } /** @var \DOMElement $autoSubmit */ $autoSubmit = new \DOMElement('input'); $autoSubmit = $form->current()->appendChild($autoSubmit); $autoSubmit->setAttribute('type', 'submit'); // for forms with no submits $autoSubmit->setAttribute('name', 'codeception_added_auto_submit'); // Symfony2.1 DOM component requires name for each field. $formSubmits = $form->filter('*[type=submit]'); $values = null; // If there are more than one submit (+1 auto_added) in one form we should add value of actually clicked one if ($formSubmits->count() > 2) { $nodeItem = $node->getNode(0); foreach ($formSubmits as $formSubmit) { if ($formSubmit === $nodeItem) { $values = array($nodeItem->getAttribute('name') => $nodeItem->getAttribute('value')); break; } } } $form = $formSubmits->form($values); $this->forms[$action] = $form; return $this->forms[$action]; }
/** * Returns a crawler Form object for the form pointed to by the * passed Crawler. * * The returned form is an independent Crawler created to take care * of the following issues currently experienced by Crawler's form * object: * - input fields disabled at a higher level (e.g. by a surrounding * fieldset) still return values * - Codeception expects an empty value to match an unselected * select box. * * The function clones the crawler's node and creates a new crawler * because it destroys or adds to the DOM for the form to achieve * the desired functionality. Other functions simply querying the * DOM wouldn't expect them. * * @param Crawler $form the form * @param string $action the form's absolute URL action * @return Form */ private function getFormFromCrawler(Crawler $form, $action) { $fakeDom = new \DOMDocument(); $fakeDom->appendChild($fakeDom->importNode($form->getNode(0), true)); $node = $fakeDom->documentElement; $cloned = new Crawler($node, $action); $shouldDisable = $cloned->filter('input:disabled:not([disabled]),select option:disabled,select optgroup:disabled option:not([disabled])'); foreach ($shouldDisable as $field) { $field->parentNode->removeChild($field); } $selectNonMulti = $cloned->filterXPath('//select[not(@multiple) and not(option[@value=""])]'); $opt = new \DOMElement('option'); foreach ($selectNonMulti as $field) { $node = $field->insertBefore($opt, $field->firstChild); $node->setAttribute('value', ''); } return $cloned->form(); }
/** * @param Crawler $block * @return array */ public function getSimilarSiblingsInfo(Crawler $block) { $all_siblings = $block->parents()->first()->children(); $siblings = [$block]; $sample_node = $block->getNode(0); $sample_tag = $block->nodeName(); $sample_classes = explode(' ', $block->extract(['class'])[0]); foreach ($all_siblings as $sibling) { if ($sample_node->isSameNode($sibling)) { continue; } $to_add = false; if ($sibling->nodeName == $sample_tag) { if ($sample_classes === FALSE) { $to_add = true; } else { $sibling_classes = explode(' ', $sibling->getAttribute('class')); $matched_classes = array_intersect($sample_classes, $sibling_classes); if (!empty($matched_classes)) { if ($matched_classes != $sample_classes) { $sample_classes = $matched_classes; } $to_add = true; } } } if ($to_add) { $siblings[] = new Crawler($sibling); } } return [$siblings, ['tag' => $sample_tag, 'classes' => $sample_classes]]; }
/** * return the parent DOMDocument * * @return \DOMDocument */ public function document() { return $this->DOM->getNode(0)->parentNode; }
/** * @param Crawler $node * @param string $currentUri */ public function __construct(Crawler $node, $currentUri) { parent::__construct($node->getNode(0), $currentUri); $this->type = strtolower(trim($node->attr('type'))); }
/** * @param int $position * * overridden from Crawler because it is not public in Symfony 2.3 * TODO: throw away as soon as we don't need to support SF 2.3 any more * * @return \DOMElement|null */ public function getNode($position) { return parent::getNode($position); }
protected function cleanDescription(Crawler $descriptionNode) { $descriptionNode->filter('a')->each(function ($node) { $domElement = $node->getNode(0); $href = $domElement->getAttribute('href'); while (strpos($href, 'https://www.google.com/url?q=') === 0) { $parts = parse_url($href); parse_str($parts['query'], $query); $href = $query['q']; } $domElement->setAttribute('href', $href); }); $html = $descriptionNode->html(); $text = trim($this->convertHtmlToText($descriptionNode->getNode(0))); return array('html' => $html, 'text' => $text); }