• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

nette / assets / 15008698441

13 May 2025 10:54PM UTC coverage: 95.035%. Remained the same
15008698441

push

github

dg
nette/assets

134 of 141 new or added lines in 5 files covered. (95.04%)

134 of 141 relevant lines covered (95.04%)

0.95 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

88.0
/src/Assets/Helpers.php
1
<?php
2

3
declare(strict_types=1);
4

5
namespace Nette\Assets;
6

7
use Nette;
8

9

10
/**
11
 * Static helper class providing utility functions for working with assets.
12
 */
13
final class Helpers
14
{
15
        use Nette\StaticClass;
16

17
        /**
18
         * Splits a potentially qualified reference 'mapper:reference' into a [mapper, reference] array.
19
         * @return array{?string, string}
20
         */
21
        public static function parseReference(string $qualifiedRef): array
1✔
22
        {
23
                $parts = explode(':', $qualifiedRef, 2);
1✔
24
                return count($parts) === 1
1✔
25
                        ? [null, $parts[0]]
1✔
26
                        : [$parts[0], $parts[1]];
1✔
27
        }
28

29

30
        /**
31
         * Validates an array of options against allowed optional and required keys.
32
         * @throws \InvalidArgumentException if there are unsupported or missing options
33
         */
34
        public static function checkOptions(array $array, array $optional = [], array $required = []): void
1✔
35
        {
36
                if ($keys = array_diff(array_keys($array), $optional, $required)) {
1✔
37
                        throw new \InvalidArgumentException('Unsupported asset options: ' . implode(', ', $keys));
1✔
38
                }
39
                if ($keys = array_diff($required, array_keys($array))) {
1✔
NEW
40
                        throw new \InvalidArgumentException('Missing asset options: ' . implode(', ', $keys));
×
41
                }
42
        }
1✔
43

44

45
        /**
46
         * Estimates the duration (in seconds) of an MP3 file, assuming constant bitrate (CBR).
47
         * @throws \RuntimeException If the file cannot be opened, MP3 sync bits aren't found, or the bitrate is invalid/unsupported.
48
         */
49
        public static function guessMP3Duration(string $path): float
1✔
50
        {
51
                if (
52
                        ($header = @file_get_contents($path, length: 10000)) === false // @ - file may not exist
1✔
53
                        || ($fileSize = @filesize($path)) === false
1✔
54
                ) {
NEW
55
                        throw new \RuntimeException(sprintf("Failed to open file '%s'. %s", $path, Nette\Utils\Helpers::getLastError()));
×
56
                }
57

58
                $frameOffset = strpos($header, "\xFF\xFB"); // 0xFB indicates MPEG Version 1, Layer III, no protection bit.
1✔
59
                if ($frameOffset === false) {
1✔
60
                        throw new \RuntimeException('Failed to find MP3 frame sync bits.');
1✔
61
                }
62

63
                $frameHeader = substr($header, $frameOffset, 4);
1✔
64
                $headerBits = unpack('N', $frameHeader)[1];
1✔
65
                $bitrateIndex = ($headerBits >> 12) & 0xF;
1✔
66
                $bitrate = [null, 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320][$bitrateIndex] ?? null;
1✔
67
                if ($bitrate === null) {
1✔
NEW
68
                        throw new \RuntimeException('Invalid or unsupported bitrate index.');
×
69
                }
70

71
                return $fileSize * 8 / $bitrate / 1000;
1✔
72
        }
73
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc