1<?php
2
3namespace Facebook\WebDriver;
4
5use Facebook\WebDriver\Exception\NoSuchElementException;
6use Facebook\WebDriver\Exception\TimeoutException;
7
8/**
9 * A utility class, designed to help the user to wait until a condition turns true.
10 *
11 * @see WebDriverExpectedCondition.
12 */
13class WebDriverWait
14{
15    /**
16     * @var WebDriver
17     */
18    protected $driver;
19    /**
20     * @var int
21     */
22    protected $timeout;
23    /**
24     * @var int
25     */
26    protected $interval;
27
28    public function __construct(WebDriver $driver, $timeout_in_second = null, $interval_in_millisecond = null)
29    {
30        $this->driver = $driver;
31        $this->timeout = isset($timeout_in_second) ? $timeout_in_second : 30;
32        $this->interval = $interval_in_millisecond ?: 250;
33    }
34
35    /**
36     * Calls the function provided with the driver as an argument until the return value is not falsey.
37     *
38     * @param callable|WebDriverExpectedCondition $func_or_ec
39     * @param string $message
40     *
41     * @throws \Exception
42     * @throws NoSuchElementException
43     * @throws TimeoutException
44     * @return mixed The return value of $func_or_ec
45     */
46    public function until($func_or_ec, $message = '')
47    {
48        $end = microtime(true) + $this->timeout;
49        $last_exception = null;
50
51        while ($end > microtime(true)) {
52            try {
53                if ($func_or_ec instanceof WebDriverExpectedCondition) {
54                    $ret_val = call_user_func($func_or_ec->getApply(), $this->driver);
55                } else {
56                    $ret_val = call_user_func($func_or_ec, $this->driver);
57                }
58                if ($ret_val) {
59                    return $ret_val;
60                }
61            } catch (NoSuchElementException $e) {
62                $last_exception = $e;
63            }
64            usleep($this->interval * 1000);
65        }
66
67        if ($last_exception) {
68            throw $last_exception;
69        }
70
71        throw new TimeoutException($message);
72    }
73}
74