Torrent::getErrorMessage()   A
last analyzed

Complexity

Conditions 4
Paths 4

Size

Total Lines 12
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 1 Features 0
Metric Value
cc 4
eloc 10
c 2
b 1
f 0
nc 4
nop 0
dl 0
loc 12
rs 9.9332
1
<?php
2
3
namespace Transmission\Models;
4
5
use Transmission\Client;
6
7
/**
8
 * Torrent.
9
 *
10
 * @method mixed getUploadRatio(bool $castingEnabled = false)   Get Upload Ratio Value.
11
 * @method mixed getLeftUntilDone(bool $castingEnabled = false) Get Left Until Done Value.
12
 * @method mixed getHaveValid(bool $castingEnabled = false)     Get Have Valid Value.
13
 * @method mixed getHaveUnchecked(bool $castingEnabled = false) Get Have Unchecked Value.
14
 */
15
class Torrent extends AbstractModel
16
{
17
    /**
18
     * Statuses.
19
     *
20
     * Field: status
21
     */
22
    public const STATUS_STOPPED = 0; /* Torrent is stopped */
23
    public const STATUS_CHECK_WAIT = 1; /* Queued to check files */
24
    public const STATUS_CHECK = 2; /* Checking files */
25
    public const STATUS_DOWNLOAD_WAIT = 3; /* Queued to download */
26
    public const STATUS_DOWNLOAD = 4; /* Downloading */
27
    public const STATUS_SEED_WAIT = 5; /* Queued to seed */
28
    public const STATUS_SEED = 6; /* Seeding */
29
    public const STATUS_ISOLATED = 7; /* Isolated */
30
31
    /**
32
     * Seed Ratio Modes.
33
     *
34
     * Field: seedRatioMode
35
     */
36
    public const RATIO_USE_GLOBAL = 0;
37
    public const RATIO_USE_LOCAL = 1;
38
    public const RATIO_UNLIMITED = 2;
39
40
    /**
41
     * Errors.
42
     *
43
     * Field: error
44
     */
45
    /* everything's fine */
46
    public const ERROR_NONE = 0;
47
    /* when we announced to the tracker, we got a warning in the response */
48
    public const ERROR_TRACKER_WARNING = 1;
49
    /* when we announced to the tracker, we got an error in the response */
50
    public const ERROR_TRACKER_ERROR = 2;
51
    /* local trouble, such as disk full or permissions error */
52
    public const ERROR_LOCAL_ERROR = 3;
53
54
    /**
55
     * Tracker Stats.
56
     *
57
     * Field: trackerStats->announceState
58
     */
59
    public const TRACKER_INACTIVE = 0;
60
    public const TRACKER_WAITING = 1;
61
    public const TRACKER_QUEUED = 2;
62
    public const TRACKER_ACTIVE = 3;
63
64
    /**
65
     * Common Fields.
66
     *
67
     * @var array
68
     */
69
    public static $fields = [
70
        'default'    => [
71
            'id',
72
            'eta',
73
            'name',
74
            'status',
75
            'isFinished',
76
            'files',
77
            'hashString',
78
            'downloadDir',
79
            'percentDone',
80
            'haveValid',
81
            'haveUnchecked',
82
            'totalSize',
83
            'leftUntilDone',
84
            'addedDate',
85
            'doneDate',
86
            'activityDate',
87
        ],
88
        'stats'      => [
89
            'error',
90
            'errorString',
91
            'eta',
92
            'isFinished',
93
            'isStalled',
94
            'leftUntilDone',
95
            'metadataPercentComplete',
96
            'peersConnected',
97
            'peersGettingFromUs',
98
            'peersSendingToUs',
99
            'percentDone',
100
            'queuePosition',
101
            'rateDownload',
102
            'rateUpload',
103
            'recheckProgress',
104
            'seedRatioMode',
105
            'seedRatioLimit',
106
            'sizeWhenDone',
107
            'status',
108
            'trackers',
109
            'downloadDir',
110
            'uploadedEver',
111
            'uploadRatio',
112
            'webseedsSendingToUs',
113
        ],
114
        'statsExtra' => [
115
            'activityDate',
116
            'corruptEver',
117
            'desiredAvailable',
118
            'downloadedEver',
119
            'fileStats',
120
            'haveUnchecked',
121
            'haveValid',
122
            'peers',
123
            'startDate',
124
            'trackerStats',
125
        ],
126
        'infoExtra'  => [
127
            'comment',
128
            'creator',
129
            'dateCreated',
130
            'files',
131
            'hashString',
132
            'isPrivate',
133
            'pieceCount',
134
            'pieceSize',
135
        ],
136
    ];
137
138
    /**
139
     * The attributes that should be cast to native and other supported types.
140
     *
141
     * Casts only when formatting is enabled.
142
     *
143
     * @var array
144
     */
145
    protected $casts = [
146
        'doneDate'      => 'datetime',
147
        'startDate'     => 'datetime',
148
        'activityDate'  => 'datetime',
149
        'addedDate'     => 'datetime',
150
        'dateCreated'   => 'datetime',
151
        'eta'           => 'interval',
152
        'haveValid'     => 'size',
153
        'haveUnchecked' => 'size',
154
        'totalDone'     => 'size', // Custom
155
        'leftUntilDone' => 'size',
156
        'totalSize'     => 'size',
157
        'sizeWhenDone'  => 'size',
158
        'uploadedEver'  => 'size',
159
        'rateDownload'  => 'datarate',
160
        'rateUpload'    => 'datarate',
161
    ];
162
163
    /**
164
     * Get Name.
165
     *
166
     * @return string
167
     */
168
    public function getName(): string
169
    {
170
        return $this->get('name', 'Unknown');
171
    }
172
173
    /**
174
     * Get Percent Done.
175
     *
176
     * @param bool $format
177
     *
178
     * @return int
179
     */
180
    public function getPercentDone($format = false): int
181
    {
182
        $percentDone = $this->get('percentDone', 0);
183
184
        return $format ? $percentDone * 100 : $percentDone;
185
    }
186
187
    /**
188
     * Get Percent Done String.
189
     *
190
     * @return string
191
     */
192
    public function getPercentDoneString(): string
193
    {
194
        return $this->getPercentDone(true).'%';
195
    }
196
197
    /**
198
     * Get Metadata Percent Complete.
199
     *
200
     * @param bool $format
201
     *
202
     * @return int
203
     */
204
    public function getMetadataPercentComplete($format = false): int
205
    {
206
        $percent = $this->get('metadataPercentComplete', 0);
207
208
        return $format ? $percent * 100 : $percent;
209
    }
210
211
    /**
212
     * Get Recheck Progress Percent.
213
     *
214
     * @param bool $format
215
     *
216
     * @return int
217
     */
218
    public function getRecheckProgress($format = false): int
219
    {
220
        $percent = $this->get('recheckProgress', 0);
221
222
        return $format ? $percent * 100 : $percent;
223
    }
224
225
    /**
226
     * Get Total Done.
227
     *
228
     * @param null|bool $castingEnabled
229
     *
230
     * @return mixed
231
     */
232
    public function getTotalDone($castingEnabled = null)
233
    {
234
        $value = $this->getHaveValid(false) + $this->getHaveUnchecked(false);
235
236
        return $this->castAttribute('totalDone', $value, $castingEnabled ?? $this->castingEnabled);
237
    }
238
239
    /**
240
     * Get Upload Speed.
241
     *
242
     * @param null|bool $castingEnabled
243
     *
244
     * @return mixed
245
     */
246
    public function getUploadSpeed($castingEnabled = null)
247
    {
248
        return $this->get('rateUpload', 0, $castingEnabled);
249
    }
250
251
    /**
252
     * Get Download Speed.
253
     *
254
     * @param null|bool $castingEnabled
255
     *
256
     * @return mixed
257
     */
258
    public function getDownloadSpeed($castingEnabled = null)
259
    {
260
        return $this->get('rateDownload', 0, $castingEnabled);
261
    }
262
263
    /**
264
     * Get File Count.
265
     *
266
     * @return mixed
267
     */
268
    public function getFileCount()
269
    {
270
        return \count($this->get('files', 0));
271
    }
272
273
    /**
274
     * Get a File by ID.
275
     *
276
     * @param int $id
277
     *
278
     * @return mixed
279
     */
280
    public function getFile(int $id)
281
    {
282
        return data_get($this->items, "files.$id");
283
    }
284
285
    /**
286
     * Check if status is stopped.
287
     *
288
     * @return bool
289
     */
290
    public function isStopped(): bool
291
    {
292
        return $this->isStatus(static::STATUS_STOPPED);
293
    }
294
295
    /**
296
     * Check if status is checking.
297
     *
298
     * @return bool
299
     */
300
    public function isChecking(): bool
301
    {
302
        return $this->isStatus(static::STATUS_CHECK);
303
    }
304
305
    /**
306
     * Check if status is downloading.
307
     *
308
     * @return bool
309
     */
310
    public function isDownloading(): bool
311
    {
312
        return $this->isStatus(static::STATUS_DOWNLOAD);
313
    }
314
315
    /**
316
     * Check if status is queued.
317
     *
318
     * @return bool
319
     */
320
    public function isQueued(): bool
321
    {
322
        return $this->isStatus(static::STATUS_DOWNLOAD_WAIT) || $this->isStatus(static::STATUS_SEED_WAIT);
323
    }
324
325
    /**
326
     * Check if status is seeding.
327
     *
328
     * @return bool
329
     */
330
    public function isSeeding(): bool
331
    {
332
        return $this->isStatus(static::STATUS_SEED);
333
    }
334
335
    /**
336
     * Check if done downloading.
337
     *
338
     * @return bool
339
     */
340
    public function isDone(): bool
341
    {
342
        return $this->getLeftUntilDone(false) < 1;
343
    }
344
345
    /**
346
     * Check if given status matches the current status.
347
     *
348
     * @param $status
349
     *
350
     * @return bool
351
     */
352
    public function isStatus($status): bool
353
    {
354
        return $this->get('status') === $status;
355
    }
356
357
    /**
358
     * Check if meta data needs to be complete.
359
     *
360
     * @return bool
361
     */
362
    public function needsMetaData(): bool
363
    {
364
        return $this->getMetadataPercentComplete() < 1;
365
    }
366
367
    /**
368
     * Determine it's a magnet.
369
     *
370
     * @return bool
371
     */
372
    public function isMagnet(): bool
373
    {
374
        return $this->needsMetaData();
375
    }
376
377
    /**
378
     * Determine it's a multi-file folder.
379
     *
380
     * @return bool
381
     */
382
    public function isFolder(): bool
383
    {
384
        return $this->getFileCount() > 1;
385
    }
386
387
    /**
388
     * Get Status String.
389
     *
390
     * @return string
391
     */
392
    public function getStatusString(): ?string
393
    {
394
        switch ($this->get('status')) {
395
            case static::STATUS_STOPPED:
396
                return $this->get('isFinished', false) ? 'Seeding complete' : 'Paused';
397
            case static::STATUS_CHECK_WAIT:
398
                return 'Queued for verification';
399
            case static::STATUS_CHECK:
400
                return 'Verifying local data';
401
            case static::STATUS_DOWNLOAD_WAIT:
402
                return 'Queued for download';
403
            case static::STATUS_DOWNLOAD:
404
                return 'Downloading';
405
            case static::STATUS_SEED_WAIT:
406
                return 'Queued for seeding';
407
            case static::STATUS_SEED:
408
                return 'Seeding';
409
            case null:
410
                return 'Unknown';
411
            default:
412
                return 'Error';
413
        }
414
    }
415
416
    /**
417
     * Get Seed Ratio Limit.
418
     *
419
     * @param int|Client $globalSeedRatioLimit Provide the global seed ratio limit if you already have cached. This is
420
     *                                         to prevent fetching on every request when looping through multiple
421
     *                                         torrents as it'll be very slow doing so. It's recommended to cache it
422
     *                                         once and pass to this method, otherwise provide Client instance.
423
     *
424
     * @return int|string
425
     */
426
    public function seedRatioLimit($globalSeedRatioLimit)
427
    {
428
        switch ($this->get('seedRatioMode')) {
429
            case static::RATIO_USE_GLOBAL:
430
                return ($globalSeedRatioLimit instanceof Client) ? $globalSeedRatioLimit->seedRatioLimit() : $globalSeedRatioLimit;
431
            case static::RATIO_USE_LOCAL:
432
                return $this->get('seedRatioLimit');
433
            default:
434
                return -1;
435
        }
436
    }
437
438
    /**
439
     * Get Error Message.
440
     *
441
     * @return string|null
442
     */
443
    public function getErrorMessage(): ?string
444
    {
445
        $str = $this->get('errorString');
446
        switch ($this->get('error')) {
447
            case static::ERROR_TRACKER_WARNING:
448
                return 'Tracker returned a warning: '.$str;
449
            case static::ERROR_TRACKER_ERROR:
450
                return 'Tracker returned an error: '.$str;
451
            case static::ERROR_LOCAL_ERROR:
452
                return 'Error: '.$str;
453
            default:
454
                return null;
455
        }
456
    }
457
}
458