Client   D
last analyzed

Complexity

Total Complexity 58

Size/Duplication

Total Lines 766
Duplicated Lines 0 %

Importance

Changes 10
Bugs 0 Features 1
Metric Value
eloc 131
c 10
b 0
f 1
dl 0
loc 766
rs 4.5599
wmc 58

45 Methods

Rating   Name   Duplication   Size   Complexity  
A set() 0 6 1
A addUrl() 0 3 1
A seedRatioLimit() 0 9 2
A updateBlocklist() 0 3 1
A authenticate() 0 8 1
A updateIncompleteDir() 0 8 1
A setSettings() 0 5 1
A reannounce() 0 5 1
A addFile() 0 3 1
A start() 0 5 1
A portTest() 0 3 1
A queueMoveTop() 0 5 1
A updateDownloadDir() 0 7 1
A create() 0 7 1
A startNow() 0 5 1
A __construct() 0 20 2
A getAll() 0 3 1
A add() 0 27 6
A instance() 0 3 1
A sessionStats() 0 3 1
A createWithHttpClient() 0 8 1
A move() 0 5 1
A queueMoveBottom() 0 5 1
A api() 0 25 3
A queueMoveDown() 0 5 1
A stop() 0 5 1
A get() 0 12 2
A isTLSEnabled() 0 3 1
A verify() 0 5 1
A getSettings() 0 3 1
A close() 0 5 1
A rename() 0 3 1
A remove() 0 6 1
A setSessionId() 0 6 1
A queueMoveUp() 0 5 1
A stopAll() 0 3 1
A startAll() 0 3 1
A freeSpace() 0 7 2
A enableTLS() 0 5 1
A getResponseHistory() 0 3 1
A getHttpClient() 0 3 1
A defaultUserAgent() 0 3 1
A findAndSetSessionId() 0 11 2
A transmissionUrl() 0 3 2
A __call() 0 6 1

How to fix   Complexity   

Complex Class

Complex classes like Client often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use Client, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
namespace Transmission;
4
5
use Http\Client\Common\Plugin\AuthenticationPlugin;
6
use Http\Client\Common\Plugin\HeaderDefaultsPlugin;
7
use Http\Client\Common\Plugin\HistoryPlugin;
8
use Http\Message\Authentication\BasicAuth;
9
use Illuminate\Support\Collection;
10
use Psr\Http\Client as Psr18;
11
use Psr\Http\Client\ClientInterface;
12
use Psr\Http\Message\ResponseInterface;
13
use Transmission\Exception\InvalidArgumentException;
14
use Transmission\Exception\NetworkException;
15
use Transmission\Exception\TransmissionException;
16
use Transmission\HttpClient\Builder;
17
use Transmission\HttpClient\Message\ParamBuilder;
18
use Transmission\HttpClient\Message\ResponseMediator;
19
use Transmission\HttpClient\Plugin\AuthSession;
20
use Transmission\HttpClient\Plugin\ExceptionThrower;
21
use Transmission\HttpClient\Plugin\History;
22
use Transmission\Models\Torrent;
23
24
/**
25
 * Transmission-RPC API SDK Client.
26
 */
27
class Client
28
{
29
    /** @var string SDK Version */
30
    public const VERSION = '2.0.0';
31
32
    /** @var string Transmission-RPC Host */
33
    public $host;
34
35
    /** @var string Transmission-RPC Port */
36
    public $port;
37
38
    /** @var string Transmission-RPC Path */
39
    public $path = '/transmission/rpc';
40
41
    /** @var History */
42
    protected $responseHistory;
43
44
    /** @var Builder */
45
    protected $httpClientBuilder;
46
47
    /** @var bool Enable TLS (HTTPS) */
48
    protected $enableTLS = false;
49
50
    /**
51
     * Instantiate a new Transmission Client.
52
     *
53
     * @param string|null  $host
54
     * @param int|null     $port
55
     * @param string|null  $username
56
     * @param string|null  $password
57
     * @param Builder|null $httpClientBuilder
58
     */
59
    public function __construct(
60
        string $host = null,
61
        int $port = null,
62
        string $username = null,
63
        string $password = null,
64
        Builder $httpClientBuilder = null
65
    ) {
66
        $this->host = $host ?? '127.0.0.1';
67
        $this->port = $port ?? 9091;
68
69
        $this->responseHistory = new History();
70
        $this->httpClientBuilder = $httpClientBuilder ?? new Builder();
71
        $this->httpClientBuilder->addPlugin(new ExceptionThrower());
72
        $this->httpClientBuilder->addPlugin(new HistoryPlugin($this->responseHistory));
73
        $this->httpClientBuilder->addPlugin(new HeaderDefaultsPlugin([
74
            'User-Agent' => $this->defaultUserAgent(),
75
        ]));
76
77
        if (filled($username)) {
78
            $this->authenticate($username, $password);
0 ignored issues
show
Bug introduced by
It seems like $username can also be of type null; however, parameter $username of Transmission\Client::authenticate() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

78
            $this->authenticate(/** @scrutinizer ignore-type */ $username, $password);
Loading history...
Bug introduced by
It seems like $password can also be of type null; however, parameter $password of Transmission\Client::authenticate() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

78
            $this->authenticate($username, /** @scrutinizer ignore-type */ $password);
Loading history...
79
        }
80
    }
81
82
    /**
83
     * Create a Transmission\Client.
84
     *
85
     * @param null|string $host
86
     * @param null|int    $port
87
     * @param null|string $username
88
     * @param null|string $password
89
     *
90
     * @return Client
91
     */
92
    public static function create(
93
        string $host = null,
94
        int $port = null,
95
        string $username = null,
96
        string $password = null
97
    ): self {
98
        return new static($host, $port, $username, $password);
99
    }
100
101
    /**
102
     * Create a Transmission\Client using an HttpClient.
103
     *
104
     * @param ClientInterface $httpClient
105
     * @param null|string     $host
106
     * @param null|int        $port
107
     * @param null|string     $username
108
     * @param null|string     $password
109
     *
110
     * @return Client
111
     */
112
    public static function createWithHttpClient(
113
        ClientInterface $httpClient,
114
        string $host = null,
115
        int $port = null,
116
        string $username = null,
117
        string $password = null
118
    ): self {
119
        return new static($host, $port, $username, $password, new Builder($httpClient));
120
    }
121
122
    /**
123
     * Determine if TLS is enabled.
124
     *
125
     * @return bool
126
     */
127
    public function isTLSEnabled(): bool
128
    {
129
        return $this->enableTLS;
130
    }
131
132
    /**
133
     * Enable TLS.
134
     *
135
     * @return $this
136
     */
137
    public function enableTLS(): self
138
    {
139
        $this->enableTLS = true;
140
141
        return $this;
142
    }
143
144
    /**
145
     * Get Client Instance.
146
     *
147
     * @return Client
148
     */
149
    public function instance(): self
150
    {
151
        return $this;
152
    }
153
154
    /**
155
     * Authenticate the user for all next requests.
156
     *
157
     * @param string      $username
158
     * @param null|string $password
159
     *
160
     * @return Client
161
     */
162
    public function authenticate(string $username, string $password = ''): self
163
    {
164
        $authentication = new BasicAuth($username, $password);
165
166
        $this->httpClientBuilder->removePlugin(AuthenticationPlugin::class);
167
        $this->httpClientBuilder->addPlugin(new AuthenticationPlugin($authentication));
168
169
        return $this;
170
    }
171
172
    /**
173
     * Set Session ID.
174
     *
175
     * @param string $sessionId
176
     *
177
     * @return Client
178
     */
179
    public function setSessionId(string $sessionId): self
180
    {
181
        $this->httpClientBuilder->removePlugin(AuthSession::class);
182
        $this->httpClientBuilder->addPlugin(new AuthSession($sessionId));
183
184
        return $this;
185
    }
186
187
    /**
188
     * Start All Torrents.
189
     *
190
     * @return bool
191
     *
192
     * @see start()
193
     */
194
    public function startAll(): bool
195
    {
196
        return $this->start();
197
    }
198
199
    /**
200
     * Start one or more torrents.
201
     *
202
     * @see https://git.io/transmission-rpc-specs Transfer Action Requests.
203
     *
204
     * @param mixed $ids One or more torrent ids, sha1 hash strings, or both OR "recently-active", for
205
     *                   recently-active torrents. All torrents are used if no value is given.
206
     *
207
     * @return bool
208
     */
209
    public function start($ids = null): bool
210
    {
211
        $this->api('torrent-start', compact('ids'));
212
213
        return true;
214
    }
215
216
    /**
217
     * Start Now one or more torrents.
218
     *
219
     * @see https://git.io/transmission-rpc-specs Torrent Action Requests.
220
     *
221
     * @param mixed $ids One or more torrent ids, as described in 3.1 of specs.
222
     *
223
     * @return bool
224
     */
225
    public function startNow($ids = null): bool
226
    {
227
        $this->api('torrent-start-now', compact('ids'));
228
229
        return true;
230
    }
231
232
    /**
233
     * Stop All Torrents.
234
     *
235
     * @return bool
236
     *
237
     * @see stop()
238
     */
239
    public function stopAll(): bool
240
    {
241
        return $this->stop();
242
    }
243
244
    /**
245
     * Stop one or more torrents.
246
     *
247
     * @see https://git.io/transmission-rpc-specs Torrent Action Requests.
248
     *
249
     * @param mixed $ids One or more torrent ids, as described in 3.1 of specs.
250
     *
251
     * @return bool
252
     */
253
    public function stop($ids = null): bool
254
    {
255
        $this->api('torrent-stop', compact('ids'));
256
257
        return true;
258
    }
259
260
    /**
261
     * Verify one or more torrents.
262
     *
263
     * @see https://git.io/transmission-rpc-specs Torrent Action Requests.
264
     *
265
     * @param mixed $ids One or more torrent ids, as described in 3.1 of specs.
266
     *
267
     * @return bool
268
     */
269
    public function verify($ids = null): bool
270
    {
271
        $this->api('torrent-verify', compact('ids'));
272
273
        return true;
274
    }
275
276
    /**
277
     * Reannounce one or more torrents.
278
     *
279
     * @see https://git.io/transmission-rpc-specs Torrent Action Requests.
280
     *
281
     * @param mixed $ids One or more torrent ids, as described in 3.1 of specs.
282
     *
283
     * @return bool
284
     */
285
    public function reannounce($ids = null): bool
286
    {
287
        $this->api('torrent-reannounce', compact('ids'));
288
289
        return true;
290
    }
291
292
    /**
293
     * Set properties of one or more torrents.
294
     *
295
     * @see https://git.io/transmission-rpc-specs "torrent-set" for available arguments.
296
     *
297
     * @param mixed $ids       One or more torrent ids, as described in 3.1 of specs.
298
     * @param array $arguments An associative array of arguments to set.
299
     *
300
     * @return bool
301
     */
302
    public function set($ids, array $arguments): bool
303
    {
304
        $arguments['ids'] = $ids;
305
        $this->api('torrent-set', $arguments);
306
307
        return true;
308
    }
309
310
    /**
311
     * Get All Torrents.
312
     *
313
     * @param array|null $fields
314
     *
315
     * @return Collection
316
     */
317
    public function getAll(array $fields = null): Collection
318
    {
319
        return $this->get(null, $fields);
320
    }
321
322
    /**
323
     * Get information on torrents, if the ids parameter is
324
     * null all torrents will be returned.
325
     *
326
     * @see https://git.io/transmission-rpc-specs "torrent-get" for available fields.
327
     *
328
     * @param mixed $ids    One or more torrent ids, as described in 3.1 of specs.
329
     * @param array $fields An array of return fields, no value will fallback to default fields.
330
     *
331
     * @return Collection
332
     */
333
    public function get($ids = null, array $fields = null): Collection
334
    {
335
        $fields = $fields ?? Torrent::$fields['default'];
336
        $data = $this->api('torrent-get', compact('ids', 'fields'));
337
338
        $torrentsInfo = data_get($data, 'arguments.torrents', 0);
339
340
        if (blank($torrentsInfo)) {
341
            return collect();
342
        }
343
344
        return collect($torrentsInfo)->mapInto(Torrent::class);
345
    }
346
347
    /**
348
     * Add a Torrent File to the download queue.
349
     *
350
     * @param string      $file         Torrent File Content.
351
     * @param string|null $savepath     Path to download the torrent to.
352
     * @param array       $optionalArgs Other optional arguments.
353
     *
354
     * @return Collection
355
     */
356
    public function addFile($file, string $savepath = null, array $optionalArgs = []): Collection
357
    {
358
        return $this->add($file, true, $savepath, $optionalArgs);
359
    }
360
361
    /**
362
     * Add a Torrent by URL to the download queue.
363
     *
364
     * @param string      $url          Magnet URI/URL of the torrent file.
365
     * @param string|null $savepath     Path to download the torrent to.
366
     * @param array       $optionalArgs Other optional arguments.
367
     *
368
     * @return Collection
369
     */
370
    public function addUrl($url, string $savepath = null, array $optionalArgs = []): Collection
371
    {
372
        return $this->add($url, false, $savepath, $optionalArgs);
373
    }
374
375
    /**
376
     * Add a torrent to the download queue.
377
     *
378
     * @see https://git.io/transmission-rpc-specs "torrent-add" for available arguments.
379
     *
380
     * @param string $torrent      Magnet URI/URL of the torrent file OR .torrent content.
381
     * @param bool   $metainfo     Is given torrent a metainfo? (default: false).
382
     * @param string $savepath     Path to download the torrent to.
383
     * @param array  $optionalArgs Other optional arguments.
384
     *
385
     * @return Collection
386
     */
387
    public function add(
388
        string $torrent,
389
        bool $metainfo = false,
390
        string $savepath = null,
391
        array $optionalArgs = []
392
    ): Collection {
393
        $arguments = [];
394
        $arguments['paused'] = false; // To start immediately
395
        $arguments[$metainfo ? 'metainfo' : 'filename'] = $metainfo ? base64_encode($torrent) : $torrent;
396
397
        if ($savepath !== null) {
398
            $arguments['download-dir'] = $savepath;
399
        }
400
401
        $data = $this->api('torrent-add', array_merge($arguments, $optionalArgs));
402
403
        if (array_key_exists('torrent-duplicate', $data['arguments'])) {
404
            $data['arguments']['torrent-duplicate']['duplicate'] = true;
405
406
            return collect($data['arguments']['torrent-duplicate']);
407
        }
408
409
        if (!array_key_exists('torrent-added', $data['arguments'])) {
410
            throw new InvalidArgumentException($data['result']);
411
        }
412
413
        return collect($data['arguments']['torrent-added']);
414
    }
415
416
    /**
417
     * Remove one or more torrents.
418
     *
419
     * @see https://git.io/transmission-rpc-specs "torrent-remove" for available arguments.
420
     *
421
     * @param mixed $ids             One or more torrent ids, as described in 3.1 of specs.
422
     * @param bool  $deleteLocalData Also remove local data? (default: false).
423
     *
424
     * @return bool
425
     */
426
    public function remove($ids, bool $deleteLocalData = false): bool
427
    {
428
        $arguments = ['ids' => $ids, 'delete-local-data' => $deleteLocalData];
429
        $this->api('torrent-remove', $arguments);
430
431
        return true;
432
    }
433
434
    /**
435
     * Move one or more torrents to new location.
436
     *
437
     * @see https://git.io/transmission-rpc-specs "torrent-set-location" for available arguments.
438
     *
439
     * @param mixed  $ids      One or more torrent ids, as described in 3.1 of specs.
440
     * @param string $location The new torrent location.
441
     * @param bool   $move     Move from previous location or search "location" for files (default: true).
442
     *
443
     * @return bool
444
     */
445
    public function move($ids, string $location, bool $move = true): bool
446
    {
447
        $this->api('torrent-set-location', compact('ids', 'location', 'move'));
448
449
        return true;
450
    }
451
452
    /**
453
     * Rename a Torrent's Path.
454
     *
455
     * @see https://git.io/transmission-rpc-specs "torrent-rename-path" for available arguments.
456
     *
457
     * @param mixed  $ids  One torrent id, as described in 3.1 of specs.
458
     * @param string $path The path to the file or folder that will be renamed.
459
     * @param string $name The file or folder's new name.
460
     *
461
     * @return array
462
     */
463
    public function rename($ids, string $path, string $name): array
464
    {
465
        return $this->api('torrent-rename-path', compact('ids', 'path', 'name'));
466
    }
467
468
    /**
469
     * Set the transmission settings.
470
     *
471
     * @see https://git.io/transmission-rpc-specs "session-set" for available arguments.
472
     *
473
     * @param array $arguments one or more of spec's arguments, except: "blocklist-size",
474
     *                         "config-dir", "rpc-version", "rpc-version-minimum",
475
     *                         "version", and "session-id"
476
     *
477
     * @return bool
478
     */
479
    public function setSettings(array $arguments): bool
480
    {
481
        $this->api('session-set', $arguments);
482
483
        return true;
484
    }
485
486
    /**
487
     * Get the transmission settings.
488
     *
489
     * @see https://git.io/transmission-rpc-specs "session-get" for available fields.
490
     *
491
     * @param array|null $fields
492
     *
493
     * @return array
494
     */
495
    public function getSettings(array $fields = null): array
496
    {
497
        return $this->api('session-get', compact('fields'));
498
    }
499
500
    /**
501
     * Get Session Stats.
502
     *
503
     * @see https://git.io/transmission-rpc-specs "session-stats" for response arguments.
504
     *
505
     * @return array
506
     */
507
    public function sessionStats(): array
508
    {
509
        return $this->api('session-stats');
510
    }
511
512
    /**
513
     * Trigger Blocklist Update.
514
     *
515
     * @see https://git.io/transmission-rpc-specs "blocklist-update" for response arguments.
516
     *
517
     * @return array
518
     */
519
    public function updateBlocklist(): array
520
    {
521
        return $this->api('blocklist-update');
522
    }
523
524
    /**
525
     * Port Test: See if your incoming peer port is accessible from the outside world.
526
     *
527
     * @see https://git.io/transmission-rpc-specs "port-test" for response arguments.
528
     *
529
     * @return bool
530
     */
531
    public function portTest(): bool
532
    {
533
        return $this->api('port-test')['arguments']['port-is-open'];
534
    }
535
536
    /**
537
     * Shutdown Transmission.
538
     *
539
     * @see https://git.io/transmission-rpc-specs "session-close".
540
     *
541
     * @return bool
542
     */
543
    public function close(): bool
544
    {
545
        $this->api('session-close');
546
547
        return true;
548
    }
549
550
    /**
551
     * Move one or more torrents to top in queue.
552
     *
553
     * @see https://git.io/transmission-rpc-specs Queue Movement Requests.
554
     *
555
     * @param mixed $ids One or more torrent ids, sha1 hash strings, or both OR "recently-active", for
556
     *                   recently-active torrents. All torrents are used if no value is given.
557
     *
558
     * @return bool
559
     */
560
    public function queueMoveTop($ids = null): bool
561
    {
562
        $this->api('queue-move-top', compact('ids'));
563
564
        return true;
565
    }
566
567
    /**
568
     * Move one or more torrents up in queue.
569
     *
570
     * @see https://git.io/transmission-rpc-specs Queue Movement Requests.
571
     *
572
     * @param mixed $ids One or more torrent ids, sha1 hash strings, or both OR "recently-active", for
573
     *                   recently-active torrents. All torrents are used if no value is given.
574
     *
575
     * @return bool
576
     */
577
    public function queueMoveUp($ids = null): bool
578
    {
579
        $this->api('queue-move-top', compact('ids'));
580
581
        return true;
582
    }
583
584
    /**
585
     * Move one or more torrents down in queue.
586
     *
587
     * @see https://git.io/transmission-rpc-specs Queue Movement Requests.
588
     *
589
     * @param mixed $ids One or more torrent ids, sha1 hash strings, or both OR "recently-active", for
590
     *                   recently-active torrents. All torrents are used if no value is given.
591
     *
592
     * @return bool
593
     */
594
    public function queueMoveDown($ids = null): bool
595
    {
596
        $this->api('queue-move-down', compact('ids'));
597
598
        return true;
599
    }
600
601
    /**
602
     * Move one or more torrents to bottom in queue.
603
     *
604
     * @see https://git.io/transmission-rpc-specs Queue Movement Requests.
605
     *
606
     * @param mixed $ids One or more torrent ids, sha1 hash strings, or both OR "recently-active", for
607
     *                   recently-active torrents. All torrents are used if no value is given.
608
     *
609
     * @return bool
610
     */
611
    public function queueMoveBottom($ids = null): bool
612
    {
613
        $this->api('queue-move-bottom', compact('ids'));
614
615
        return true;
616
    }
617
618
    /**
619
     * Free Space: Tests how much free space is available in a client-specified folder.
620
     *
621
     * @see https://git.io/transmission-rpc-specs "free-space" for arguments.
622
     *
623
     * @param null|string $path Path to check free space (default: download-dir).
624
     *
625
     * @return array
626
     */
627
    public function freeSpace(string $path = null): array
628
    {
629
        if (blank($path)) {
630
            $path = $this->getSettings()['arguments']['download-dir'];
631
        }
632
633
        return $this->api('free-space', compact('path'))['arguments'];
634
    }
635
636
    /**
637
     * Seed Ratio Limit.
638
     *
639
     * @return int|float
640
     */
641
    public function seedRatioLimit()
642
    {
643
        $settings = $this->getSettings(['seedRatioLimited', 'seedRatioLimit'])['arguments'];
644
645
        if (isset($settings['seedRatioLimited'])) {
646
            return $settings['seedRatioLimit'];
647
        }
648
649
        return -1;
650
    }
651
652
    /**
653
     * Update Download Dir.
654
     *
655
     * @param string $downloadDir Path to download torrents.
656
     *
657
     * @return bool
658
     */
659
    public function updateDownloadDir(string $downloadDir): bool
660
    {
661
        $settings = [
662
            'download-dir' => $downloadDir,
663
        ];
664
665
        return $this->setSettings($settings);
666
    }
667
668
    /**
669
     * Update & Enable Incomplete Dir.
670
     *
671
     * @param string $incompleteDir       Path to store incomplete torrents.
672
     * @param bool   $enableIncompleteDir Is incomplete dir enabled? (default: true).
673
     *
674
     * @return bool
675
     */
676
    public function updateIncompleteDir(string $incompleteDir, bool $enableIncompleteDir = true): bool
677
    {
678
        $settings = [
679
            'incomplete-dir-enabled' => $enableIncompleteDir,
680
            'incomplete-dir'         => $incompleteDir,
681
        ];
682
683
        return $this->setSettings($settings);
684
    }
685
686
    /**
687
     * Request API.
688
     *
689
     * @param string $method
690
     * @param array  $params
691
     *
692
     * @return mixed
693
     */
694
    protected function api(string $method, array $params = [])
695
    {
696
        $arguments = ParamBuilder::build($params);
697
698
        $body = json_encode(compact('method', 'arguments'));
699
700
        try {
701
            $response = $this->getHttpClient()
702
                ->send(
703
                    'POST',
704
                    $this->transmissionUrl(),
705
                    ['Content-Type' => 'application/json'],
706
                    $body
707
                );
708
        } catch (Psr18\NetworkExceptionInterface $e) {
709
            throw new NetworkException($e->getMessage(), $e->getCode());
710
        }
711
712
        if (ResponseMediator::isConflictError($response)) {
713
            $this->findAndSetSessionId($response);
714
715
            return $this->api($method, $params);
716
        }
717
718
        return ResponseMediator::getContent($response);
719
    }
720
721
    /**
722
     * Find and Set Session ID from the response.
723
     *
724
     * @param ResponseInterface $response
725
     *
726
     * @throws TransmissionException
727
     *
728
     * @return Client
729
     */
730
    protected function findAndSetSessionId(ResponseInterface $response): self
731
    {
732
        $sessionId = $response->getHeaderLine('x-transmission-session-id');
733
734
        if (blank($sessionId)) {
735
            throw new TransmissionException('Unable to retrieve X-Transmission-Session-Id');
736
        }
737
738
        $this->setSessionId($sessionId);
739
740
        return $this;
741
    }
742
743
    /**
744
     * Transmission-RPC API URL.
745
     *
746
     * @return string
747
     */
748
    protected function transmissionUrl(): string
749
    {
750
        return 'http'.($this->isTLSEnabled() ? 's' : '').'://'.$this->host.':'.$this->port.$this->path;
751
    }
752
753
    /**
754
     * Default User Agent for all HTTP Requests.
755
     *
756
     * @return string HTTP User Agent.
757
     */
758
    protected function defaultUserAgent(): string
759
    {
760
        return 'PHP-Transmission-SDK/'.self::VERSION;
761
    }
762
763
    /**
764
     * Get HTTP Client.
765
     *
766
     * @return Builder
767
     */
768
    public function getHttpClient(): Builder
769
    {
770
        return $this->httpClientBuilder;
771
    }
772
773
    /**
774
     * @return History
775
     */
776
    public function getResponseHistory(): History
777
    {
778
        return $this->responseHistory;
779
    }
780
781
    /**
782
     * @param $method
783
     * @param $arguments
784
     *
785
     * @return mixed
786
     */
787
    public function __call($method, $arguments)
788
    {
789
        throw new \BadMethodCallException(sprintf(
790
            'Method %s::%s does not exist.',
791
            static::class,
792
            $method
793
        ));
794
    }
795
}
796