Manager::start()   A
last analyzed

Complexity

Conditions 3
Paths 4

Size

Total Lines 18

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 18
rs 9.6666
cc 3
nc 4
nop 3
1
<?php
2
namespace Peridot\WebDriverManager;
3
4
use Peridot\WebDriverManager\Binary\BinaryInterface;
5
use Peridot\WebDriverManager\Binary\BinaryResolver;
6
use Peridot\WebDriverManager\Binary\BinaryResolverInterface;
7
use Peridot\WebDriverManager\Binary\ChromeDriver;
8
use Peridot\WebDriverManager\Binary\DriverInterface;
9
use Peridot\WebDriverManager\Binary\IEDriver;
10
use Peridot\WebDriverManager\Binary\SeleniumStandalone;
11
use Peridot\WebDriverManager\Event\EventEmitterInterface;
12
use Peridot\WebDriverManager\Event\EventEmitterTrait;
13
use Peridot\WebDriverManager\Process\SeleniumProcessInterface;
14
use Peridot\WebDriverManager\Process\SeleniumProcess;
15
use RuntimeException;
16
17
/**
18
 * The Manager provides an api for controlling Selenium Server. It can be used
19
 * to keep binaries and drivers up to date, as well as start Selenium Server.
20
 *
21
 * @package Peridot\WebDriverManager
22
 */
23
class Manager implements EventEmitterInterface
24
{
25
    use EventEmitterTrait;
26
27
    /**
28
     * @var array
29
     */
30
    protected $binaries;
31
32
    /**
33
     * @var BinaryResolverInterface
34
     */
35
    protected $resolver;
36
37
    /**
38
     * @var SeleniumProcessInterface
39
     */
40
    protected $process;
41
42
    /**
43
     * @var string
44
     */
45
    protected $installPath = '';
46
47
    /**
48
     * @param BinaryResolverInterface $resolver
49
     * @param SeleniumProcessInterface $process
50
     */
51
    public function __construct(BinaryResolverInterface $resolver = null, SeleniumProcessInterface $process = null) {
52
        $this->resolver = $resolver;
53
        $this->process = $process;
54
        $this->binaries = [];
55
56
        $resolver = $this->getBinaryResolver();
57
        $this->addBinary(new SeleniumStandalone($resolver));
58
        $this->addBinary(new ChromeDriver($resolver));
59
        $this->addBinary(new IEDriver($resolver));
60
        $this->setBinaryResolver($resolver);
61
    }
62
63
    /**
64
     * Add a binary to the collection of managed binaries.
65
     *
66
     * @param BinaryInterface $binary
67
     */
68
    public function addBinary(BinaryInterface $binary)
69
    {
70
        $this->binaries[$binary->getName()] = $binary;
71
    }
72
73
    /**
74
     * Remove a binary from the collection of managed binaries.
75
     *
76
     * @param string $binaryName
77
     */
78
    public function removeBinary($binaryName)
79
    {
80
        if (isset($this->binaries[$binaryName])) {
81
            unset($this->binaries[$binaryName]);
82
        }
83
    }
84
85
    /**
86
     * Return the BinaryResolver used to resolve binary files.
87
     *
88
     * @return BinaryResolver|BinaryResolverInterface
89
     */
90
    public function getBinaryResolver()
91
    {
92
        if ($this->resolver === null) {
93
            $this->resolver = new BinaryResolver();
94
        }
95
96
        return $this->resolver;
97
    }
98
99
    /**
100
     * Set the BinaryResolver used to resolve binary files.
101
     *
102
     * @param BinaryResolverInterface $resolver
103
     */
104
    public function setBinaryResolver(BinaryResolverInterface $resolver)
105
    {
106
        $this->resolver = $resolver;
107
        $this->inherit(['progress', 'request.start', 'complete'], $resolver);
108
    }
109
110
    /**
111
     * Return the SeleniumProcessInterface that will execute the
112
     * selenium server command.
113
     *
114
     * @return SeleniumProcess|SeleniumProcessInterface
115
     */
116
    public function getSeleniumProcess()
117
    {
118
        if ($this->process === null) {
119
            $this->process = new SeleniumProcess();
120
        }
121
122
        return $this->process;
123
    }
124
125
    /**
126
     * Return all managed binaries.
127
     *
128
     * @param callable $predicate
129
     * @return array
130
     */
131
    public function getBinaries(callable $predicate = null)
132
    {
133
        $binaries = $this->binaries;
134
        if ($predicate !== null) {
135
            return array_filter($binaries, $predicate);
136
        }
137
        return $binaries;
138
    }
139
140
    /**
141
     * Return all binaries that are considered drivers.
142
     *
143
     * @return array
144
     */
145
    public function getDrivers()
146
    {
147
        return $this->getBinaries(function ($binary) {
148
            return $binary instanceof DriverInterface;
149
        });
150
    }
151
152
    /**
153
     * Pending binaries are binaries that are supported but have not been installed.
154
     *
155
     * @return array
156
     */
157
    public function getPendingBinaries()
158
    {
159
        return $this->getBinaries(function (BinaryInterface $binary) {
160
            $exists = $binary->exists($this->getInstallPath());
161
            $supported = $binary->isSupported();
162
            return $supported && !$exists;
163
        });
164
    }
165
166
    /**
167
     * Fetch and save binaries.
168
     *
169
     * @return bool
170
     */
171
    public function update($binaryName = '')
172
    {
173
        if ($binaryName) {
174
            $this->updateSingle($binaryName);
175
            return;
176
        }
177
178
        foreach ($this->binaries as $binary) {
179
            $binary->fetchAndSave($this->getInstallPath());
180
        }
181
    }
182
183
    /**
184
     * Update a single binary.
185
     *
186
     * @param $binaryName
187
     * @return void
188
     */
189
    public function updateSingle($binaryName)
190
    {
191
        if (! array_key_exists($binaryName, $this->binaries)) {
192
            throw new RuntimeException("Binary named $binaryName does not exist");
193
        }
194
195
        $binary = $this->binaries[$binaryName];
196
        $binary->fetchAndSave($this->getInstallPath());
197
    }
198
199
    /**
200
     * Start the Selenium server.
201
     *
202
     * @param bool $background
203
     * @param int $port
204
     * @param array $args
205
     * @return SeleniumProcessInterface
206
     */
207
    public function start($background = false, $port = 4444, array $args = [])
208
    {
209
        $selenium = $this->binaries['selenium'];
210
        $this->assertStartConditions($selenium);
211
212
        $process = $this->getSeleniumProcess();
213
        $this->registerBinaries($process, $selenium);
214
215
        if ($port != 4444) {
216
            $process->addArg('-port', $port);
217
        }
218
219
        if (!empty($args)) {
220
            $process->addArgs($args);
221
        }
222
223
        return $process->start($background);
224
    }
225
226
    /**
227
     * Start Selenium in the foreground.
228
     *
229
     * @param int $port
230
     * @return SeleniumProcessInterface
231
     */
232
    public function startInForeground($port = 4444, array $args = [])
233
    {
234
        return $this->start(false, $port, $args);
235
    }
236
237
    /**
238
     * Start Selenium in a background process.
239
     *
240
     * @param int $port
241
     * @return SeleniumProcessInterface
242
     */
243
    public function startInBackground($port = 4444, array $args = [])
244
    {
245
        return $this->start(true, $port, $args);
246
    }
247
248
    /**
249
     * Remove all binaries from the install path.
250
     *
251
     * @return void
252
     */
253
    public function clean()
254
    {
255
        $files = glob($this->getInstallPath() . '/*');
256
        foreach ($files as $file) {
257
            unlink($file);
258
        }
259
    }
260
261
    /**
262
     * Get the installation path of binaries.
263
     *
264
     * @return string
265
     */
266
    public function getInstallPath()
267
    {
268
        if ($this->installPath === '') {
269
            $this->installPath = realpath(__DIR__ . '/../binaries');
270
        }
271
272
        return $this->installPath;
273
    }
274
275
    /**
276
     * Set the installation path for binaries.
277
     *
278
     * @param string $path
279
     */
280
    public function setInstallPath($path)
281
    {
282
        $this->installPath = $path;
283
    }
284
285
    /**
286
     * Assert that the selenium server can start.
287
     *
288
     * @param SeleniumStandalone $selenium
289
     * @throws \RuntimeException
290
     * @return void
291
     */
292
    protected function assertStartConditions(SeleniumStandalone $selenium)
293
    {
294
        if (!$selenium->exists($this->getInstallPath())) {
295
            throw new RuntimeException("Selenium Standalone binary not installed");
296
        }
297
298
        if (!$this->getSeleniumProcess()->isAvailable()) {
299
            throw new RuntimeException('java is not available');
300
        }
301
    }
302
303
    /**
304
     * Register selenium binary and drivers with the process.
305
     *
306
     * @param SeleniumProcessInterface $process
307
     * @param SeleniumStandalone $selenium
308
     * @return void
309
     */
310
    protected function registerBinaries(SeleniumProcessInterface $process, SeleniumStandalone $selenium)
311
    {
312
        $drivers = $this->getDrivers();
313
        foreach ($drivers as $driver) {
314
            $process->addBinary($driver, $this->getInstallPath());
315
        }
316
        $process->addBinary($selenium, $this->getInstallPath());
317
    }
318
}
319