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)) |
||
0 ignored issues
–
show
Bug
introduced
by
![]() |
|||
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
The expression
$to_install of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.
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 ![]() |
|||
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. |
||
0 ignored issues
–
show
break is not strictly necessary here and could be removed.
The switch ($x) {
case 1:
return 'foo';
break; // This break is not necessary and can be left off.
}
If you would like to keep this construct to be consistent with other ![]() |
|||
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 | ?> |