1 | <?php |
||
2 | /** |
||
3 | * @link https://www.yiiframework.com/ |
||
4 | * @copyright Copyright (c) 2008 Yii Software LLC |
||
5 | * @license https://www.yiiframework.com/license/ |
||
6 | */ |
||
7 | |||
8 | namespace yii\base; |
||
9 | |||
10 | use Yii; |
||
11 | use yii\helpers\FileHelper; |
||
12 | |||
13 | /** |
||
14 | * Theme represents an application theme. |
||
15 | * |
||
16 | * When [[View]] renders a view file, it will check the [[View::theme|active theme]] |
||
17 | * to see if there is a themed version of the view file exists. If so, the themed version will be rendered instead. |
||
18 | * |
||
19 | * A theme is a directory consisting of view files which are meant to replace their non-themed counterparts. |
||
20 | * |
||
21 | * Theme uses [[pathMap]] to achieve the view file replacement: |
||
22 | * |
||
23 | * 1. It first looks for a key in [[pathMap]] that is a substring of the given view file path; |
||
24 | * 2. If such a key exists, the corresponding value will be used to replace the corresponding part |
||
25 | * in the view file path; |
||
26 | * 3. It will then check if the updated view file exists or not. If so, that file will be used |
||
27 | * to replace the original view file. |
||
28 | * 4. If Step 2 or 3 fails, the original view file will be used. |
||
29 | * |
||
30 | * For example, if [[pathMap]] is `['@app/views' => '@app/themes/basic']`, |
||
31 | * then the themed version for a view file `@app/views/site/index.php` will be |
||
32 | * `@app/themes/basic/site/index.php`. |
||
33 | * |
||
34 | * It is possible to map a single path to multiple paths. For example, |
||
35 | * |
||
36 | * ```php |
||
37 | * 'pathMap' => [ |
||
38 | * '@app/views' => [ |
||
39 | * '@app/themes/christmas', |
||
40 | * '@app/themes/basic', |
||
41 | * ], |
||
42 | * ] |
||
43 | * ``` |
||
44 | * |
||
45 | * In this case, the themed version could be either `@app/themes/christmas/site/index.php` or |
||
46 | * `@app/themes/basic/site/index.php`. The former has precedence over the latter if both files exist. |
||
47 | * |
||
48 | * To use a theme, you should configure the [[View::theme|theme]] property of the "view" application |
||
49 | * component like the following: |
||
50 | * |
||
51 | * ```php |
||
52 | * 'view' => [ |
||
53 | * 'theme' => [ |
||
54 | * 'basePath' => '@app/themes/basic', |
||
55 | * 'baseUrl' => '@web/themes/basic', |
||
56 | * ], |
||
57 | * ], |
||
58 | * ``` |
||
59 | * |
||
60 | * The above configuration specifies a theme located under the "themes/basic" directory of the Web folder |
||
61 | * that contains the entry script of the application. If your theme is designed to handle modules, |
||
62 | * you may configure the [[pathMap]] property like described above. |
||
63 | * |
||
64 | * For more details and usage information on Theme, see the [guide article on theming](guide:output-theming). |
||
65 | * |
||
66 | * @property string $basePath The root path of this theme. All resources of this theme are located under this |
||
67 | * directory. |
||
68 | * @property string $baseUrl The base URL (without ending slash) for this theme. All resources of this theme |
||
69 | * are considered to be under this base URL. |
||
70 | * |
||
71 | * @author Qiang Xue <[email protected]> |
||
72 | * @since 2.0 |
||
73 | */ |
||
74 | class Theme extends Component |
||
75 | { |
||
76 | /** |
||
77 | * @var array|null the mapping between view directories and their corresponding themed versions. |
||
78 | * This property is used by [[applyTo()]] when a view is trying to apply the theme. |
||
79 | * [Path aliases](guide:concept-aliases) can be used when specifying directories. |
||
80 | * If this property is empty or not set, a mapping [[Application::basePath]] to [[basePath]] will be used. |
||
81 | */ |
||
82 | public $pathMap; |
||
83 | |||
84 | private $_baseUrl; |
||
85 | |||
86 | |||
87 | /** |
||
88 | * @return string the base URL (without ending slash) for this theme. All resources of this theme are considered |
||
89 | * to be under this base URL. |
||
90 | */ |
||
91 | 3 | public function getBaseUrl() |
|
92 | { |
||
93 | 3 | return $this->_baseUrl; |
|
94 | } |
||
95 | |||
96 | /** |
||
97 | * @param string $url the base URL or [path alias](guide:concept-aliases) for this theme. All resources of this theme are considered |
||
98 | * to be under this base URL. |
||
99 | */ |
||
100 | 4 | public function setBaseUrl($url) |
|
101 | { |
||
102 | 4 | $this->_baseUrl = $url === null ? null : rtrim(Yii::getAlias($url), '/'); |
|
103 | } |
||
104 | |||
105 | private $_basePath; |
||
106 | |||
107 | /** |
||
108 | * @return string the root path of this theme. All resources of this theme are located under this directory. |
||
109 | * @see pathMap |
||
110 | */ |
||
111 | 5 | public function getBasePath() |
|
112 | { |
||
113 | 5 | return $this->_basePath; |
|
114 | } |
||
115 | |||
116 | /** |
||
117 | * @param string $path the root path or [path alias](guide:concept-aliases) of this theme. All resources of this theme are located |
||
118 | * under this directory. |
||
119 | * @see pathMap |
||
120 | */ |
||
121 | 4 | public function setBasePath($path) |
|
122 | { |
||
123 | 4 | $this->_basePath = Yii::getAlias($path); |
|
124 | } |
||
125 | |||
126 | /** |
||
127 | * Converts a file to a themed file if possible. |
||
128 | * If there is no corresponding themed file, the original file will be returned. |
||
129 | * @param string $path the file to be themed |
||
130 | * @return string the themed file, or the original file if the themed version is not available. |
||
131 | * @throws InvalidConfigException if [[basePath]] is not set |
||
132 | */ |
||
133 | 7 | public function applyTo($path) |
|
134 | { |
||
135 | 7 | $pathMap = $this->pathMap; |
|
136 | 7 | if (empty($pathMap)) { |
|
137 | 2 | if (($basePath = $this->getBasePath()) === null) { |
|
138 | 1 | throw new InvalidConfigException('The "basePath" property must be set.'); |
|
139 | } |
||
140 | 1 | $pathMap = [Yii::$app->getBasePath() => [$basePath]]; |
|
141 | } |
||
142 | 6 | $path = FileHelper::normalizePath($path); |
|
143 | 6 | foreach ($pathMap as $from => $tos) { |
|
144 | 6 | $from = FileHelper::normalizePath(Yii::getAlias($from)) . DIRECTORY_SEPARATOR; |
|
0 ignored issues
–
show
Bug
introduced
by
Loading history...
|
|||
145 | 6 | if (strpos($path, $from) === 0) { |
|
146 | 6 | $n = strlen($from); |
|
147 | 6 | foreach ((array) $tos as $to) { |
|
148 | 6 | $to = FileHelper::normalizePath(Yii::getAlias($to)) . DIRECTORY_SEPARATOR; |
|
149 | 6 | $file = $to . substr($path, $n); |
|
150 | 6 | if (is_file($file)) { |
|
151 | 5 | return $file; |
|
152 | } |
||
153 | } |
||
154 | } |
||
155 | } |
||
156 | |||
157 | 2 | return $path; |
|
158 | } |
||
159 | |||
160 | /** |
||
161 | * Converts a relative URL into an absolute URL using [[baseUrl]]. |
||
162 | * @param string $url the relative URL to be converted. |
||
163 | * @return string the absolute URL |
||
164 | * @throws InvalidConfigException if [[baseUrl]] is not set |
||
165 | */ |
||
166 | 2 | public function getUrl($url) |
|
167 | { |
||
168 | 2 | if (($baseUrl = $this->getBaseUrl()) !== null) { |
|
0 ignored issues
–
show
|
|||
169 | 1 | return $baseUrl . '/' . ltrim($url, '/'); |
|
170 | } |
||
171 | |||
172 | 1 | throw new InvalidConfigException('The "baseUrl" property must be set.'); |
|
173 | } |
||
174 | |||
175 | /** |
||
176 | * Converts a relative file path into an absolute one using [[basePath]]. |
||
177 | * @param string $path the relative file path to be converted. |
||
178 | * @return string the absolute file path |
||
179 | * @throws InvalidConfigException if [[basePath]] is not set |
||
180 | */ |
||
181 | 2 | public function getPath($path) |
|
182 | { |
||
183 | 2 | if (($basePath = $this->getBasePath()) !== null) { |
|
184 | 1 | return $basePath . DIRECTORY_SEPARATOR . ltrim($path, '/\\'); |
|
185 | } |
||
186 | |||
187 | 1 | throw new InvalidConfigException('The "basePath" property must be set.'); |
|
188 | } |
||
189 | } |
||
190 |