Chris@0: Chris@0: * Chris@0: * For the full copyright and license information, please view the LICENSE Chris@0: * file that was distributed with this source code. Chris@0: */ Chris@0: Chris@0: namespace Behat\Mink\Element; Chris@0: Chris@0: use Behat\Mink\Driver\DriverInterface; Chris@0: use Behat\Mink\Exception\ElementNotFoundException; Chris@0: use Behat\Mink\Selector\SelectorsHandler; Chris@0: use Behat\Mink\Selector\Xpath\Manipulator; Chris@0: use Behat\Mink\Session; Chris@0: Chris@0: /** Chris@0: * Base element. Chris@0: * Chris@0: * @author Konstantin Kudryashov Chris@0: */ Chris@0: abstract class Element implements ElementInterface Chris@0: { Chris@0: /** Chris@0: * @var Session Chris@0: */ Chris@0: private $session; Chris@0: Chris@0: /** Chris@0: * Driver. Chris@0: * Chris@0: * @var DriverInterface Chris@0: */ Chris@0: private $driver; Chris@0: Chris@0: /** Chris@0: * @var SelectorsHandler Chris@0: */ Chris@0: private $selectorsHandler; Chris@0: Chris@0: /** Chris@0: * @var Manipulator Chris@0: */ Chris@0: private $xpathManipulator; Chris@0: Chris@0: /** Chris@0: * Initialize element. Chris@0: * Chris@0: * @param Session $session Chris@0: */ Chris@0: public function __construct(Session $session) Chris@0: { Chris@0: $this->xpathManipulator = new Manipulator(); Chris@0: $this->session = $session; Chris@0: Chris@0: $this->driver = $session->getDriver(); Chris@0: $this->selectorsHandler = $session->getSelectorsHandler(); Chris@0: } Chris@0: Chris@0: /** Chris@0: * Returns element session. Chris@0: * Chris@0: * @return Session Chris@0: * Chris@0: * @deprecated Accessing the session from the element is deprecated as of 1.6 and will be impossible in 2.0. Chris@0: */ Chris@0: public function getSession() Chris@0: { Chris@0: @trigger_error(sprintf('The method %s is deprecated as of 1.6 and will be removed in 2.0', __METHOD__), E_USER_DEPRECATED); Chris@0: Chris@0: return $this->session; Chris@0: } Chris@0: Chris@0: /** Chris@0: * Returns element's driver. Chris@0: * Chris@0: * @return DriverInterface Chris@0: */ Chris@0: protected function getDriver() Chris@0: { Chris@0: return $this->driver; Chris@0: } Chris@0: Chris@0: /** Chris@0: * Returns selectors handler. Chris@0: * Chris@0: * @return SelectorsHandler Chris@0: * Chris@0: * @deprecated Accessing the selectors handler in the element is deprecated as of 1.7 and will be impossible in 2.0. Chris@0: */ Chris@0: protected function getSelectorsHandler() Chris@0: { Chris@0: @trigger_error(sprintf('The method %s is deprecated as of 1.7 and will be removed in 2.0', __METHOD__), E_USER_DEPRECATED); Chris@0: Chris@0: return $this->selectorsHandler; Chris@0: } Chris@0: Chris@0: /** Chris@0: * {@inheritdoc} Chris@0: */ Chris@0: public function has($selector, $locator) Chris@0: { Chris@0: return null !== $this->find($selector, $locator); Chris@0: } Chris@0: Chris@0: /** Chris@0: * {@inheritdoc} Chris@0: */ Chris@0: public function isValid() Chris@0: { Chris@0: return 1 === count($this->getDriver()->find($this->getXpath())); Chris@0: } Chris@0: Chris@0: /** Chris@0: * {@inheritdoc} Chris@0: */ Chris@0: public function waitFor($timeout, $callback) Chris@0: { Chris@0: if (!is_callable($callback)) { Chris@0: throw new \InvalidArgumentException('Given callback is not a valid callable'); Chris@0: } Chris@0: Chris@0: $start = microtime(true); Chris@0: $end = $start + $timeout; Chris@0: Chris@0: do { Chris@0: $result = call_user_func($callback, $this); Chris@0: Chris@0: if ($result) { Chris@0: break; Chris@0: } Chris@0: Chris@0: usleep(100000); Chris@0: } while (microtime(true) < $end); Chris@0: Chris@0: return $result; Chris@0: } Chris@0: Chris@0: /** Chris@0: * {@inheritdoc} Chris@0: */ Chris@0: public function find($selector, $locator) Chris@0: { Chris@0: $items = $this->findAll($selector, $locator); Chris@0: Chris@0: return count($items) ? current($items) : null; Chris@0: } Chris@0: Chris@0: /** Chris@0: * {@inheritdoc} Chris@0: */ Chris@0: public function findAll($selector, $locator) Chris@0: { Chris@0: if ('named' === $selector) { Chris@0: $items = $this->findAll('named_exact', $locator); Chris@0: if (empty($items)) { Chris@0: $items = $this->findAll('named_partial', $locator); Chris@0: } Chris@0: Chris@0: return $items; Chris@0: } Chris@0: Chris@0: $xpath = $this->selectorsHandler->selectorToXpath($selector, $locator); Chris@0: $xpath = $this->xpathManipulator->prepend($xpath, $this->getXpath()); Chris@0: Chris@0: return $this->getDriver()->find($xpath); Chris@0: } Chris@0: Chris@0: /** Chris@0: * {@inheritdoc} Chris@0: */ Chris@0: public function getText() Chris@0: { Chris@0: return $this->getDriver()->getText($this->getXpath()); Chris@0: } Chris@0: Chris@0: /** Chris@0: * {@inheritdoc} Chris@0: */ Chris@0: public function getHtml() Chris@0: { Chris@0: return $this->getDriver()->getHtml($this->getXpath()); Chris@0: } Chris@0: Chris@0: /** Chris@0: * Returns element outer html. Chris@0: * Chris@0: * @return string Chris@0: */ Chris@0: public function getOuterHtml() Chris@0: { Chris@0: return $this->getDriver()->getOuterHtml($this->getXpath()); Chris@0: } Chris@0: Chris@0: /** Chris@0: * Builds an ElementNotFoundException. Chris@0: * Chris@0: * @param string $type Chris@0: * @param string|null $selector Chris@0: * @param string|null $locator Chris@0: * Chris@0: * @return ElementNotFoundException Chris@0: * Chris@0: * @deprecated as of 1.7, to be removed in 2.0 Chris@0: */ Chris@0: protected function elementNotFound($type, $selector = null, $locator = null) Chris@0: { Chris@0: @trigger_error(sprintf('The method %s is deprecated as of 1.7 and will be removed in 2.0', __METHOD__), E_USER_DEPRECATED); Chris@0: Chris@0: return new ElementNotFoundException($this->driver, $type, $selector, $locator); Chris@0: } Chris@0: }