Issues (7)

src/Formatter.php (1 issue)

Labels
Severity
1
<?php
2
3
namespace Transmission;
4
5
use Carbon\CarbonInterval;
6
use Illuminate\Support\Carbon;
7
8
/**
9
 * Formatter.
10
 */
11
class Formatter
12
{
13
    /** Used by formatBytes() modes */
14
    public const UNITS_MODE_DECIMAL = 0;
15
    public const UNITS_MODE_BINARY = 1;
16
    /** Speed */
17
    public const SPEED_KBPS = 1000;
18
19
    /**
20
     * Formats bytes into a human readable string if $format is true, otherwise return $bytes as is.
21
     *
22
     * @param int  $bytes
23
     * @param bool $format Should we suffix symbol? Default: true.
24
     * @param int  $mode   Should we calculate in binary/speed mode? Default: decimal.
25
     *
26
     * @return string
27
     */
28
    public static function formatBytes(int $bytes, bool $format = true, int $mode = 0): string
29
    {
30
        if (!$format) {
31
            return $bytes;
32
        }
33
34
        if ($mode === static::UNITS_MODE_BINARY) { // Binary (Used with memory size formating)
35
            $base = 1024;
36
            $units = ['B', 'KiB', 'MiB', 'GiB', 'TiB', 'PiB', 'EiB', 'ZiB', 'YiB'];
37
        } else { // Decimal (Disk space)
38
            $base = 1000;
39
            $units = ['B', 'kB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];
40
        }
41
42
        $i = 0;
43
44
        while ($bytes > $base) {
45
            $bytes /= $base;
46
            $i++;
47
        }
48
49
        return round($bytes, 2).' '.$units[$i];
50
    }
51
52
    /**
53
     * Speed Bps.
54
     *
55
     * @param $Bps
56
     *
57
     * @return string
58
     */
59
    public static function speedBps($Bps): string
60
    {
61
        return static::speed(static::bpsToKBps($Bps));
62
    }
63
64
    /**
65
     * Bps to KBps.
66
     *
67
     * @param $Bps
68
     *
69
     * @return float
70
     */
71
    public static function bpsToKBps($Bps): float
72
    {
73
        return floor($Bps / static::SPEED_KBPS);
74
    }
75
76
    /**
77
     * Format KBps to Data-rate units.
78
     *
79
     * @param $KBps
80
     *
81
     * @return string
82
     */
83
    public static function speed($KBps): string
84
    {
85
        $speed = $KBps;
86
87
        if ($speed <= 999.95) { // 0 KBps to 999 K
88
            return static::trunicateNumber($speed, 0).' KB/s';
89
        }
90
91
        $speed /= static::SPEED_KBPS;
92
93
        if ($speed <= 99.995) { // 1 M to 99.99 M
94
            return static::trunicateNumber($speed, 2).' MB/s';
95
        }
96
        if ($speed <= 999.95) { // 100 M to 999.9 M
97
            return static::trunicateNumber($speed, 1).' MB/s';
98
        }
99
100
        // insane speeds
101
        $speed /= static::SPEED_KBPS;
102
103
        return static::trunicateNumber($speed, 2).' GB/s';
104
    }
105
106
    /**
107
     * Trunicate a number to the given decimal points.
108
     *
109
     * @param string $number
110
     * @param int    $decimals
111
     *
112
     * @return string
113
     */
114
    public static function trunicateNumber($number, int $decimals = 2): string
115
    {
116
        return bcdiv($number, 1, $decimals);
117
    }
118
119
    /**
120
     * Cast an attribute to a native PHP type.
121
     *
122
     * @param mixed  $value
123
     * @param string $type
124
     *
125
     * @return mixed
126
     */
127
    public static function castAttribute($type, $value)
128
    {
129
        if ($value === null) {
130
            return $value;
131
        }
132
133
        switch ($type) {
134
            case 'collection':
135
                return collect(\is_array($value) ? $value : (new static())->fromJson($value));
0 ignored issues
show
It seems like is_array($value) ? $valu...tic()->fromJson($value) can also be of type array; however, parameter $value of collect() does only seem to accept Illuminate\Contracts\Support\Arrayable, 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

135
                return collect(/** @scrutinizer ignore-type */ \is_array($value) ? $value : (new static())->fromJson($value));
Loading history...
136
            case 'interval':
137
                return $value < 1 ? -1 : CarbonInterval::seconds($value)->cascade();
138
            case 'date':
139
                return (new static())->asDate($value);
140
            case 'datetime':
141
                return (new static())->asDateTime($value);
142
            case 'timestamp':
143
                return (new static())->asTimestamp($value);
144
            case 'size':
145
                return static::formatBytes($value);
146
            case 'memory':
147
                return static::formatBytes($value, true, static::UNITS_MODE_BINARY);
148
            case 'datarate':
149
                return static::speedBps($value);
150
            default:
151
                return $value;
152
        }
153
    }
154
155
    /**
156
     * Encode the given value as JSON.
157
     *
158
     * @param mixed $value
159
     *
160
     * @return string
161
     */
162
    protected function asJson($value): string
163
    {
164
        return json_encode($value);
165
    }
166
167
    /**
168
     * Decode the given JSON back into an array or object.
169
     *
170
     * @param string $value
171
     * @param bool   $asObject
172
     *
173
     * @return mixed
174
     */
175
    protected function fromJson($value, $asObject = false)
176
    {
177
        return json_decode($value, !$asObject);
178
    }
179
180
    /**
181
     * Return a timestamp as DateTime object with time set to 00:00:00.
182
     *
183
     * @param mixed $value
184
     *
185
     * @return \Illuminate\Support\Carbon
186
     */
187
    protected function asDate($value): Carbon
188
    {
189
        return $this->asDateTime($value)->startOfDay();
190
    }
191
192
    /**
193
     * Return a timestamp as DateTime object.
194
     *
195
     * @param mixed $value
196
     *
197
     * @return \Illuminate\Support\Carbon
198
     */
199
    protected function asDateTime($value): Carbon
200
    {
201
        // If this value is already a Carbon instance, we shall just return it as is.
202
        // This prevents us having to re-instantiate a Carbon instance when we know
203
        // it already is one, which wouldn't be fulfilled by the DateTime check.
204
        if ($value instanceof Carbon) {
205
            return $value;
206
        }
207
208
        // If this value is an integer, we will assume it is a UNIX timestamp's value
209
        // and format a Carbon object from this timestamp. This allows flexibility
210
        // when defining your date fields as they might be UNIX timestamps here.
211
        if (is_numeric($value)) {
212
            return Carbon::createFromTimestamp($value);
213
        }
214
215
        return $value;
216
    }
217
218
    /**
219
     * Return a timestamp as unix timestamp.
220
     *
221
     * @param mixed $value
222
     *
223
     * @return int
224
     */
225
    protected function asTimestamp($value): int
226
    {
227
        return $this->asDateTime($value)->getTimestamp();
228
    }
229
}
230