Commit bc29399f authored by Van's avatar Van

Merge remote-tracking branch 'origin/3.5.0-dev' into 3.5.0-dev

parents cc7c1990 38711218
......@@ -39,7 +39,6 @@ import org.b3log.solo.event.B3ArticleUpdater;
import org.b3log.solo.event.B3CommentSender;
import org.b3log.solo.event.PluginRefresher;
import org.b3log.solo.model.Option;
import org.b3log.solo.model.Skin;
import org.b3log.solo.processor.InitCheckHandler;
import org.b3log.solo.processor.PermalinkHandler;
import org.b3log.solo.processor.console.*;
......@@ -189,10 +188,9 @@ public final class SoloServletListener extends AbstractServletListener {
}
/**
* Loads preference.
* Loads skin.
* <p>
* Loads preference from repository, loads skins from skin directory then sets it into preference if the skins
* changed.
* Loads skin from repository, loads skins from skin directory then sets it into preference if the skins changed.
* </p>
*/
private void loadPreference() {
......@@ -201,15 +199,15 @@ public final class SoloServletListener extends AbstractServletListener {
LOGGER.debug("Loading preference....");
final OptionQueryService optionQueryService = beanManager.getReference(OptionQueryService.class);
JSONObject preference;
JSONObject skin;
try {
preference = optionQueryService.getPreference();
if (null == preference) {
skin = optionQueryService.getSkin();
if (null == skin) {
return;
}
final PreferenceMgmtService preferenceMgmtService = beanManager.getReference(PreferenceMgmtService.class);
preferenceMgmtService.loadSkins(preference);
final SkinMgmtService skinMgmtService = beanManager.getReference(SkinMgmtService.class);
skinMgmtService.loadSkins(skin);
} catch (final Exception e) {
LOGGER.log(Level.ERROR, e.getMessage(), e);
......@@ -256,25 +254,22 @@ public final class SoloServletListener extends AbstractServletListener {
private void resolveSkinDir(final HttpServletRequest httpServletRequest) {
String skin = Skins.getSkinDirNameFromCookie(httpServletRequest);
if (StringUtils.isBlank(skin)) {
try {
final InitService initService = beanManager.getReference(InitService.class);
if (initService.isInited()) {
final OptionQueryService optionQueryService = beanManager.getReference(OptionQueryService.class);
final JSONObject preference = optionQueryService.getPreference();
if (null != preference) {
skin = preference.getString(Skin.SKIN_DIR_NAME);
}
final OptionQueryService optionQueryService = beanManager.getReference(OptionQueryService.class);
final JSONObject skinOpt = optionQueryService.getSkin();
if (Solos.isMobile(httpServletRequest)) {
if (null != skinOpt) {
skin = skinOpt.optString(Option.ID_C_MOBILE_SKIN_DIR_NAME);
} else {
skin = Option.DefaultPreference.DEFAULT_MOBILE_SKIN_DIR_NAME;
}
} else {
if (null != skinOpt) {
skin = skinOpt.optString(Option.ID_C_SKIN_DIR_NAME);
} else {
skin = Option.DefaultPreference.DEFAULT_SKIN_DIR_NAME;
}
} catch (final Exception e) {
LOGGER.log(Level.ERROR, "Resolves skin failed", e);
}
}
if (StringUtils.isBlank(skin)) {
skin = Option.DefaultPreference.DEFAULT_SKIN_DIR_NAME;
}
if (Solos.isMobile(httpServletRequest)) {
skin = Solos.MOBILE_SKIN;
}
httpServletRequest.setAttribute(Keys.TEMAPLTE_DIR_NAME, skin);
}
......@@ -399,6 +394,10 @@ public final class SoloServletListener extends AbstractServletListener {
DispatcherServlet.get("/console/preference/", preferenceConsole::getPreference);
DispatcherServlet.put("/console/preference/", preferenceConsole::updatePreference);
final SkinConsole skinConsole = beanManager.getReference(SkinConsole.class);
DispatcherServlet.get("/console/skin", skinConsole::getSkin);
DispatcherServlet.put("/console/skin", skinConsole::updateSkin);
final RepairConsole repairConsole = beanManager.getReference(RepairConsole.class);
DispatcherServlet.get("/fix/restore-signs", repairConsole::restoreSigns);
......
......@@ -26,7 +26,7 @@ import org.json.JSONObject;
*
* @author <a href="http://88250.b3log.org">Liang Ding</a>
* @author <a href="https://github.com/hzchendou">hzchendou</a>
* @version 1.5.0.6, Mar 20, 2019
* @version 1.6.0.0, Mar 29, 2019
* @since 0.6.0
*/
public final class Option {
......@@ -217,20 +217,15 @@ public final class Option {
*/
public static final String ID_C_FEED_OUTPUT_CNT = "feedOutputCnt";
/**
* Key of skins.
*/
public static final String ID_C_SKINS = "skins";
/**
* Key of skin dir name.
*/
public static final String ID_C_SKIN_DIR_NAME = "skinDirName";
/**
* Key of skin name.
* Key of mobile skin dir name.
*/
public static final String ID_C_SKIN_NAME = "skinName";
public static final String ID_C_MOBILE_SKIN_DIR_NAME = "mobileSkinDirName";
/**
* Key of footer content.
......@@ -273,6 +268,11 @@ public final class Option {
*/
public static final String CATEGORY_C_HACPAI = "hacpai";
/**
* Category - Skin.
*/
public static final String CATEGORY_C_SKIN = "skin";
//// Transient ////
/**
* Key of statistic blog published article count.
......@@ -359,6 +359,11 @@ public final class Option {
*/
public static final String DEFAULT_SKIN_DIR_NAME = "Pinghsu";
/**
* Default mobile skin directory name.
*/
public static final String DEFAULT_MOBILE_SKIN_DIR_NAME = "Pinghsu";
/**
* Default language.
*/
......
/*
* Solo - A small and beautiful blogging system written in Java.
* Copyright (c) 2010-2019, b3log.org & hacpai.com
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package org.b3log.solo.model;
/**
* This class defines all skin model relevant keys.
*
* @author <a href="http://88250.b3log.org">Liang Ding</a>
* @version 1.0.0.1, Aug 22, 2010
*/
public final class Skin {
/**
* Skin.
*/
public static final String SKIN = "skin";
/**
* Skins.
*/
public static final String SKINS = "skins";
/**
* Key of skin name, current selected skin name.
*/
public static final String SKIN_NAME = "skinName";
/**
* Key of skin directory name.
*/
public static final String SKIN_DIR_NAME = "skinDirName";
/**
* Private constructor.
*/
private Skin() {
}
}
......@@ -36,7 +36,6 @@ import org.b3log.latke.util.Paginator;
import org.b3log.solo.SoloServletListener;
import org.b3log.solo.model.Common;
import org.b3log.solo.model.Option;
import org.b3log.solo.model.Skin;
import org.b3log.solo.service.DataModelService;
import org.b3log.solo.service.InitService;
import org.b3log.solo.service.OptionQueryService;
......@@ -117,11 +116,14 @@ public class IndexProcessor {
// 前台皮肤切换 https://github.com/b3log/solo/issues/12060
String specifiedSkin = Skins.getSkinDirName(context);
if (StringUtils.isBlank(specifiedSkin)) {
specifiedSkin = preference.optString(Option.ID_C_SKIN_DIR_NAME);
final JSONObject skinOpt = optionQueryService.getSkin();
specifiedSkin = Solos.isMobile(request) ?
skinOpt.optString(Option.ID_C_MOBILE_SKIN_DIR_NAME) :
skinOpt.optString(Option.ID_C_SKIN_DIR_NAME);
}
request.setAttribute(Keys.TEMAPLTE_DIR_NAME, specifiedSkin);
final Cookie cookie = new Cookie(Skin.SKIN, specifiedSkin);
final Cookie cookie = new Cookie(Option.CATEGORY_C_SKIN, specifiedSkin);
cookie.setMaxAge(60 * 60); // 1 hour
cookie.setPath("/");
response.addCookie(cookie);
......
......@@ -42,7 +42,6 @@ import org.b3log.latke.util.Strings;
import org.b3log.solo.SoloServletListener;
import org.b3log.solo.model.Common;
import org.b3log.solo.model.Option;
import org.b3log.solo.model.Skin;
import org.b3log.solo.model.UserExt;
import org.b3log.solo.service.DataModelService;
import org.b3log.solo.service.ExportService;
......@@ -144,7 +143,8 @@ public class AdminConsole {
dataModel.put(Common.YEAR, String.valueOf(Calendar.getInstance().get(Calendar.YEAR)));
dataModel.put(Option.ID_C_ARTICLE_LIST_DISPLAY_COUNT, preference.getInt(Option.ID_C_ARTICLE_LIST_DISPLAY_COUNT));
dataModel.put(Option.ID_C_ARTICLE_LIST_PAGINATION_WINDOW_SIZE, preference.getInt(Option.ID_C_ARTICLE_LIST_PAGINATION_WINDOW_SIZE));
dataModel.put(Skin.SKIN_DIR_NAME, preference.getString(Skin.SKIN_DIR_NAME));
final JSONObject skin = optionQueryService.getSkin();
dataModel.put(Option.CATEGORY_C_SKIN, skin.optString(Option.OPTION_VALUE));
Keys.fillRuntime(dataModel);
dataModelService.fillMinified(dataModel);
// 使用 Marked 时代码高亮问题 https://github.com/b3log/solo/issues/12614
......
......@@ -29,16 +29,12 @@ import org.b3log.latke.servlet.annotation.RequestProcessor;
import org.b3log.latke.servlet.renderer.JsonRenderer;
import org.b3log.solo.model.Option;
import org.b3log.solo.model.Sign;
import org.b3log.solo.model.Skin;
import org.b3log.solo.service.OptionMgmtService;
import org.b3log.solo.service.OptionQueryService;
import org.b3log.solo.service.PreferenceMgmtService;
import org.json.JSONArray;
import org.json.JSONObject;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletResponse;
/**
* Preference console request processing.
*
......@@ -145,10 +141,8 @@ public class PreferenceConsole {
* "blogSubtitle": "",
* "localeString": "",
* "timeZoneId": "",
* "skinName": "",
* "skinDirName": "",
* "skins": "[{
* "skinName": "",
* "skinDirName": ""
* }, ....]",
* "noticeBoard": "",
......@@ -212,7 +206,6 @@ public class PreferenceConsole {
/**
* Updates the preference by the specified request.
* <p>
* <p>
* Request json:
* <pre>
* {
......@@ -228,7 +221,6 @@ public class PreferenceConsole {
* "randomArticlesDisplayCount": int,
* "blogTitle": "",
* "blogSubtitle": "",
* "skinDirName": "",
* "localeString": "",
* "timeZoneId": "",
* "noticeBoard": "",
......@@ -271,12 +263,6 @@ public class PreferenceConsole {
preferenceMgmtService.updatePreference(preference);
final HttpServletResponse response = context.getResponse();
final Cookie cookie = new Cookie(Skin.SKIN, preference.getString(Skin.SKIN_DIR_NAME));
cookie.setMaxAge(60 * 60); // 1 hour
cookie.setPath("/");
response.addCookie(cookie);
ret.put(Keys.STATUS_CODE, true);
ret.put(Keys.MSG, langPropsService.get("updateSuccLabel"));
} catch (final ServiceException e) {
......
......@@ -707,7 +707,7 @@ public class DataModelService {
final JSONObject admin = userRepository.getAdmin();
dataModel.put(Common.ADMIN_USER, admin);
final String skinDirName = (String) context.attr(Keys.TEMAPLTE_DIR_NAME);
dataModel.put(Skin.SKIN_DIR_NAME, skinDirName);
dataModel.put(Option.ID_C_SKIN_DIR_NAME, skinDirName);
Keys.fillRuntime(dataModel);
fillMinified(dataModel);
fillPageNavigations(dataModel);
......
......@@ -55,7 +55,7 @@ import java.util.Set;
* Solo initialization service.
*
* @author <a href="http://88250.b3log.org">Liang Ding</a>
* @version 1.5.2.31, Mar 23, 2019
* @version 1.5.2.32, Mar 29, 2019
* @since 0.4.0
*/
@Service
......@@ -226,7 +226,7 @@ public class InitService {
final Transaction transaction = userRepository.beginTransaction();
try {
initStatistic();
initPreference(requestJSONObject);
initOptions(requestJSONObject);
initAdmin(requestJSONObject);
initLink();
helloWorld();
......@@ -466,12 +466,12 @@ public class InitService {
}
/**
* Initializes preference.
* Initializes options.
*
* @param requestJSONObject the specified json object
* @throws Exception exception
*/
private void initPreference(final JSONObject requestJSONObject) throws Exception {
private void initOptions(final JSONObject requestJSONObject) throws Exception {
LOGGER.debug("Initializing preference....");
final JSONObject hljsThemeOpt = new JSONObject();
......@@ -660,36 +660,17 @@ public class InitService {
footerContentOpt.put(Option.OPTION_VALUE, DefaultPreference.DEFAULT_FOOTER_CONTENT);
optionRepository.add(footerContentOpt);
final String skinDirName = DefaultPreference.DEFAULT_SKIN_DIR_NAME;
final JSONObject skinDirNameOpt = new JSONObject();
skinDirNameOpt.put(Keys.OBJECT_ID, Option.ID_C_SKIN_DIR_NAME);
skinDirNameOpt.put(Option.OPTION_CATEGORY, Option.CATEGORY_C_PREFERENCE);
skinDirNameOpt.put(Option.OPTION_VALUE, skinDirName);
skinDirNameOpt.put(Option.OPTION_CATEGORY, Option.CATEGORY_C_SKIN);
skinDirNameOpt.put(Option.OPTION_VALUE, DefaultPreference.DEFAULT_SKIN_DIR_NAME);
optionRepository.add(skinDirNameOpt);
final String skinName = Latkes.getSkinName(skinDirName);
final JSONObject skinNameOpt = new JSONObject();
skinNameOpt.put(Keys.OBJECT_ID, Option.ID_C_SKIN_NAME);
skinNameOpt.put(Option.OPTION_CATEGORY, Option.CATEGORY_C_PREFERENCE);
skinNameOpt.put(Option.OPTION_VALUE, skinName);
optionRepository.add(skinNameOpt);
final Set<String> skinDirNames = Skins.getSkinDirNames();
final JSONArray skinArray = new JSONArray();
for (final String dirName : skinDirNames) {
final JSONObject skin = new JSONObject();
skinArray.put(skin);
final String name = Latkes.getSkinName(dirName);
skin.put(Skin.SKIN_NAME, name);
skin.put(Skin.SKIN_DIR_NAME, dirName);
}
final JSONObject skinsOpt = new JSONObject();
skinsOpt.put(Keys.OBJECT_ID, Option.ID_C_SKINS);
skinsOpt.put(Option.OPTION_CATEGORY, Option.CATEGORY_C_PREFERENCE);
skinsOpt.put(Option.OPTION_VALUE, skinArray.toString());
optionRepository.add(skinsOpt);
final JSONObject mobileSkinDirNameOpt = new JSONObject();
mobileSkinDirNameOpt.put(Keys.OBJECT_ID, Option.ID_C_MOBILE_SKIN_DIR_NAME);
mobileSkinDirNameOpt.put(Option.OPTION_CATEGORY, Option.CATEGORY_C_SKIN);
mobileSkinDirNameOpt.put(Option.OPTION_VALUE, DefaultPreference.DEFAULT_MOBILE_SKIN_DIR_NAME);
optionRepository.add(mobileSkinDirNameOpt);
LOGGER.info("Initialized preference");
}
......
......@@ -47,6 +47,29 @@ public class OptionQueryService {
@Inject
private OptionRepository optionRepository;
/**
* Gets the skin.
*
* @return skin, returns {@code null} if not found
*/
public JSONObject getSkin() {
try {
JSONObject ret = getOptions(Option.CATEGORY_C_SKIN);
if (null == ret) {
// TODO: 在 v3.5.0 发布后可移除判空
ret = new JSONObject().
put(Option.ID_C_SKIN_DIR_NAME, Option.DefaultPreference.DEFAULT_SKIN_DIR_NAME).
put(Option.ID_C_MOBILE_SKIN_DIR_NAME, Option.DefaultPreference.DEFAULT_MOBILE_SKIN_DIR_NAME);
}
return ret;
} catch (final Exception e) {
LOGGER.log(Level.ERROR, "Gets skin failed", e);
return null;
}
}
/**
* Gets the user preference.
*
......
......@@ -27,26 +27,18 @@ import org.b3log.latke.service.LangPropsService;
import org.b3log.latke.service.ServiceException;
import org.b3log.latke.service.annotation.Service;
import org.b3log.latke.util.Locales;
import org.b3log.latke.util.Stopwatchs;
import org.b3log.solo.model.Option;
import org.b3log.solo.model.Skin;
import org.b3log.solo.repository.OptionRepository;
import org.b3log.solo.util.Skins;
import org.json.JSONArray;
import org.json.JSONObject;
import java.util.Iterator;
import java.util.Locale;
import java.util.Set;
import static org.b3log.solo.model.Skin.*;
import static org.b3log.solo.util.Skins.getSkinDirNames;
/**
* Preference management service.
*
* @author <a href="http://88250.b3log.org">Liang Ding</a>
* @version 1.3.2.18, Feb 6, 2019
* @version 1.4.0.0, Mar 29, 2019
* @since 0.4.0
*/
@Service
......@@ -75,72 +67,6 @@ public class PreferenceMgmtService {
@Inject
private LangPropsService langPropsService;
/**
* Loads skins for the specified preference and initializes templates loading.
* <p>
* If the skins directory has been changed, persists the change into preference.
* </p>
*
* @param preference the specified preference
* @throws Exception exception
*/
public void loadSkins(final JSONObject preference) throws Exception {
Stopwatchs.start("Load Skins");
LOGGER.debug("Loading skins....");
final Set<String> skinDirNames = getSkinDirNames();
LOGGER.log(Level.DEBUG, "Loaded skins[dirNames={0}]", skinDirNames);
final JSONArray skinArray = new JSONArray();
for (final String dirName : skinDirNames) {
final JSONObject skin = new JSONObject();
final String name = Latkes.getSkinName(dirName);
if (null == name) {
LOGGER.log(Level.WARN, "The directory [{0}] does not contain any skin, ignored it", dirName);
continue;
}
skin.put(SKIN_NAME, name);
skin.put(SKIN_DIR_NAME, dirName);
skinArray.put(skin);
}
final String currentSkinDirName = preference.optString(SKIN_DIR_NAME);
final String skinName = preference.optString(SKIN_NAME);
LOGGER.log(Level.DEBUG, "Current skin[name={0}]", skinName);
if (!skinDirNames.contains(currentSkinDirName)) {
LOGGER.log(Level.WARN, "Configured skin [dirName={0}] can not find, try to use " + "default skin [dirName="
+ Option.DefaultPreference.DEFAULT_SKIN_DIR_NAME + "] instead.", currentSkinDirName);
if (!skinDirNames.contains(Option.DefaultPreference.DEFAULT_SKIN_DIR_NAME)) {
LOGGER.log(Level.ERROR, "Can not find default skin [dirName=" + Option.DefaultPreference.DEFAULT_SKIN_DIR_NAME
+ "], please redeploy your Solo and make sure contains the default skin. If you are using git, try to re-pull with 'git pull --recurse-submodules'");
System.exit(-1);
}
preference.put(SKIN_DIR_NAME, Option.DefaultPreference.DEFAULT_SKIN_DIR_NAME);
preference.put(SKIN_NAME, Latkes.getSkinName(Option.DefaultPreference.DEFAULT_SKIN_DIR_NAME));
updatePreference(preference);
}
final String skinsString = skinArray.toString();
if (!skinsString.equals(preference.getString(SKINS))) {
LOGGER.debug("The skins directory has been changed, persists the change into preference");
preference.put(SKINS, skinsString);
updatePreference(preference);
}
LOGGER.debug("Loaded skins....");
Stopwatchs.end();
}
/**
* Updates the preference with the specified preference.
*
......@@ -151,33 +77,14 @@ public class PreferenceMgmtService {
final Iterator<String> keys = preference.keys();
while (keys.hasNext()) {
final String key = keys.next();
if (preference.isNull(key)) {
throw new ServiceException("A value is null of preference[key=" + key + "]");
throw new ServiceException("A value is null of preference [key=" + key + "]");
}
}
final Transaction transaction = optionRepository.beginTransaction();
try {
final String skinDirName = preference.getString(Skin.SKIN_DIR_NAME);
final String skinName = Latkes.getSkinName(skinDirName);
preference.put(Skin.SKIN_NAME, skinName);
final Set<String> skinDirNames = Skins.getSkinDirNames();
final JSONArray skinArray = new JSONArray();
for (final String dirName : skinDirNames) {
final JSONObject skin = new JSONObject();
skinArray.put(skin);
final String name = Latkes.getSkinName(dirName);
skin.put(Skin.SKIN_NAME, name);
skin.put(Skin.SKIN_DIR_NAME, dirName);
}
preference.put(Skin.SKINS, skinArray.toString());
preference.put(Option.ID_C_SIGNS, preference.get(Option.ID_C_SIGNS).toString());
final JSONObject oldPreference = optionQueryService.getPreference();
......@@ -288,18 +195,6 @@ public class PreferenceMgmtService {
signsOpt.put(Option.OPTION_VALUE, preference.optString(Option.ID_C_SIGNS));
optionRepository.update(Option.ID_C_SIGNS, signsOpt);
final JSONObject skinDirNameOpt = optionRepository.get(Option.ID_C_SKIN_DIR_NAME);
skinDirNameOpt.put(Option.OPTION_VALUE, preference.optString(Option.ID_C_SKIN_DIR_NAME));
optionRepository.update(Option.ID_C_SKIN_DIR_NAME, skinDirNameOpt);
final JSONObject skinNameOpt = optionRepository.get(Option.ID_C_SKIN_NAME);
skinNameOpt.put(Option.OPTION_VALUE, preference.optString(Option.ID_C_SKIN_NAME));
optionRepository.update(Option.ID_C_SKIN_NAME, skinNameOpt);
final JSONObject skinsOpt = optionRepository.get(Option.ID_C_SKINS);
skinsOpt.put(Option.OPTION_VALUE, preference.optString(Option.ID_C_SKINS));
optionRepository.update(Option.ID_C_SKINS, skinsOpt);
final JSONObject timeZoneIdOpt = optionRepository.get(Option.ID_C_TIME_ZONE_ID);
timeZoneIdOpt.put(Option.OPTION_VALUE, preference.optString(Option.ID_C_TIME_ZONE_ID));
optionRepository.update(Option.ID_C_TIME_ZONE_ID, timeZoneIdOpt);
......
/*
* Solo - A small and beautiful blogging system written in Java.
* Copyright (c) 2010-2019, b3log.org & hacpai.com
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package org.b3log.solo.service;
import org.b3log.latke.Keys;
import org.b3log.latke.Latkes;
import org.b3log.latke.ioc.Inject;
import org.b3log.latke.logging.Level;
import org.b3log.latke.logging.Logger;
import org.b3log.latke.repository.Transaction;
import org.b3log.latke.service.LangPropsService;
import org.b3log.latke.service.ServiceException;
import org.b3log.latke.service.annotation.Service;
import org.b3log.latke.util.Stopwatchs;
import org.b3log.solo.model.Option;
import org.b3log.solo.repository.OptionRepository;
import org.b3log.solo.util.Skins;
import org.json.JSONArray;
import org.json.JSONObject;
import java.util.Set;
/**
* Skin management service.
*
* @author <a href="http://88250.b3log.org">Liang Ding</a>
* @version 1.0.0.0, Mar 29, 2019
* @since 3.5.0
*/
@Service
public class SkinMgmtService {
/**
* Logger.
*/
private static final Logger LOGGER = Logger.getLogger(SkinMgmtService.class);
/**
* Option query service.
*/
@Inject
private OptionQueryService optionQueryService;
/**
* Option repository.
*/
@Inject
private OptionRepository optionRepository;
/**
* Language service.
*/
@Inject
private LangPropsService langPropsService;
/**
* Loads skins.
*
* @param skin the specified skin
* @throws Exception exception
*/
public void loadSkins(final JSONObject skin) throws Exception {
final Set<String> skinDirNames = Skins.getSkinDirNames();
LOGGER.log(Level.DEBUG, "Loaded skins [dirNames={0}]", skinDirNames);
final JSONArray skinArray = new JSONArray();
for (final String dirName : skinDirNames) {
final JSONObject s = new JSONObject();
final String name = Latkes.getSkinName(dirName);
if (null == name) {
LOGGER.log(Level.WARN, "The directory [{0}] does not contain any skin, ignored it", dirName);
continue;
}
s.put(Option.ID_C_SKIN_DIR_NAME, dirName);
skinArray.put(s);
}
final String currentSkinDirName = skin.optString(Option.ID_C_SKIN_DIR_NAME);
if (!skinDirNames.contains(currentSkinDirName)) {
LOGGER.log(Level.WARN, "Configured skin [dirName={0}] can not find, try to use " + "default skin [dirName="
+ Option.DefaultPreference.DEFAULT_SKIN_DIR_NAME + "] instead.", currentSkinDirName);
if (!skinDirNames.contains(Option.DefaultPreference.DEFAULT_SKIN_DIR_NAME)) {
LOGGER.log(Level.ERROR, "Can not find default skin [dirName=" + Option.DefaultPreference.DEFAULT_SKIN_DIR_NAME
+ "], please redeploy your Solo and make sure contains the default skin. If you are using git, try to re-pull with 'git pull --recurse-submodules'");
System.exit(-1);
}
skin.put(Option.ID_C_SKIN_DIR_NAME, Option.DefaultPreference.DEFAULT_SKIN_DIR_NAME);
updateSkin(skin);
}
}
/**
* Updates the skin with the specified skin.
*
* @param skin the specified skin
* @throws ServiceException service exception
*/
public void updateSkin(final JSONObject skin) throws ServiceException {
final Transaction transaction = optionRepository.beginTransaction();
try {
final JSONObject skinDirNameOpt = optionRepository.get(Option.ID_C_SKIN_DIR_NAME);
skinDirNameOpt.put(Option.OPTION_VALUE, skin.optString(Option.ID_C_SKIN_DIR_NAME));
optionRepository.update(Option.ID_C_SKIN_DIR_NAME, skinDirNameOpt);
JSONObject mobileSkinDirNameOpt = optionRepository.get(Option.ID_C_MOBILE_SKIN_DIR_NAME);
// TODO: 在 v3.5.0 发布后可移除判空
if (null == mobileSkinDirNameOpt) {
mobileSkinDirNameOpt = new JSONObject();
mobileSkinDirNameOpt.put(Keys.OBJECT_ID, Option.ID_C_MOBILE_SKIN_DIR_NAME);
mobileSkinDirNameOpt.put(Option.OPTION_CATEGORY, Option.CATEGORY_C_SKIN);
mobileSkinDirNameOpt.put(Option.OPTION_VALUE, Option.DefaultPreference.DEFAULT_MOBILE_SKIN_DIR_NAME);
optionRepository.add(mobileSkinDirNameOpt);
} else {
mobileSkinDirNameOpt.put(Option.OPTION_VALUE, skin.optString(Option.ID_C_MOBILE_SKIN_DIR_NAME));
optionRepository.update(Option.ID_C_MOBILE_SKIN_DIR_NAME, mobileSkinDirNameOpt);
}
transaction.commit();
} catch (final Exception e) {
if (transaction.isActive()) {
transaction.rollback();
}
LOGGER.log(Level.ERROR, "Updates skin failed", e);
throw new ServiceException(langPropsService.get("updateFailLabel"));
}
}
}
......@@ -57,6 +57,15 @@ public final class V340_350 {
try {
final Transaction transaction = optionRepository.beginTransaction();
optionRepository.remove("skinName");
optionRepository.remove("skins");
final JSONObject skinOpt = optionRepository.get(Option.ID_C_SKIN_DIR_NAME);
skinOpt.put(Option.OPTION_CATEGORY, Option.CATEGORY_C_SKIN);
optionRepository.update(Option.ID_C_SKIN_DIR_NAME, skinOpt);
final JSONObject mobileSkinOpt = optionRepository.get(Option.ID_C_MOBILE_SKIN_DIR_NAME);
mobileSkinOpt.put(Option.OPTION_CATEGORY, Option.CATEGORY_C_SKIN);
optionRepository.update(Option.ID_C_SKIN_DIR_NAME, mobileSkinOpt);
JSONObject hljsThemeOpt = optionRepository.get(Option.ID_C_HLJS_THEME);
if (null == hljsThemeOpt) {
hljsThemeOpt = new JSONObject();
......
......@@ -33,7 +33,6 @@ import org.b3log.latke.util.Locales;
import org.b3log.latke.util.Stopwatchs;
import org.b3log.solo.SoloServletListener;
import org.b3log.solo.model.Option;
import org.b3log.solo.model.Skin;
import javax.servlet.ServletContext;
import javax.servlet.http.Cookie;
......@@ -48,7 +47,7 @@ import java.util.*;
* Skin utilities.
*
* @author <a href="http://88250.b3log.org">Liang Ding</a>
* @version 1.1.6.5, Feb 26, 2019
* @version 1.1.6.6, Mar 29, 2019
* @since 0.3.1
*/
public final class Skins {
......@@ -120,7 +119,7 @@ public final class Skins {
}
/**
* Fills the specified data model with the current skink's (WebRoot/skins/${skinName}/lang/lang_xx_XX.properties)
* Fills the specified data model with the current skin's (WebRoot/skins/${skinDirName}/lang/lang_xx_XX.properties)
* and core language (WebRoot/WEB-INF/classes/lang_xx_XX.properties) configurations.
*
* @param localeString the specified locale string
......@@ -218,12 +217,8 @@ public final class Skins {
* @return directory name, or {@code null} if not found
*/
public static String getSkinDirName(final RequestContext context) {
if (Solos.isMobile(context.getRequest())) {
return Solos.MOBILE_SKIN;
}
// 1. Get skin from query
final String specifiedSkin = context.param(Skin.SKIN);
final String specifiedSkin = context.param(Option.CATEGORY_C_SKIN);
if (StringUtils.isNotBlank(specifiedSkin)) {
final Set<String> skinDirNames = Skins.getSkinDirNames();
if (skinDirNames.contains(specifiedSkin)) {
......@@ -247,7 +242,7 @@ public final class Skins {
final Cookie[] cookies = request.getCookies();
if (null != cookies) {
for (final Cookie cookie : cookies) {
if (Skin.SKIN.equals(cookie.getName())) {
if (Option.CATEGORY_C_SKIN.equals(cookie.getName())) {
final String skin = cookie.getValue();
final Set<String> skinDirNames = Skins.getSkinDirNames();
......
......@@ -36,7 +36,6 @@ import org.b3log.latke.util.Strings;
import org.b3log.solo.SoloServletListener;
import org.b3log.solo.model.Article;
import org.b3log.solo.model.Common;
import org.b3log.solo.model.Option;
import org.b3log.solo.model.UserExt;
import org.b3log.solo.repository.UserRepository;
import org.json.JSONObject;
......@@ -54,7 +53,7 @@ import java.util.ResourceBundle;
* Solo utilities.
*
* @author <a href="http://88250.b3log.org">Liang Ding</a>
* @version 1.8.0.0, Mar 20, 2019
* @version 1.8.0.1, Mar 29, 2019
* @since 2.8.0
*/
public final class Solos {
......@@ -74,11 +73,6 @@ public final class Solos {
*/
public static final String GRAVATAR;
/**
* Mobile skin.
*/
public static final String MOBILE_SKIN;
/**
* Solo User-Agent.
*/
......@@ -114,13 +108,6 @@ public final class Solos {
FAVICON_API = solo.getString("faviconAPI");
GRAVATAR = solo.getString("gravatar");
String mobileSkin = Option.DefaultPreference.DEFAULT_SKIN_DIR_NAME;
try {
mobileSkin = solo.getString("mobile.skin");
} catch (final Exception e) {
LOGGER.log(Level.WARN, "Loads [mobile.skin] in solo.props failed [" + e.getMessage() + "], using [" + mobileSkin + "] as the default mobile skin");
}
MOBILE_SKIN = mobileSkin;
}
static {
......
......@@ -18,11 +18,9 @@
#
# Description: Solo configurations.
# Version: 2.4.0.5, Feb 28, 2019
# Version: 2.5.0.0, Mar 29, 2019
# Author: Liang Ding
#
mobile.skin=Pinghsu
gravatar=https://secure.gravatar.com/avatar/
faviconAPI=https://api.byi.pw/favicon?url=
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment