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

nette / assets / 14721447169

29 Apr 2025 01:37AM UTC coverage: 87.571% (+0.07%) from 87.5%
14721447169

push

github

dg
assets: added new properties

2 of 2 new or added lines in 1 file covered. (100.0%)

12 existing lines in 4 files now uncovered.

155 of 177 relevant lines covered (87.57%)

0.88 hits per line

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

83.33
/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
        public static function createAssetFromPath(string $path, string $url, array $args = []): Asset
1✔
18
        {
19
                $args['url'] = $url;
1✔
20
                $args['sourcePath'] = $path;
1✔
21
                $class = self::getAssetClassByExtension($path);
1✔
22
                if ($class === Types\ImageAsset::class) {
1✔
23
                        [0 => $args['width'], 1 => $args['height'], 'mime' => $args['mimeType']] = @getimagesize($path) ?: [null, null, 'mime' => null]; // @ - file may not exist
1✔
24
                } else {
25
                        $args['mimeType'] ??= @mime_content_type($path) ?: null; // @ - file may not exist
1✔
26
                }
27
                return new $class(...$args);
1✔
28
        }
29

30

31
        public static function getAssetClassByExtension(string $path): string
1✔
32
        {
33
                return match (strtolower(pathinfo($path, PATHINFO_EXTENSION))) {
1✔
34
                        'jpg', 'jpeg', 'png', 'gif', 'svg', 'webp', 'avif', 'bmp', 'ico' => Types\ImageAsset::class,
1✔
UNCOV
35
                        'js', 'mjs', 'cjs', 'ts', 'jsx', 'tsx' => Types\ScriptAsset::class,
×
UNCOV
36
                        'css', 'scss', 'sass', 'less', 'styl' => Types\StyleAsset::class,
×
37
                        'mp3', 'wav', 'ogg', 'aac', 'flac', 'm4a' => Types\AudioAsset::class,
1✔
38
                        'mp4', 'webm', 'ogv', 'avi', 'mov', 'mkv' => Types\VideoAsset::class,
×
39
                        default => Types\GenericAsset::class,
1✔
40
                };
41
        }
42

43

44
        /**
45
         * Validates an array of options against allowed optional and required keys.
46
         * @throws \InvalidArgumentException if there are unsupported or missing options
47
         */
48
        public static function checkOptions(array $array, array $optional = [], array $required = []): void
1✔
49
        {
50
                if ($keys = array_diff(array_keys($array), $optional, $required)) {
1✔
51
                        throw new \InvalidArgumentException('Unsupported asset options: ' . implode(', ', $keys));
1✔
52
                }
53
                if ($keys = array_diff($required, array_keys($array))) {
1✔
UNCOV
54
                        throw new \InvalidArgumentException('Missing asset options: ' . implode(', ', $keys));
×
55
                }
56
        }
1✔
57

58

59
        /**
60
         * Estimates the duration (in seconds) of an MP3 file, assuming constant bitrate (CBR).
61
         * @throws \RuntimeException If the file cannot be opened, MP3 sync bits aren't found, or bitrate is invalid/unsupported.
62
         */
63
        public static function guessMP3Duration(string $path): int
1✔
64
        {
65
                if (
66
                        ($header = @file_get_contents($path, length: 10000)) === false // @ - file may not exist
1✔
67
                        || ($fileSize = @filesize($path)) === false
1✔
68
                ) {
UNCOV
69
                        throw new \RuntimeException(sprintf("Failed to open file '%s'. %s", $path, Nette\Utils\Helpers::getLastError()));
×
70
                }
71

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

77
                $frameHeader = substr($header, $frameOffset, 4);
1✔
78
                $headerBits = unpack('N', $frameHeader)[1];
1✔
79
                $bitrateIndex = ($headerBits >> 12) & 0xF;
1✔
80
                $bitrate = [null, 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320][$bitrateIndex] ?? null;
1✔
81
                if ($bitrate === null) {
1✔
UNCOV
82
                        throw new \RuntimeException('Invalid or unsupported bitrate index.');
×
83
                }
84

85
                return (int) round($fileSize * 8 / $bitrate / 1000);
1✔
86
        }
87
}
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