Completed
Pull Request — master (#50)
by Alexander
01:51
created

AssetBundle::isRelative()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 2

Importance

Changes 0
Metric Value
eloc 1
dl 0
loc 3
ccs 2
cts 2
cp 1
rs 10
c 0
b 0
f 0
cc 2
nc 2
nop 1
crap 2
1
<?php
2
declare(strict_types = 1);
3
4
namespace Yiisoft\Asset;
5
6
use Yiisoft\Arrays\ArrayHelper;
7
use Yiisoft\View\WebView;
8
9
/**
10
 * AssetBundle represents a collection of asset files, such as CSS, JS, images.
11
 *
12
 * Each asset bundle has a unique name that globally identifies it among all asset bundles used in an application. The
13
 * name is the [fully qualified class name](http://php.net/manual/en/language.namespaces.rules.php) of the class
14
 * representing it.
15
 *
16
 * An asset bundle can depend on other asset bundles. When registering an asset bundle with a view, all its dependent
17
 * asset bundles will be automatically registered.
18
 */
19
class AssetBundle
20
{
21
    /**
22
     * @var string the Web-accessible directory that contains the asset files in this bundle.
23
     *
24
     * If {@see sourcePath} is set, this property will be *overwritten* by {@see AssetManager} when it publishes the
25
     * asset files from {@see sourcePath}.
26
     *
27
     * You can use either a directory or an alias of the directory.
28
     */
29
    public $basePath;
30
31
    /**
32
     * @var string the base URL for the relative asset files listed in {@see js} and {@see css}.
33
     *
34
     * If {@see {sourcePath} is set, this property will be *overwritten* by {@see {AssetManager} when it publishes the
35
     * asset files from {@see {sourcePath}.
36
     *
37
     * You can use either a URL or an alias of the URL.
38
     */
39
    public $baseUrl;
40
41
    /**
42
     * @var array list of CSS files that this bundle contains. Each CSS file can be specified in one of the three
43
     * formats as explained in {@see js}.
44
     *
45
     * Note that only a forward slash "/" should be used as directory separator.
46
     */
47
    public $css = [];
48
49
    /**
50
     * @var array the options that will be passed to {@see View::registerCssFile()} when registering the CSS files in
51
     * this bundle.
52
     */
53
    public $cssOptions = [];
54
55
    /**
56
     * @var array list of bundle class names that this bundle depends on.
57
     *
58
     * For example:
59
     *
60
     * ```php
61
     * public $depends = [
62
     *    \Yiisoft\Web\YiiAsset::class,
63
     *    \yii\bootstrap\BootstrapAsset::class,
64
     * ];
65
     * ```
66
     */
67
    public $depends = [];
68
69
    /**
70
     * @var array list of JavaScript files that this bundle contains. Each JavaScript file can be specified in one of
71
     * the following formats:
72
     *
73
     * - an absolute URL representing an external asset. For example,
74
     *   `http://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js` or
75
     *   `//ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js`.
76
     * - a relative path representing a local asset (e.g. `js/main.js`). The actual file path of a local asset can be
77
     *   determined by prefixing [[basePath]] to the relative path, and the actual URL of the asset can be determined
78
     *   by prefixing [[baseUrl]] to the relative path.
79
     * - an array, with the first entry being the URL or relative path as described before, and a list of key => value
80
     *   pairs that will be used to overwrite {@see jsOptions} settings for this entry.
81
     *
82
     * Note that only a forward slash "/" should be used as directory separator.
83
     */
84
    public $js = [];
85
86
    /**
87
     * @var array the options that will be passed to {@see View::registerJsFile()} when registering the JS files in this
88
     * bundle.
89
     */
90
    public $jsOptions = [];
91
92
    /**
93
     * @var array the options to be passed to {@see AssetManager::publish()} when the asset bundle  is being published.
94
     * This property is used only when {@see sourcePath} is set.
95
     */
96
    public $publishOptions = [];
97
98
    /**
99
     * @var string the directory that contains the source asset files for this asset bundle. A source asset file is a
100
     * file that is part of your source code repository of your Web application.
101
     *
102
     * You must set this property if the directory containing the source asset files is not Web accessible. By setting
103
     * this property, [[AssetManager]] will publish the source asset files to a Web-accessible directory automatically
104
     * when the asset bundle is registered on a page.
105
     *
106
     * If you do not set this property, it means the source asset files are located under {@see basePath}.
107
     *
108
     * You can use either a directory or an alias of the directory.
109
     *
110
     * {@see publishOptions}
111
     */
112
    public $sourcePath;
113
114
    /**
115
     * Publishes the asset bundle if its source code is not under Web-accessible directory.
116
     *
117
     * It will also try to convert non-CSS or JS files (e.g. LESS, Sass) into the corresponding CSS or JS files using
118
     * {@see AssetManager::converter|asset converter}.
119
     *
120
     * @param AssetManager $am the asset manager to perform the asset publishing
121
     * @return void
122
     */
123 13
    public function publish(AssetManager $am): void
124
    {
125 13
        if ($this->sourcePath !== null && !isset($this->basePath, $this->baseUrl)) {
126 2
            [$this->basePath, $this->baseUrl] = $am->publish($this->sourcePath, $this->publishOptions);
127
        }
128
129 13
        if (isset($this->basePath, $this->baseUrl) && ($converter = $am->getConverter()) !== null) {
130 13
            foreach ($this->js as $i => $js) {
131 13
                if (is_array($js)) {
132 1
                    $file = array_shift($js);
133 1
                    if ($this->isRelative($file)) {
134 1
                        $js = ArrayHelper::merge($this->jsOptions, $js);
135 1
                        array_unshift($js, $converter->convert($file, $this->basePath));
136 1
                        $this->js[$i] = $js;
137
                    }
138 13
                } elseif ($this->isRelative($js)) {
139 13
                    $this->js[$i] = $converter->convert($js, $this->basePath);
140
                }
141
            }
142 13
            foreach ($this->css as $i => $css) {
143 11
                if (is_array($css)) {
144 1
                    $file = array_shift($css);
145 1
                    if ($this->isRelative($file)) {
146 1
                        $css = ArrayHelper::merge($this->cssOptions, $css);
147 1
                        array_unshift($css, $converter->convert($file, $this->basePath));
148 1
                        $this->css[$i] = $css;
149
                    }
150 11
                } elseif ($this->isRelative($css)) {
151 11
                    $this->css[$i] = $converter->convert($css, $this->basePath);
152
                }
153
            }
154
        }
155
    }
156
157
    /**
158
     * Registers this asset bundle with a view.
159
     *
160
     * @param WebView $webView to be registered with
161
     *
162
     * @return AssetBundle the registered asset bundle instance
163
     */
164 12
    public static function register(WebView $webView): AssetBundle
165
    {
166 12
        return $webView->registerAssetBundle(static::class);
167
    }
168
169
    /**
170
     * Registers the CSS and JS files with the given view.
171
     *
172
     * @param Webview $view the view that the asset files are to be registered with.
173
     * @return void
174
     */
175 8
    public function registerAssetFiles(WebView $view): void
176
    {
177 8
        $manager = $view->getAssetManager();
178
179 8
        foreach ($this->js as $js) {
180 8
            if (is_array($js)) {
181 1
                $file = array_shift($js);
182 1
                $options = ArrayHelper::merge($this->jsOptions, $js);
183 1
                $view->registerJsFile($manager->getAssetUrl($this, $file), $options);
184 8
            } elseif ($js !== null) {
185 8
                $view->registerJsFile($manager->getAssetUrl($this, $js), $this->jsOptions);
186
            }
187
        }
188
189 8
        foreach ($this->css as $css) {
190 7
            if (is_array($css)) {
191 1
                $file = array_shift($css);
192 1
                $options = ArrayHelper::merge($this->cssOptions, $css);
193 1
                $view->registerCssFile($manager->getAssetUrl($this, $file), $options);
194 7
            } elseif ($css !== null) {
195 7
                $view->registerCssFile($manager->getAssetUrl($this, $css), $this->cssOptions);
196
            }
197
        }
198
    }
199
200
    /**
201
     * Returns a value indicating whether a URL is relative.
202
     * A relative URL does not have host info part.
203
     * @param string $url the URL to be checked
204
     * @return bool whether the URL is relative
205
     */
206 13
    protected function isRelative(string $url): bool
207
    {
208 13
        return strncmp($url, '//', 2) && strpos($url, '://') === false;
209
    }
210
}
211