Passed
Push — master ( 9601bc...40dd50 )
by Evgeniy
02:37
created

AssetUtil::exportToFile()   A

Complexity

Conditions 4
Paths 3

Size

Total Lines 10
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 4.074

Importance

Changes 0
Metric Value
eloc 5
c 0
b 0
f 0
dl 0
loc 10
ccs 5
cts 6
cp 0.8333
rs 10
cc 4
nc 3
nop 2
crap 4.074
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Yiisoft\Assets;
6
7
use RuntimeException;
8
use Yiisoft\Aliases\Aliases;
9
10
use function dirname;
11
use function file_put_contents;
12
use function is_dir;
13
use function is_subclass_of;
14
use function is_writable;
15
use function mb_strlen;
16
use function strncmp;
17
use function strpos;
18
use function substr_compare;
19
20
/**
21
 * AssetUtil shared functions.
22
 */
23
final class AssetUtil
24
{
25
    /**
26
     * Creates a new asset bundle instance.
27
     *
28
     * If the name is a class name, an instance of this class will be created,
29
     * otherwise an instance of the {@see AssetBundle} will be created.
30
     *
31
     * @param string $name The asset bundle name. Usually the asset bundle class name (without leading backslash).
32
     * @param array $config The asset bundle instance configuration. If specified, it will be applied to the instance.
33
     *
34
     * @return AssetBundle The created asset bundle.
35
     *
36
     * @psalm-suppress UnsafeInstantiation
37
     */
38 42
    public static function createAsset(string $name, array $config = []): AssetBundle
39
    {
40 42
        $bundle = is_subclass_of($name, AssetBundle::class) ? new $name() : new AssetBundle();
41
42 42
        foreach ($config as $property => $value) {
43 17
            $bundle->{$property} = $value;
44
        }
45
46 42
        return $bundle;
47
    }
48
49
    /**
50
     * Resolves the actual URL for the specified asset.
51
     *
52
     * @param AssetBundle $bundle The asset bundle which the asset file belongs to.
53
     * @param string $assetPath The asset path. This should be one of the assets listed
54
     * in {@see AssetBundle::$js} or {@see AssetBundle::$css}.
55
     * @param array $assetMap Mapping from source asset files (keys) to target asset files (values)
56
     * {@see AssetPublisher::$assetMap}.
57
     *
58
     * @return string|null The actual URL for the specified asset, or null if there is no mapping.
59
     */
60 33
    public static function resolveAsset(AssetBundle $bundle, string $assetPath, array $assetMap): ?string
61
    {
62 33
        if (isset($assetMap[$assetPath])) {
63 1
            return $assetMap[$assetPath];
64
        }
65
66 32
        if (!empty($bundle->sourcePath) && self::isRelative($assetPath)) {
67 8
            $assetPath = $bundle->sourcePath . '/' . $assetPath;
68
        }
69
70 32
        $n = mb_strlen($assetPath, 'utf-8');
71
72 32
        foreach ($assetMap as $from => $to) {
73
            $n2 = mb_strlen($from, 'utf-8');
74
            if ($n2 <= $n && substr_compare($assetPath, $from, $n - $n2, $n2) === 0) {
75
                return $to;
76
            }
77
        }
78
79 32
        return null;
80
    }
81
82
    /**
83
     * Resolve path aliases for {@see AssetBundle} properties:
84
     *
85
     * - {@see AssetBundle::basePath}
86
     * - {@see AssetBundle::baseUrl}
87
     * - {@see AssetBundle::sourcePath}
88
     *
89
     * @param AssetBundle $bundle The asset bundle instance to resolving path aliases.
90
     * @param Aliases $aliases The aliases instance to resolving path aliases.
91
     *
92
     * @return AssetBundle The asset bundle instance with resolved paths.
93
     */
94 3
    public static function resolvePathAliases(AssetBundle $bundle, Aliases $aliases): AssetBundle
95
    {
96 3
        if ($bundle->basePath !== null) {
97 3
            $bundle->basePath = $aliases->get($bundle->basePath);
98
        }
99
100 3
        if ($bundle->baseUrl !== null) {
101 3
            $bundle->baseUrl = $aliases->get($bundle->baseUrl);
102
        }
103
104 3
        if ($bundle->sourcePath !== null) {
105 1
            $bundle->sourcePath = $aliases->get($bundle->sourcePath);
106
        }
107
108 3
        return $bundle;
109
    }
110
111
    /**
112
     * Writes a string representation of asset bundles to the specified file.
113
     *
114
     * @param string $targetFile The full path to the target file.
115
     * @param string $bundles The string representation of asset bundles.
116
     *
117
     * @throws RuntimeException If an error occurred while writing to the file.
118
     */
119 7
    public static function exportToFile(string $targetFile, string $bundles): void
120
    {
121 7
        $targetDirectory = dirname($targetFile);
122
123 7
        if (!is_dir($targetDirectory) || !is_writable($targetDirectory)) {
124 2
            throw new RuntimeException("Target directory \"{$targetDirectory}\" does not exist or is not writable.");
125
        }
126
127 5
        if (file_put_contents($targetFile, $bundles, LOCK_EX) === false) {
128
            throw new RuntimeException("An error occurred while writing to the \"{$targetFile}\" file.");
129
        }
130 5
    }
131
132
    /**
133
     * Returns a value indicating whether a URL is relative.
134
     *
135
     * A relative URL does not have host info part.
136
     *
137
     * @param string $url The URL to be checked.
138
     *
139
     * @return bool Whether the URL is relative.
140
     */
141 32
    public static function isRelative(string $url): bool
142
    {
143 32
        return strncmp($url, '//', 2) && strpos($url, '://') === false;
144
    }
145
}
146