Perfect theme configuration resolve

pull/146/head
johnniang 2019-04-10 12:48:21 +08:00
parent 901a6a0456
commit 4b486ae099
5 changed files with 94 additions and 19 deletions

View File

@ -0,0 +1,71 @@
package run.halo.app.handler.theme;
import org.springframework.lang.NonNull;
import org.springframework.lang.Nullable;
import org.springframework.stereotype.Component;
import run.halo.app.handler.theme.impl.YamlThemeConfigResolverImpl;
import java.io.IOException;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
/**
* Theme configuration resolver manager.
*
* @author johnniang
* @date 4/10/19
*/
@Component
public class ThemeConfigResolvers {
private final Map<ConfigType, ThemeConfigResolver> resolverMap = new ConcurrentHashMap<>(2);
public ThemeConfigResolvers() {
resolverMap.put(ConfigType.YAML, new YamlThemeConfigResolverImpl());
// TODO Add another theme config resolver
}
/**
* Config type enum.
*/
public enum ConfigType {
YAML,
PROPERTY
}
/**
* Resolves the content.
*
* @param content content must not be blank
* @param type config type
* @return a list of group
* @throws IOException throws when content conversion fails
*/
public List<Group> resolve(@NonNull String content, @Nullable ConfigType type) throws IOException {
ThemeConfigResolver resolver = getResolver(type);
if (resolver == null) {
throw new UnsupportedOperationException("Unsupported theme config type: " + type);
}
return resolver.resolve(content);
}
/**
* Resolves the content.
*
* @param content content must not be blank
* @return a list of group
* @throws IOException throws when content conversion fails
*/
public List<Group> resolve(String content) throws IOException {
return resolve(content, ConfigType.YAML);
}
private ThemeConfigResolver getResolver(@Nullable ConfigType type) {
return type == null ? null : resolverMap.get(type);
}
}

View File

@ -3,7 +3,6 @@ package run.halo.app.handler.theme.impl;
import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.dataformat.yaml.YAMLFactory; import com.fasterxml.jackson.dataformat.yaml.YAMLFactory;
import org.springframework.lang.Nullable; import org.springframework.lang.Nullable;
import org.springframework.stereotype.Component;
import run.halo.app.handler.theme.Group; import run.halo.app.handler.theme.Group;
import run.halo.app.handler.theme.Item; import run.halo.app.handler.theme.Item;
import run.halo.app.handler.theme.Option; import run.halo.app.handler.theme.Option;
@ -23,7 +22,6 @@ import java.util.Map;
* @author johnniang * @author johnniang
* @date 4/10/19 * @date 4/10/19
*/ */
@Component
public class YamlThemeConfigResolverImpl implements ThemeConfigResolver { public class YamlThemeConfigResolverImpl implements ThemeConfigResolver {
private final ObjectMapper yamlMapper = new ObjectMapper(new YAMLFactory()); private final ObjectMapper yamlMapper = new ObjectMapper(new YAMLFactory());

View File

@ -2,6 +2,7 @@ package run.halo.app.service;
import org.springframework.lang.NonNull; import org.springframework.lang.NonNull;
import org.springframework.lang.Nullable; import org.springframework.lang.Nullable;
import run.halo.app.handler.theme.Group;
import run.halo.app.model.support.ThemeFile; import run.halo.app.model.support.ThemeFile;
import run.halo.app.model.support.ThemeProperty; import run.halo.app.model.support.ThemeProperty;
@ -164,10 +165,10 @@ public interface ThemeService {
* Fetches theme configuration. * Fetches theme configuration.
* *
* @param themeId must not be blank * @param themeId must not be blank
* @return theme configuration or null if not found * @return theme configuration
*/ */
@Nullable @NonNull
Object fetchConfig(@NonNull String themeId); List<Group> fetchConfig(@NonNull String themeId);
/** /**
* Renders a theme page. * Renders a theme page.

View File

@ -21,6 +21,8 @@ import run.halo.app.exception.BadRequestException;
import run.halo.app.exception.ForbiddenException; import run.halo.app.exception.ForbiddenException;
import run.halo.app.exception.NotFoundException; import run.halo.app.exception.NotFoundException;
import run.halo.app.exception.ServiceException; import run.halo.app.exception.ServiceException;
import run.halo.app.handler.theme.Group;
import run.halo.app.handler.theme.ThemeConfigResolvers;
import run.halo.app.model.properties.PrimaryProperties; import run.halo.app.model.properties.PrimaryProperties;
import run.halo.app.model.support.HaloConst; import run.halo.app.model.support.HaloConst;
import run.halo.app.model.support.ThemeFile; import run.halo.app.model.support.ThemeFile;
@ -60,22 +62,23 @@ public class ThemeServiceImpl implements ThemeService {
*/ */
private String activatedThemeId; private String activatedThemeId;
private final ObjectMapper yamlMapper;
private final OptionService optionService; private final OptionService optionService;
private final StringCacheStore cacheStore; private final StringCacheStore cacheStore;
private final Configuration configuration; private final Configuration configuration;
private final ThemeConfigResolvers resolvers;
public ThemeServiceImpl(HaloProperties haloProperties, public ThemeServiceImpl(HaloProperties haloProperties,
OptionService optionService, OptionService optionService,
StringCacheStore cacheStore, StringCacheStore cacheStore,
Configuration configuration) { Configuration configuration,
ThemeConfigResolvers resolvers) {
this.optionService = optionService; this.optionService = optionService;
this.cacheStore = cacheStore; this.cacheStore = cacheStore;
this.configuration = configuration; this.configuration = configuration;
yamlMapper = new ObjectMapper(new YAMLFactory()); this.resolvers = resolvers;
workDir = Paths.get(haloProperties.getWorkDir(), THEME_FOLDER); workDir = Paths.get(haloProperties.getWorkDir(), THEME_FOLDER);
} }
@ -224,15 +227,15 @@ public class ThemeServiceImpl implements ThemeService {
} }
@Override @Override
public Object fetchConfig(String themeId) { public List<Group> fetchConfig(String themeId) {
Assert.hasText(themeId, "Theme name must not be blank"); Assert.hasText(themeId, "Theme name must not be blank");
// Get theme property // Get theme property
ThemeProperty themeProperty = getThemeOfNonNullBy(themeId); ThemeProperty themeProperty = getThemeOfNonNullBy(themeId);
if (!themeProperty.isHasOptions()) { if (!themeProperty.isHasOptions()) {
// If this theme dose not has an option, then return null // If this theme dose not has an option, then return empty list
return null; return Collections.emptyList();
} }
try { try {
@ -247,14 +250,15 @@ public class ThemeServiceImpl implements ThemeService {
continue; continue;
} }
// Read the yaml file and return the object value // Read the yaml file
return yamlMapper.readValue(optionsPath.toFile(), Object.class); String optionContent = new String(Files.readAllBytes(optionsPath));
// Resolve it
return resolvers.resolve(optionContent);
} }
return null; return Collections.emptyList();
} catch (IOException e) { } catch (IOException e) {
log.error("Failed to read options.yaml", e); throw new ServiceException("Failed to read options file", e);
return null;
} }
} }

View File

@ -2,6 +2,7 @@ package run.halo.app.web.controller.admin.api;
import io.swagger.annotations.ApiOperation; import io.swagger.annotations.ApiOperation;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
import run.halo.app.handler.theme.Group;
import run.halo.app.model.support.BaseResponse; import run.halo.app.model.support.BaseResponse;
import run.halo.app.model.support.ThemeFile; import run.halo.app.model.support.ThemeFile;
import run.halo.app.model.support.ThemeProperty; import run.halo.app.model.support.ThemeProperty;
@ -97,8 +98,8 @@ public class ThemeController {
@GetMapping("{themeId}/configurations") @GetMapping("{themeId}/configurations")
@ApiOperation("Fetches theme configuration by theme id") @ApiOperation("Fetches theme configuration by theme id")
public BaseResponse<Object> fetchConfig(@PathVariable("themeId") String themeId) { public List<Group> fetchConfig(@PathVariable("themeId") String themeId) {
return BaseResponse.ok(themeService.fetchConfig(themeId)); return themeService.fetchConfig(themeId);
} }
@PostMapping("{themeId}/settings") @PostMapping("{themeId}/settings")