1 | <?php |
||
2 | |||
3 | /** |
||
4 | * Helper file for handling themes. |
||
5 | * |
||
6 | * Simple Machines Forum (SMF) |
||
7 | * |
||
8 | * @package SMF |
||
9 | * @author Simple Machines https://www.simplemachines.org |
||
10 | * @copyright 2020 Simple Machines and individual contributors |
||
11 | * @license https://www.simplemachines.org/about/smf/license.php BSD |
||
12 | * |
||
13 | * @version 2.1 RC2 |
||
14 | */ |
||
15 | |||
16 | if (!defined('SMF')) |
||
17 | die('No direct access...'); |
||
18 | |||
19 | /** |
||
20 | * Gets a single theme's info. |
||
21 | * |
||
22 | * @param int $id The theme ID to get the info from. |
||
23 | * @return array The theme info as an array. |
||
24 | */ |
||
25 | function get_single_theme($id) |
||
26 | { |
||
27 | global $smcFunc, $modSettings; |
||
28 | |||
29 | // No data, no fun! |
||
30 | if (empty($id)) |
||
31 | return false; |
||
32 | |||
33 | // Make sure $id is an int. |
||
34 | $id = (int) $id; |
||
35 | |||
36 | // List of all possible values. |
||
37 | $themeValues = array( |
||
38 | 'theme_dir', |
||
39 | 'images_url', |
||
40 | 'theme_url', |
||
41 | 'name', |
||
42 | 'theme_layers', |
||
43 | 'theme_templates', |
||
44 | 'version', |
||
45 | 'install_for', |
||
46 | 'based_on', |
||
47 | ); |
||
48 | |||
49 | // Make changes if you really want it. |
||
50 | call_integration_hook('integrate_get_single_theme', array(&$themeValues, $id)); |
||
51 | |||
52 | $single = array( |
||
53 | 'id' => $id, |
||
54 | ); |
||
55 | |||
56 | // Make our known/enable themes a little easier to work with. |
||
57 | $knownThemes = !empty($modSettings['knownThemes']) ? explode(',', $modSettings['knownThemes']) : array(); |
||
58 | $enableThemes = !empty($modSettings['enableThemes']) ? explode(',', $modSettings['enableThemes']) : array(); |
||
59 | |||
60 | $request = $smcFunc['db_query']('', ' |
||
61 | SELECT id_theme, variable, value |
||
62 | FROM {db_prefix}themes |
||
63 | WHERE variable IN ({array_string:theme_values}) |
||
64 | AND id_theme = ({int:id_theme}) |
||
65 | AND id_member = {int:no_member}', |
||
66 | array( |
||
67 | 'theme_values' => $themeValues, |
||
68 | 'id_theme' => $id, |
||
69 | 'no_member' => 0, |
||
70 | ) |
||
71 | ); |
||
72 | |||
73 | while ($row = $smcFunc['db_fetch_assoc']($request)) |
||
74 | { |
||
75 | $single[$row['variable']] = $row['value']; |
||
76 | |||
77 | // Fix the path and tell if its a valid one. |
||
78 | if ($row['variable'] == 'theme_dir') |
||
79 | { |
||
80 | $single['theme_dir'] = realpath($row['value']); |
||
81 | $single['valid_path'] = file_exists($row['value']) && is_dir($row['value']); |
||
82 | } |
||
83 | } |
||
84 | |||
85 | // Is this theme installed and enabled? |
||
86 | $single['known'] = in_array($single['id'], $knownThemes); |
||
87 | $single['enable'] = in_array($single['id'], $enableThemes); |
||
88 | |||
89 | // It should at least return if the theme is a known one or if its enable. |
||
90 | return $single; |
||
91 | } |
||
92 | |||
93 | /** |
||
94 | * Loads and returns all installed themes. |
||
95 | * |
||
96 | * Stores all themes on $context['themes'] for easier use. |
||
97 | * |
||
98 | * $modSettings['knownThemes'] stores themes that the user is able to select. |
||
99 | * |
||
100 | * @param bool $enable_only Whether to fetch only enabled themes. Default is false. |
||
101 | */ |
||
102 | function get_all_themes($enable_only = false) |
||
103 | { |
||
104 | global $modSettings, $context, $smcFunc; |
||
105 | |||
106 | // Make our known/enable themes a little easier to work with. |
||
107 | $knownThemes = !empty($modSettings['knownThemes']) ? explode(',', $modSettings['knownThemes']) : array(); |
||
108 | $enableThemes = !empty($modSettings['enableThemes']) ? explode(',', $modSettings['enableThemes']) : array(); |
||
109 | |||
110 | // List of all possible themes values. |
||
111 | $themeValues = array( |
||
112 | 'theme_dir', |
||
113 | 'images_url', |
||
114 | 'theme_url', |
||
115 | 'name', |
||
116 | 'theme_layers', |
||
117 | 'theme_templates', |
||
118 | 'version', |
||
119 | 'install_for', |
||
120 | 'based_on', |
||
121 | ); |
||
122 | |||
123 | // Make changes if you really want it. |
||
124 | call_integration_hook('integrate_get_all_themes', array(&$themeValues, $enable_only)); |
||
125 | |||
126 | // So, what is it going to be? |
||
127 | $query_where = $enable_only ? $enableThemes : $knownThemes; |
||
128 | |||
129 | // Perform the query as requested. |
||
130 | $request = $smcFunc['db_query']('', ' |
||
131 | SELECT id_theme, variable, value |
||
132 | FROM {db_prefix}themes |
||
133 | WHERE variable IN ({array_string:theme_values}) |
||
134 | AND id_theme IN ({array_string:query_where}) |
||
135 | AND id_member = {int:no_member}', |
||
136 | array( |
||
137 | 'query_where' => $query_where, |
||
138 | 'theme_values' => $themeValues, |
||
139 | 'no_member' => 0, |
||
140 | ) |
||
141 | ); |
||
142 | |||
143 | $context['themes'] = array(); |
||
144 | |||
145 | while ($row = $smcFunc['db_fetch_assoc']($request)) |
||
146 | { |
||
147 | $context['themes'][$row['id_theme']]['id'] = (int) $row['id_theme']; |
||
148 | |||
149 | // Fix the path and tell if its a valid one. |
||
150 | if ($row['variable'] == 'theme_dir') |
||
151 | { |
||
152 | $context['themes'][$row['id_theme']][$row['variable']] = realpath($row['value']); |
||
153 | $context['themes'][$row['id_theme']]['valid_path'] = file_exists(realpath($row['value'])) && is_dir(realpath($row['value'])); |
||
154 | } |
||
155 | |||
156 | $context['themes'][$row['id_theme']]['known'] = in_array($row['id_theme'], $knownThemes); |
||
157 | $context['themes'][$row['id_theme']]['enable'] = in_array($row['id_theme'], $enableThemes); |
||
158 | $context['themes'][$row['id_theme']][$row['variable']] = $row['value']; |
||
159 | } |
||
160 | |||
161 | $smcFunc['db_free_result']($request); |
||
162 | } |
||
163 | |||
164 | /** |
||
165 | * Loads and returns all installed themes. |
||
166 | * |
||
167 | * Stores all themes on $context['themes'] for easier use. |
||
168 | * |
||
169 | * $modSettings['knownThemes'] stores themes that the user is able to select. |
||
170 | */ |
||
171 | function get_installed_themes() |
||
172 | { |
||
173 | global $modSettings, $context, $smcFunc; |
||
174 | |||
175 | // Make our known/enable themes a little easier to work with. |
||
176 | $knownThemes = !empty($modSettings['knownThemes']) ? explode(',', $modSettings['knownThemes']) : array(); |
||
177 | $enableThemes = !empty($modSettings['enableThemes']) ? explode(',', $modSettings['enableThemes']) : array(); |
||
178 | |||
179 | // List of all possible themes values. |
||
180 | $themeValues = array( |
||
181 | 'theme_dir', |
||
182 | 'images_url', |
||
183 | 'theme_url', |
||
184 | 'name', |
||
185 | 'theme_layers', |
||
186 | 'theme_templates', |
||
187 | 'version', |
||
188 | 'install_for', |
||
189 | 'based_on', |
||
190 | ); |
||
191 | |||
192 | // Make changes if you really want it. |
||
193 | call_integration_hook('integrate_get_installed_themes', array(&$themeValues)); |
||
194 | |||
195 | // Perform the query as requested. |
||
196 | $request = $smcFunc['db_query']('', ' |
||
197 | SELECT id_theme, variable, value |
||
198 | FROM {db_prefix}themes |
||
199 | WHERE variable IN ({array_string:theme_values}) |
||
200 | AND id_member = {int:no_member}', |
||
201 | array( |
||
202 | 'theme_values' => $themeValues, |
||
203 | 'no_member' => 0, |
||
204 | ) |
||
205 | ); |
||
206 | |||
207 | $context['themes'] = array(); |
||
208 | |||
209 | while ($row = $smcFunc['db_fetch_assoc']($request)) |
||
210 | { |
||
211 | $context['themes'][$row['id_theme']]['id'] = (int) $row['id_theme']; |
||
212 | |||
213 | // Fix the path and tell if its a valid one. |
||
214 | if ($row['variable'] == 'theme_dir') |
||
215 | { |
||
216 | $context['themes'][$row['id_theme']][$row['variable']] = realpath($row['value']); |
||
217 | $context['themes'][$row['id_theme']]['valid_path'] = file_exists(realpath($row['value'])) && is_dir(realpath($row['value'])); |
||
218 | } |
||
219 | |||
220 | $context['themes'][$row['id_theme']]['known'] = in_array($row['id_theme'], $knownThemes); |
||
221 | $context['themes'][$row['id_theme']]['enable'] = in_array($row['id_theme'], $enableThemes); |
||
222 | $context['themes'][$row['id_theme']][$row['variable']] = $row['value']; |
||
223 | } |
||
224 | |||
225 | $smcFunc['db_free_result']($request); |
||
226 | } |
||
227 | |||
228 | /** |
||
229 | * Reads an .xml file and returns the data as an array |
||
230 | * |
||
231 | * Removes the entire theme if the .xml file couldn't be found or read. |
||
232 | * |
||
233 | * @param string $path The absolute path to the xml file. |
||
234 | * @return array An array with all the info extracted from the xml file. |
||
235 | */ |
||
236 | function get_theme_info($path) |
||
237 | { |
||
238 | global $smcFunc, $sourcedir, $txt, $scripturl, $context; |
||
239 | global $explicit_images; |
||
240 | |||
241 | if (empty($path)) |
||
242 | return false; |
||
243 | |||
244 | $xml_data = array(); |
||
245 | $explicit_images = false; |
||
246 | |||
247 | // Perhaps they are trying to install a mod, lets tell them nicely this is the wrong function. |
||
248 | if (file_exists($path . '/package-info.xml')) |
||
249 | { |
||
250 | loadLanguage('Errors'); |
||
251 | |||
252 | // We need to delete the dir otherwise the next time you try to install a theme you will get the same error. |
||
253 | remove_dir($path); |
||
254 | |||
255 | $txt['package_get_error_is_mod'] = str_replace('{MANAGEMODURL}', $scripturl . '?action=admin;area=packages;' . $context['session_var'] . '=' . $context['session_id'], $txt['package_get_error_is_mod']); |
||
256 | fatal_lang_error('package_theme_upload_error_broken', false, $txt['package_get_error_is_mod']); |
||
257 | } |
||
258 | |||
259 | // Parse theme-info.xml into an xmlArray. |
||
260 | require_once($sourcedir . '/Class-Package.php'); |
||
261 | $theme_info_xml = new xmlArray(file_get_contents($path . '/theme_info.xml')); |
||
262 | |||
263 | // Error message, there isn't any valid info. |
||
264 | if (!$theme_info_xml->exists('theme-info[0]')) |
||
265 | { |
||
266 | remove_dir($path); |
||
267 | fatal_lang_error('package_get_error_packageinfo_corrupt', false); |
||
268 | } |
||
269 | |||
270 | // Check for compatibility with 2.1 or greater. |
||
271 | if (!$theme_info_xml->exists('theme-info/install')) |
||
272 | { |
||
273 | remove_dir($path); |
||
274 | fatal_lang_error('package_get_error_theme_not_compatible', false, SMF_FULL_VERSION); |
||
275 | } |
||
276 | |||
277 | // So, we have an install tag which is cool and stuff but we also need to check it and match your current SMF version... |
||
278 | $the_version = SMF_VERSION; |
||
279 | $install_versions = $theme_info_xml->path('theme-info/install/@for'); |
||
280 | |||
281 | // The theme isn't compatible with the current SMF version. |
||
282 | if (!$install_versions || !matchPackageVersion($the_version, $install_versions)) |
||
283 | { |
||
284 | remove_dir($path); |
||
285 | fatal_lang_error('package_get_error_theme_not_compatible', false, SMF_FULL_VERSION); |
||
286 | } |
||
287 | |||
288 | $theme_info_xml = $theme_info_xml->path('theme-info[0]'); |
||
289 | $theme_info_xml = $theme_info_xml->to_array(); |
||
290 | |||
291 | $xml_elements = array( |
||
292 | 'theme_layers' => 'layers', |
||
293 | 'theme_templates' => 'templates', |
||
294 | 'based_on' => 'based-on', |
||
295 | 'version' => 'version', |
||
296 | ); |
||
297 | |||
298 | // Assign the values to be stored. |
||
299 | foreach ($xml_elements as $var => $name) |
||
300 | if (!empty($theme_info_xml[$name])) |
||
301 | $xml_data[$var] = $theme_info_xml[$name]; |
||
302 | |||
303 | // Add the supported versions. |
||
304 | $xml_data['install_for'] = $install_versions; |
||
305 | |||
306 | // Overwrite the default images folder. |
||
307 | if (!empty($theme_info_xml['images'])) |
||
308 | { |
||
309 | $xml_data['images_url'] = $path . '/' . $theme_info_xml['images']; |
||
310 | $explicit_images = true; |
||
311 | } |
||
312 | |||
313 | if (!empty($theme_info_xml['extra'])) |
||
314 | $xml_data += $smcFunc['json_decode']($theme_info_xml['extra'], true); |
||
315 | |||
316 | return $xml_data; |
||
317 | } |
||
318 | |||
319 | /** |
||
320 | * Inserts a theme's data to the DataBase. |
||
321 | * |
||
322 | * Ends execution with fatal_lang_error() if an error appears. |
||
323 | * |
||
324 | * @param array $to_install An array containing all values to be stored into the DB. |
||
325 | * @return int The newly created theme ID. |
||
326 | */ |
||
327 | function theme_install($to_install = array()) |
||
328 | { |
||
329 | global $smcFunc, $context, $modSettings; |
||
330 | global $settings, $explicit_images; |
||
331 | |||
332 | // External use? no problem! |
||
333 | if ($to_install) |
||
0 ignored issues
–
show
|
|||
334 | $context['to_install'] = $to_install; |
||
335 | |||
336 | // One last check. |
||
337 | if (empty($context['to_install']['theme_dir']) || basename($context['to_install']['theme_dir']) == 'Themes') |
||
338 | fatal_lang_error('theme_install_invalid_dir', false); |
||
339 | |||
340 | // OK, is this a newer version of an already installed theme? |
||
341 | if (!empty($context['to_install']['version'])) |
||
342 | { |
||
343 | $request = $smcFunc['db_query']('', ' |
||
344 | SELECT id_theme, variable, value |
||
345 | FROM {db_prefix}themes |
||
346 | WHERE id_member = {int:no_member} |
||
347 | AND variable = {string:name} |
||
348 | AND value LIKE {string:name_value} |
||
349 | LIMIT 1', |
||
350 | array( |
||
351 | 'no_member' => 0, |
||
352 | 'name' => 'name', |
||
353 | 'version' => 'version', |
||
354 | 'name_value' => '%' . $context['to_install']['name'] . '%', |
||
355 | ) |
||
356 | ); |
||
357 | |||
358 | $to_update = $smcFunc['db_fetch_assoc']($request); |
||
359 | $smcFunc['db_free_result']($request); |
||
360 | |||
361 | // Got something, lets figure it out what to do next. |
||
362 | if (!empty($to_update) && !empty($to_update['version'])) |
||
363 | switch (compareVersions($context['to_install']['version'], $to_update['version'])) |
||
364 | { |
||
365 | case 1: // Got a newer version, update the old entry. |
||
366 | $smcFunc['db_query']('', ' |
||
367 | UPDATE {db_prefix}themes |
||
368 | SET value = {string:new_value} |
||
369 | WHERE variable = {string:version} |
||
370 | AND id_theme = {int:id_theme}', |
||
371 | array( |
||
372 | 'new_value' => $context['to_install']['version'], |
||
373 | 'version' => 'version', |
||
374 | 'id_theme' => $to_update['id_theme'], |
||
375 | ) |
||
376 | ); |
||
377 | |||
378 | // Done with the update, tell the user about it. |
||
379 | $context['to_install']['updated'] = true; |
||
380 | |||
381 | return $to_update['id_theme']; |
||
382 | break; // Just for reference. |
||
383 | case 0: // This is exactly the same theme. |
||
384 | case -1: // The one being installed is older than the one already installed. |
||
385 | default: // Any other possible result. |
||
386 | fatal_lang_error('package_get_error_theme_no_new_version', false, array($context['to_install']['version'], $to_update['version'])); |
||
387 | } |
||
388 | } |
||
389 | |||
390 | if (!empty($context['to_install']['based_on'])) |
||
391 | { |
||
392 | // No need for elaborated stuff when the theme is based on the default one. |
||
393 | if ($context['to_install']['based_on'] == 'default') |
||
394 | { |
||
395 | $context['to_install']['theme_url'] = $settings['default_theme_url']; |
||
396 | $context['to_install']['images_url'] = $settings['default_images_url']; |
||
397 | } |
||
398 | |||
399 | // Custom theme based on another custom theme, lets get some info. |
||
400 | elseif ($context['to_install']['based_on'] != '') |
||
401 | { |
||
402 | $context['to_install']['based_on'] = preg_replace('~[^A-Za-z0-9\-_ ]~', '', $context['to_install']['based_on']); |
||
403 | |||
404 | // Get the theme info first. |
||
405 | $request = $smcFunc['db_query']('', ' |
||
406 | SELECT id_theme |
||
407 | FROM {db_prefix}themes |
||
408 | WHERE id_member = {int:no_member} |
||
409 | AND (value LIKE {string:based_on} OR value LIKE {string:based_on_path}) |
||
410 | LIMIT 1', |
||
411 | array( |
||
412 | 'no_member' => 0, |
||
413 | 'based_on' => '%/' . $context['to_install']['based_on'], |
||
414 | 'based_on_path' => '%' . "\\" . $context['to_install']['based_on'], |
||
415 | ) |
||
416 | ); |
||
417 | |||
418 | $based_on = $smcFunc['db_fetch_assoc']($request); |
||
419 | $smcFunc['db_free_result']($request); |
||
420 | |||
421 | $request = $smcFunc['db_query']('', ' |
||
422 | SELECT variable, value |
||
423 | FROM {db_prefix}themes |
||
424 | WHERE variable IN ({array_string:theme_values}) |
||
425 | AND id_theme = ({int:based_on}) |
||
426 | LIMIT 1', |
||
427 | array( |
||
428 | 'no_member' => 0, |
||
429 | 'theme__values' => array('theme_url', 'images_url', 'theme_dir',), |
||
430 | 'based_on' => $based_on['id_theme'], |
||
431 | ) |
||
432 | ); |
||
433 | $temp = $smcFunc['db_fetch_assoc']($request); |
||
434 | $smcFunc['db_free_result']($request); |
||
435 | |||
436 | // Found the based on theme info, add it to the current one being installed. |
||
437 | if (is_array($temp)) |
||
438 | { |
||
439 | $context['to_install']['base_theme_url'] = $temp['theme_url']; |
||
440 | $context['to_install']['base_theme_dir'] = $temp['theme_dir']; |
||
441 | |||
442 | if (empty($explicit_images) && !empty($context['to_install']['base_theme_url'])) |
||
443 | $context['to_install']['theme_url'] = $context['to_install']['base_theme_url']; |
||
444 | } |
||
445 | |||
446 | // Nope, sorry, couldn't find any theme already installed. |
||
447 | else |
||
448 | fatal_lang_error('package_get_error_theme_no_based_on_found', false, $context['to_install']['based_on']); |
||
449 | } |
||
450 | |||
451 | unset($context['to_install']['based_on']); |
||
452 | } |
||
453 | |||
454 | // Find the newest id_theme. |
||
455 | $result = $smcFunc['db_query']('', ' |
||
456 | SELECT MAX(id_theme) |
||
457 | FROM {db_prefix}themes', |
||
458 | array( |
||
459 | ) |
||
460 | ); |
||
461 | list ($id_theme) = $smcFunc['db_fetch_row']($result); |
||
462 | $smcFunc['db_free_result']($result); |
||
463 | |||
464 | // This will be theme number... |
||
465 | $id_theme++; |
||
466 | |||
467 | // Last minute changes? although, the actual array is a context value you might want to use the new ID. |
||
468 | call_integration_hook('integrate_theme_install', array(&$context['to_install'], $id_theme)); |
||
469 | |||
470 | $inserts = array(); |
||
471 | foreach ($context['to_install'] as $var => $val) |
||
472 | $inserts[] = array($id_theme, $var, $val); |
||
473 | |||
474 | if (!empty($inserts)) |
||
475 | $smcFunc['db_insert']('insert', |
||
476 | '{db_prefix}themes', |
||
477 | array('id_theme' => 'int', 'variable' => 'string-255', 'value' => 'string-65534'), |
||
478 | $inserts, |
||
479 | array('id_theme', 'variable') |
||
480 | ); |
||
481 | |||
482 | // Update the known and enable Theme's settings. |
||
483 | $known = strtr($modSettings['knownThemes'] . ',' . $id_theme, array(',,' => ',')); |
||
484 | $enable = strtr($modSettings['enableThemes'] . ',' . $id_theme, array(',,' => ',')); |
||
485 | updateSettings(array('knownThemes' => $known, 'enableThemes' => $enable)); |
||
486 | |||
487 | return $id_theme; |
||
488 | } |
||
489 | |||
490 | /** |
||
491 | * Removes a directory from the themes dir. |
||
492 | * |
||
493 | * This is a recursive function, it will call itself if there are subdirs inside the main directory. |
||
494 | * |
||
495 | * @param string $path The absolute path to the directory to be removed |
||
496 | * @return bool true when success, false on error. |
||
497 | */ |
||
498 | function remove_dir($path) |
||
499 | { |
||
500 | if (empty($path)) |
||
501 | return false; |
||
502 | |||
503 | if (is_dir($path)) |
||
504 | { |
||
505 | $objects = scandir($path); |
||
506 | |||
507 | foreach ($objects as $object) |
||
508 | if ($object != '.' && $object != '..') |
||
509 | { |
||
510 | if (filetype($path . '/' . $object) == 'dir') |
||
511 | remove_dir($path . '/' . $object); |
||
512 | |||
513 | else |
||
514 | unlink($path . '/' . $object); |
||
515 | } |
||
516 | } |
||
517 | |||
518 | reset($objects); |
||
519 | rmdir($path); |
||
520 | } |
||
521 | |||
522 | /** |
||
523 | * Removes a theme from the DB, includes all possible places where the theme might be used. |
||
524 | * |
||
525 | * @param int $themeID The theme ID |
||
526 | * @return bool true when success, false on error. |
||
527 | */ |
||
528 | function remove_theme($themeID) |
||
529 | { |
||
530 | global $smcFunc, $modSettings; |
||
531 | |||
532 | // Can't delete the default theme, sorry! |
||
533 | if (empty($themeID) || $themeID == 1) |
||
534 | return false; |
||
535 | |||
536 | $known = explode(',', $modSettings['knownThemes']); |
||
537 | $enable = explode(',', $modSettings['enableThemes']); |
||
538 | |||
539 | // Remove it from the themes table. |
||
540 | $smcFunc['db_query']('', ' |
||
541 | DELETE FROM {db_prefix}themes |
||
542 | WHERE id_theme = {int:current_theme}', |
||
543 | array( |
||
544 | 'current_theme' => $themeID, |
||
545 | ) |
||
546 | ); |
||
547 | |||
548 | // Update users preferences. |
||
549 | $smcFunc['db_query']('', ' |
||
550 | UPDATE {db_prefix}members |
||
551 | SET id_theme = {int:default_theme} |
||
552 | WHERE id_theme = {int:current_theme}', |
||
553 | array( |
||
554 | 'default_theme' => 0, |
||
555 | 'current_theme' => $themeID, |
||
556 | ) |
||
557 | ); |
||
558 | |||
559 | // Some boards may have it as preferred theme. |
||
560 | $smcFunc['db_query']('', ' |
||
561 | UPDATE {db_prefix}boards |
||
562 | SET id_theme = {int:default_theme} |
||
563 | WHERE id_theme = {int:current_theme}', |
||
564 | array( |
||
565 | 'default_theme' => 0, |
||
566 | 'current_theme' => $themeID, |
||
567 | ) |
||
568 | ); |
||
569 | |||
570 | // Remove it from the list of known themes. |
||
571 | $known = array_diff($known, array($themeID)); |
||
572 | |||
573 | // And the enable list too. |
||
574 | $enable = array_diff($enable, array($themeID)); |
||
575 | |||
576 | // Back to good old comma separated string. |
||
577 | $known = strtr(implode(',', $known), array(',,' => ',')); |
||
578 | $enable = strtr(implode(',', $enable), array(',,' => ',')); |
||
579 | |||
580 | // Update the enableThemes list. |
||
581 | updateSettings(array('enableThemes' => $enable, 'knownThemes' => $known)); |
||
582 | |||
583 | // Fix it if the theme was the overall default theme. |
||
584 | if ($modSettings['theme_guests'] == $themeID) |
||
585 | updateSettings(array('theme_guests' => '1')); |
||
586 | |||
587 | return true; |
||
588 | } |
||
589 | |||
590 | /** |
||
591 | * Generates a file listing for a given directory |
||
592 | * |
||
593 | * @param string $path The full path to the directory |
||
594 | * @param string $relative The relative path (relative to the Themes directory) |
||
595 | * @return array An array of information about the files and directories found |
||
596 | */ |
||
597 | function get_file_listing($path, $relative) |
||
598 | { |
||
599 | global $scripturl, $txt, $context; |
||
600 | |||
601 | // Is it even a directory? |
||
602 | if (!is_dir($path)) |
||
603 | fatal_lang_error('error_invalid_dir', 'critical'); |
||
604 | |||
605 | $dir = dir($path); |
||
606 | $entries = array(); |
||
607 | while ($entry = $dir->read()) |
||
608 | $entries[] = $entry; |
||
609 | $dir->close(); |
||
610 | |||
611 | natcasesort($entries); |
||
612 | |||
613 | $listing1 = array(); |
||
614 | $listing2 = array(); |
||
615 | |||
616 | foreach ($entries as $entry) |
||
617 | { |
||
618 | // Skip all dot files, including .htaccess. |
||
619 | if (substr($entry, 0, 1) == '.' || $entry == 'CVS') |
||
620 | continue; |
||
621 | |||
622 | if (is_dir($path . '/' . $entry)) |
||
623 | $listing1[] = array( |
||
624 | 'filename' => $entry, |
||
625 | 'is_writable' => is_writable($path . '/' . $entry), |
||
626 | 'is_directory' => true, |
||
627 | 'is_template' => false, |
||
628 | 'is_image' => false, |
||
629 | 'is_editable' => false, |
||
630 | 'href' => $scripturl . '?action=admin;area=theme;th=' . $_GET['th'] . ';' . $context['session_var'] . '=' . $context['session_id'] . ';sa=edit;directory=' . $relative . $entry, |
||
631 | 'size' => '', |
||
632 | ); |
||
633 | else |
||
634 | { |
||
635 | $size = filesize($path . '/' . $entry); |
||
636 | if ($size > 2048 || $size == 1024) |
||
637 | $size = comma_format($size / 1024) . ' ' . $txt['themeadmin_edit_kilobytes']; |
||
638 | else |
||
639 | $size = comma_format($size) . ' ' . $txt['themeadmin_edit_bytes']; |
||
640 | |||
641 | $listing2[] = array( |
||
642 | 'filename' => $entry, |
||
643 | 'is_writable' => is_writable($path . '/' . $entry), |
||
644 | 'is_directory' => false, |
||
645 | 'is_template' => preg_match('~\.template\.php$~', $entry) != 0, |
||
646 | 'is_image' => preg_match('~\.(jpg|jpeg|gif|bmp|png)$~', $entry) != 0, |
||
647 | 'is_editable' => is_writable($path . '/' . $entry) && preg_match('~\.(php|pl|css|js|vbs|xml|xslt|txt|xsl|html|htm|shtm|shtml|asp|aspx|cgi|py)$~', $entry) != 0, |
||
648 | 'href' => $scripturl . '?action=admin;area=theme;th=' . $_GET['th'] . ';' . $context['session_var'] . '=' . $context['session_id'] . ';sa=edit;filename=' . $relative . $entry, |
||
649 | 'size' => $size, |
||
650 | 'last_modified' => timeformat(filemtime($path . '/' . $entry)), |
||
651 | ); |
||
652 | } |
||
653 | } |
||
654 | |||
655 | return array_merge($listing1, $listing2); |
||
656 | } |
||
657 | |||
658 | ?> |
This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.
Consider making the comparison explicit by using
empty(..)
or! empty(...)
instead.