refactor: detach admin and client option configuration (#1445)

* separate admin and client option configuration

* resolve checkstyle error
pull/1469/head
Li 2021-08-23 11:51:44 +08:00 committed by GitHub
parent 8953a06b08
commit 71a2e5a52d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 729 additions and 585 deletions

View File

@ -1,7 +1,5 @@
package run.halo.app.controller.content.api;
import static java.util.stream.Collectors.toMap;
import io.swagger.annotations.ApiOperation;
import java.util.ArrayList;
import java.util.Arrays;
@ -18,8 +16,7 @@ import org.springframework.web.bind.annotation.RestController;
import run.halo.app.model.dto.OptionDTO;
import run.halo.app.model.properties.CommentProperties;
import run.halo.app.model.support.BaseResponse;
import run.halo.app.service.OptionService;
import run.halo.app.service.impl.OptionFilter;
import run.halo.app.service.ClientOptionService;
/**
* Content option controller.
@ -31,27 +28,16 @@ import run.halo.app.service.impl.OptionFilter;
@RequestMapping("/api/content/options")
public class OptionController {
private final OptionService optionService;
private final ClientOptionService optionService;
private final OptionFilter optionFilter;
public OptionController(OptionService optionService) {
this.optionService = optionService;
optionFilter = new OptionFilter(optionService);
public OptionController(ClientOptionService clientOptionService) {
this.optionService = clientOptionService;
}
@GetMapping("list_view")
@ApiOperation("Lists all options with list view")
public List<OptionDTO> listAll() {
var options = optionService.listDtos();
var optionMap = options.stream()
.collect(toMap(OptionDTO::getKey, option -> option));
var keys = options.stream()
.map(OptionDTO::getKey)
.collect(Collectors.toUnmodifiableSet());
return optionFilter.filter(keys).stream()
.map(optionMap::get)
.collect(Collectors.toUnmodifiableList());
return optionService.listDtos();
}
@GetMapping("map_view")
@ -62,28 +48,23 @@ public class OptionController {
@RequestParam(value = "keys", required = false) String keys) {
// handle for key list
if (!CollectionUtils.isEmpty(keyList)) {
return optionService.listOptions(optionFilter.filter(keyList));
return optionService.listOptions(keyList);
}
// handle for keys
if (StringUtils.hasText(keys)) {
var nameSet = Arrays.stream(keys.split(","))
.map(String::trim)
.collect(Collectors.toUnmodifiableSet());
var filteredNames = optionFilter.filter(nameSet);
return optionService.listOptions(filteredNames);
return optionService.listOptions(nameSet);
}
// list all
Map<String, Object> options = optionService.listOptions();
return optionFilter.filter(options.keySet()).stream()
.collect(toMap(optionName -> optionName, options::get));
return optionService.listOptions();
}
@GetMapping("keys/{key}")
@ApiOperation("Gets option value by option key")
public BaseResponse<Object> getBy(@PathVariable("key") String key) {
Object optionValue = optionFilter.filter(key)
.flatMap(k -> optionService.getByKey(key))
.orElse(null);
Object optionValue = optionService.getByKey(key).orElse(null);
return BaseResponse.ok(optionValue);
}
@ -95,7 +76,7 @@ public class OptionController {
keys.add(CommentProperties.GRAVATAR_DEFAULT.getValue());
keys.add(CommentProperties.CONTENT_PLACEHOLDER.getValue());
keys.add(CommentProperties.GRAVATAR_SOURCE.getValue());
return optionService.listOptions(optionFilter.filter(keys));
return optionService.listOptions(keys);
}
}

View File

@ -25,6 +25,7 @@ import run.halo.app.event.user.UserUpdatedEvent;
import run.halo.app.model.properties.BlogProperties;
import run.halo.app.model.properties.SeoProperties;
import run.halo.app.model.support.HaloConst;
import run.halo.app.service.ClientOptionService;
import run.halo.app.service.OptionService;
import run.halo.app.service.ThemeService;
import run.halo.app.service.ThemeSettingService;
@ -41,7 +42,7 @@ import run.halo.app.service.UserService;
@Component
public class FreemarkerConfigAwareListener {
private final OptionService optionService;
private final ClientOptionService optionService;
private final Configuration configuration;
@ -53,7 +54,7 @@ public class FreemarkerConfigAwareListener {
private final AbstractStringCacheStore cacheStore;
public FreemarkerConfigAwareListener(OptionService optionService,
public FreemarkerConfigAwareListener(ClientOptionService optionService,
Configuration configuration,
ThemeService themeService,
ThemeSettingService themeSettingService,

View File

@ -0,0 +1,14 @@
package run.halo.app.service;
/**
* User client option service.
*
* @author LIlGG
* @date 2021/8/2
*/
public interface ClientOptionService extends OptionProvideService {
/**
* Flushes all pending changes to the database.
*/
void flush();
}

View File

@ -0,0 +1,537 @@
package run.halo.app.service;
import com.qiniu.common.Zone;
import com.qiniu.storage.Region;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Optional;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.lang.NonNull;
import org.springframework.lang.Nullable;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;
import run.halo.app.exception.MissingPropertyException;
import run.halo.app.model.dto.OptionDTO;
import run.halo.app.model.dto.OptionSimpleDTO;
import run.halo.app.model.enums.PostPermalinkType;
import run.halo.app.model.enums.SheetPermalinkType;
import run.halo.app.model.enums.ValueEnum;
import run.halo.app.model.params.OptionQuery;
import run.halo.app.model.properties.BlogProperties;
import run.halo.app.model.properties.OtherProperties;
import run.halo.app.model.properties.PermalinkProperties;
import run.halo.app.model.properties.PropertyEnum;
import run.halo.app.model.properties.QiniuOssProperties;
import run.halo.app.model.properties.SeoProperties;
/**
* Option parameter provision service.
*
* @author LIlGG
* @date 2021/8/2
*/
public interface OptionProvideService {
/**
* Get all options.
*
* @return Map
*/
@NonNull
@Transactional
Map<String, Object> listOptions();
/**
* Lists options by key list.
*
* @param keys key list
* @return a map of option
*/
@NonNull
default Map<String, Object> listOptions(@Nullable Collection<String> keys) {
if (CollectionUtils.isEmpty(keys)) {
return Collections.emptyMap();
}
Map<String, Object> optionMap = listOptions();
Map<String, Object> result = new HashMap<>(keys.size());
keys.stream()
.filter(optionMap::containsKey)
.forEach(key -> result.put(key, optionMap.get(key)));
return result;
}
/**
* Lists all option dtos.
*
* @return a list of option dto
*/
@NonNull
default List<OptionDTO> listDtos() {
List<OptionDTO> result = new LinkedList<>();
listOptions().forEach((key, value) -> result.add(new OptionDTO(key, value)));
return result;
}
/**
* Pages option output dtos.
*
* @param pageable page info must not be null
* @param optionQuery optionQuery
* @return a page of option output dto
*/
Page<OptionSimpleDTO> pageDtosBy(@NonNull Pageable pageable, OptionQuery optionQuery);
/**
* Get option by key.
*
* @param key option key must not be blank
* @return option value or null
*/
@Nullable
default Object getByKeyOfNullable(@NonNull String key) {
return getByKey(key).orElse(null);
}
/**
* Gets option value of non null.
*
* @param key option key must not be null
* @return option value of non null
*/
@NonNull
default Object getByKeyOfNonNull(@NonNull String key) {
return getByKey(key).orElseThrow(
() -> new MissingPropertyException("You have to config " + key + " setting"));
}
/**
* Get option by key.
*
* @param key option key must not be blank
* @return an optional option value
*/
@NonNull
default Optional<Object> getByKey(@NonNull String key) {
Assert.hasText(key, "Option key must not be blank");
return Optional.ofNullable(listOptions().get(key));
}
/**
* Gets value by key.
*
* @param key key must not be null
* @param valueType value type must not be null
* @param <T> value type
* @return value
*/
@NonNull
default <T> Optional<T> getByKey(@NonNull String key, @NonNull Class<T> valueType) {
return getByKey(key).map(value -> PropertyEnum.convertTo(value.toString(), valueType));
}
/**
* Gets option value by blog property.
*
* @param property blog property must not be null
* @return an option value
*/
@Nullable
default Object getByPropertyOfNullable(@NonNull PropertyEnum property) {
return getByProperty(property).orElse(null);
}
/**
* Gets option value by blog property.
*
* @param property blog property
* @return an optiona value
* @throws MissingPropertyException throws when property value dismisses
*/
@NonNull
default Object getByPropertyOfNonNull(@NonNull PropertyEnum property) {
Assert.notNull(property, "Blog property must not be null");
return getByKeyOfNonNull(property.getValue());
}
/**
* Gets option value by blog property.
*
* @param property blog property must not be null
* @return an optional option value
*/
@NonNull
default Optional<Object> getByProperty(@NonNull PropertyEnum property) {
Assert.notNull(property, "Blog property must not be null");
return getByKey(property.getValue());
}
/**
* Gets property value by blog property.
*
* @param property blog property must not be null
* @param propertyType property type must not be null
* @param <T> property type
* @return property value
*/
default <T> Optional<T> getByProperty(@NonNull PropertyEnum property,
@NonNull Class<T> propertyType) {
return getByProperty(property)
.map(propertyValue -> PropertyEnum.convertTo(propertyValue.toString(), propertyType));
}
/**
* Gets property value by blog property.
*
* @param property blog property must not be null
* @param propertyType property type must not be null
* @param defaultValue default value
* @param <T> property type
* @return property value
*/
default <T> T getByPropertyOrDefault(@NonNull PropertyEnum property,
@NonNull Class<T> propertyType,
T defaultValue) {
Assert.notNull(property, "Blog property must not be null");
return getByProperty(property, propertyType).orElse(defaultValue);
}
/**
* Gets property value by blog property.
*
* Default value from property default value.
*
* @param property blog property must not be null
* @param propertyType property type must not be null
* @param <T> property type
* @return property value
*/
default <T> T getByPropertyOrDefault(@NonNull PropertyEnum property,
@NonNull Class<T> propertyType) {
return getByProperty(property, propertyType).orElse(property.defaultValue(propertyType));
}
/**
* Gets value by key.
*
* @param key key must not be null
* @param valueType value type must not be null
* @param defaultValue default value
* @param <T> property type
* @return value
*/
default <T> T getByKeyOrDefault(@NonNull String key, @NonNull Class<T> valueType,
T defaultValue) {
return getByKey(key, valueType).orElse(defaultValue);
}
/**
* Gets enum value by property.
*
* @param property property must not be blank
* @param valueType enum value type must not be null
* @param <T> enum value type
* @return an optional enum value
*/
@NonNull
default <T extends Enum<T>> Optional<T> getEnumByProperty(@NonNull PropertyEnum property,
@NonNull Class<T> valueType) {
return getByProperty(property)
.map(value -> PropertyEnum.convertToEnum(value.toString(), valueType));
}
/**
* Gets enum value by property.
*
* @param property property must not be blank
* @param valueType enum value type must not be null
* @param defaultValue default value
* @param <T> enum value type
* @return enum value
*/
@Nullable
default <T extends Enum<T>> T getEnumByPropertyOrDefault(@NonNull PropertyEnum property,
@NonNull Class<T> valueType, @Nullable T defaultValue) {
return getEnumByProperty(property, valueType).orElse(defaultValue);
}
/**
* Gets value enum by property.
*
* @param property property must not be blank
* @param valueType enum value type must not be null
* @param enumType enum type must not be null
* @param <V> enum value type
* @param <E> value enum type
* @return an optional value enum value
*/
@NonNull
default <V, E extends Enum<E> & ValueEnum<V>> Optional<E> getValueEnumByProperty(
@NonNull PropertyEnum property,
@NonNull Class<V> valueType, @NonNull Class<E> enumType) {
return getByProperty(property).map(value -> ValueEnum
.valueToEnum(enumType, PropertyEnum.convertTo(value.toString(), valueType)));
}
/**
* Gets value enum by property.
*
* @param property property must not be blank
* @param valueType enum value type must not be null
* @param enumType enum type must not be null
* @param defaultValue default value enum value
* @param <V> enum value type
* @param <E> value enum type
* @return value enum value or null if the default value is null
*/
@Nullable
default <V, E extends Enum<E> & ValueEnum<V>> E getValueEnumByPropertyOrDefault(
@NonNull PropertyEnum property,
@NonNull Class<V> valueType, @NonNull Class<E> enumType, @Nullable E defaultValue) {
return getValueEnumByProperty(property, valueType, enumType).orElse(defaultValue);
}
/**
* Gets post page size.
*
* @return page size
*/
int getPostPageSize();
/**
* Gets archives page size.
*
* @return page size
*/
int getArchivesPageSize();
/**
* Gets comment page size.
*
* @return page size
*/
int getCommentPageSize();
/**
* Gets rss page size.
*
* @return page size
*/
int getRssPageSize();
/**
* Get qi niu yun zone.
*
* @return qiniu zone
*/
@NonNull
@Deprecated
default Zone getQnYunZone() {
return getByProperty(QiniuOssProperties.OSS_ZONE).map(qiniuZone -> {
Zone zone;
switch (qiniuZone.toString()) {
case "z0":
zone = Zone.zone0();
break;
case "z1":
zone = Zone.zone1();
break;
case "z2":
zone = Zone.zone2();
break;
case "na0":
zone = Zone.zoneNa0();
break;
case "as0":
zone = Zone.zoneAs0();
break;
default:
// Default is detecting zone automatically
zone = Zone.autoZone();
}
return zone;
}).orElseGet(Zone::autoZone);
}
/**
* Get qiniu oss region.
*
* @return qiniu region
*/
@NonNull
Region getQiniuRegion();
/**
* Gets locale.
*
* @return locale user set or default locale
*/
@NonNull
Locale getLocale();
/**
* Gets blog base url. (Without /)
*
* @return blog base url (If blog url isn't present, current machine IP address will be default)
*/
@NonNull
String getBlogBaseUrl();
/**
* Gets blog title.
*
* @return blog title.
*/
@NonNull
default String getBlogTitle() {
return getByProperty(BlogProperties.BLOG_TITLE).orElse("").toString();
}
/**
* Gets global seo keywords.
*
* @return keywords
*/
default String getSeoKeywords() {
return getByProperty(SeoProperties.KEYWORDS).orElse("").toString();
}
/**
* Get global seo description.
*
* @return description
*/
default String getSeoDescription() {
return getByProperty(SeoProperties.DESCRIPTION).orElse("").toString();
}
/**
* Gets blog birthday.
*
* @return birthday timestamp
*/
long getBirthday();
/**
* Get post permalink type.
*
* @return PostPermalinkType
*/
default PostPermalinkType getPostPermalinkType() {
return getEnumByPropertyOrDefault(PermalinkProperties.POST_PERMALINK_TYPE,
PostPermalinkType.class, PostPermalinkType.DEFAULT);
}
/**
* Get sheet permalink type.
*
* @return SheetPermalinkType
*/
default SheetPermalinkType getSheetPermalinkType() {
return getEnumByPropertyOrDefault(PermalinkProperties.SHEET_PERMALINK_TYPE,
SheetPermalinkType.class, SheetPermalinkType.SECONDARY);
}
/**
* Get sheet custom prefix.
*
* @return sheet prefix.
*/
default String getSheetPrefix() {
return getByPropertyOrDefault(PermalinkProperties.SHEET_PREFIX, String.class,
PermalinkProperties.SHEET_PREFIX.defaultValue());
}
/**
* Get links page custom prefix.
*
* @return links page prefix.
*/
default String getLinksPrefix() {
return getByPropertyOrDefault(PermalinkProperties.LINKS_PREFIX, String.class,
PermalinkProperties.LINKS_PREFIX.defaultValue());
}
/**
* Get photos page custom prefix.
*
* @return photos page prefix.
*/
default String getPhotosPrefix() {
return getByPropertyOrDefault(PermalinkProperties.PHOTOS_PREFIX, String.class,
PermalinkProperties.PHOTOS_PREFIX.defaultValue());
}
/**
* Get journals page custom prefix.
*
* @return journals page prefix.
*/
default String getJournalsPrefix() {
return getByPropertyOrDefault(PermalinkProperties.JOURNALS_PREFIX, String.class,
PermalinkProperties.JOURNALS_PREFIX.defaultValue());
}
/**
* Get archives custom prefix.
*
* @return archives prefix.
*/
default String getArchivesPrefix() {
return getByPropertyOrDefault(PermalinkProperties.ARCHIVES_PREFIX, String.class,
PermalinkProperties.ARCHIVES_PREFIX.defaultValue());
}
/**
* Get categories custom prefix.
*
* @return categories prefix.
*/
default String getCategoriesPrefix() {
return getByPropertyOrDefault(PermalinkProperties.CATEGORIES_PREFIX, String.class,
PermalinkProperties.CATEGORIES_PREFIX.defaultValue());
}
/**
* Get tags custom prefix.
*
* @return tags prefix.
*/
default String getTagsPrefix() {
return getByPropertyOrDefault(PermalinkProperties.TAGS_PREFIX, String.class,
PermalinkProperties.TAGS_PREFIX.defaultValue());
}
/**
* Get custom path suffix.
*
* @return path suffix.
*/
default String getPathSuffix() {
return getByPropertyOrDefault(PermalinkProperties.PATH_SUFFIX, String.class,
PermalinkProperties.PATH_SUFFIX.defaultValue());
}
default Boolean isEnabledAbsolutePath() {
return getByPropertyOrDefault(OtherProperties.GLOBAL_ABSOLUTE_PATH_ENABLED, Boolean.class,
true);
}
}

View File

@ -1,26 +1,13 @@
package run.halo.app.service;
import com.qiniu.common.Zone;
import com.qiniu.storage.Region;
import java.util.Collection;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Optional;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.lang.NonNull;
import org.springframework.lang.Nullable;
import org.springframework.transaction.annotation.Transactional;
import run.halo.app.exception.MissingPropertyException;
import run.halo.app.model.dto.OptionDTO;
import run.halo.app.model.dto.OptionSimpleDTO;
import run.halo.app.model.entity.Option;
import run.halo.app.model.enums.PostPermalinkType;
import run.halo.app.model.enums.SheetPermalinkType;
import run.halo.app.model.enums.ValueEnum;
import run.halo.app.model.params.OptionParam;
import run.halo.app.model.params.OptionQuery;
import run.halo.app.model.properties.PropertyEnum;
import run.halo.app.service.base.CrudService;
@ -31,7 +18,7 @@ import run.halo.app.service.base.CrudService;
* @author ryanwang
* @date 2019-03-14
*/
public interface OptionService extends CrudService<Option, Integer> {
public interface OptionService extends CrudService<Option, Integer>, OptionProvideService {
int DEFAULT_POST_PAGE_SIZE = 10;
@ -91,41 +78,6 @@ public interface OptionService extends CrudService<Option, Integer> {
@Transactional
void saveProperties(@NonNull Map<? extends PropertyEnum, String> properties);
/**
* Get all options
*
* @return Map
*/
@NonNull
@Transactional
Map<String, Object> listOptions();
/**
* Lists options by key list.
*
* @param keys key list
* @return a map of option
*/
@NonNull
Map<String, Object> listOptions(@Nullable Collection<String> keys);
/**
* Lists all option dtos.
*
* @return a list of option dto
*/
@NonNull
List<OptionDTO> listDtos();
/**
* Pages option output dtos.
*
* @param pageable page info must not be null
* @param optionQuery optionQuery
* @return a page of option output dto
*/
Page<OptionSimpleDTO> pageDtosBy(@NonNull Pageable pageable, OptionQuery optionQuery);
/**
* Removes option permanently.
*
@ -135,340 +87,6 @@ public interface OptionService extends CrudService<Option, Integer> {
@NonNull
Option removePermanently(@NonNull Integer id);
/**
* Get option by key
*
* @param key option key must not be blank
* @return option value or null
*/
@Nullable
Object getByKeyOfNullable(@NonNull String key);
/**
* Gets option value of non null.
*
* @param key option key must not be null
* @return option value of non null
*/
@NonNull
Object getByKeyOfNonNull(@NonNull String key);
/**
* Get option by key
*
* @param key option key must not be blank
* @return an optional option value
*/
@NonNull
Optional<Object> getByKey(@NonNull String key);
/**
* Gets value by key.
*
* @param key key must not be null
* @param valueType value type must not be null
* @param <T> value type
* @return value
*/
@NonNull
<T> Optional<T> getByKey(@NonNull String key, @NonNull Class<T> valueType);
/**
* Gets option value by blog property.
*
* @param property blog property must not be null
* @return an option value
*/
@Nullable
Object getByPropertyOfNullable(@NonNull PropertyEnum property);
/**
* Gets option value by blog property.
*
* @param property blog property
* @return an optiona value
* @throws MissingPropertyException throws when property value dismisses
*/
@NonNull
Object getByPropertyOfNonNull(@NonNull PropertyEnum property);
/**
* Gets option value by blog property.
*
* @param property blog property must not be null
* @return an optional option value
*/
@NonNull
Optional<Object> getByProperty(@NonNull PropertyEnum property);
/**
* Gets property value by blog property.
*
* @param property blog property must not be null
* @param propertyType property type must not be null
* @param <T> property type
* @return property value
*/
<T> Optional<T> getByProperty(@NonNull PropertyEnum property, @NonNull Class<T> propertyType);
/**
* Gets property value by blog property.
*
* @param property blog property must not be null
* @param propertyType property type must not be null
* @param defaultValue default value
* @param <T> property type
* @return property value
*/
<T> T getByPropertyOrDefault(@NonNull PropertyEnum property, @NonNull Class<T> propertyType,
T defaultValue);
/**
* Gets property value by blog property.
*
* Default value from property default value.
*
* @param property blog property must not be null
* @param propertyType property type must not be null
* @param <T> property type
* @return property value
*/
<T> T getByPropertyOrDefault(@NonNull PropertyEnum property, @NonNull Class<T> propertyType);
/**
* Gets value by key.
*
* @param key key must not be null
* @param valueType value type must not be null
* @param defaultValue default value
* @param <T> property type
* @return value
*/
<T> T getByKeyOrDefault(@NonNull String key, @NonNull Class<T> valueType, T defaultValue);
/**
* Gets enum value by property.
*
* @param property property must not be blank
* @param valueType enum value type must not be null
* @param <T> enum value type
* @return an optional enum value
*/
@NonNull
<T extends Enum<T>> Optional<T> getEnumByProperty(@NonNull PropertyEnum property,
@NonNull Class<T> valueType);
/**
* Gets enum value by property.
*
* @param property property must not be blank
* @param valueType enum value type must not be null
* @param defaultValue default value
* @param <T> enum value type
* @return enum value
*/
@Nullable
<T extends Enum<T>> T getEnumByPropertyOrDefault(@NonNull PropertyEnum property,
@NonNull Class<T> valueType, @Nullable T defaultValue);
/**
* Gets value enum by property.
*
* @param property property must not be blank
* @param valueType enum value type must not be null
* @param enumType enum type must not be null
* @param <V> enum value type
* @param <E> value enum type
* @return an optional value enum value
*/
@NonNull
<V, E extends Enum<E> & ValueEnum<V>> Optional<E> getValueEnumByProperty(
@NonNull PropertyEnum property,
@NonNull Class<V> valueType, @NonNull Class<E> enumType);
/**
* Gets value enum by property.
*
* @param property property must not be blank
* @param valueType enum value type must not be null
* @param enumType enum type must not be null
* @param defaultValue default value enum value
* @param <V> enum value type
* @param <E> value enum type
* @return value enum value or null if the default value is null
*/
@Nullable
<V, E extends Enum<E> & ValueEnum<V>> E getValueEnumByPropertyOrDefault(
@NonNull PropertyEnum property,
@NonNull Class<V> valueType, @NonNull Class<E> enumType, @Nullable E defaultValue);
/**
* Gets post page size.
*
* @return page size
*/
int getPostPageSize();
/**
* Gets archives page size.
*
* @return page size
*/
int getArchivesPageSize();
/**
* Gets comment page size.
*
* @return page size
*/
int getCommentPageSize();
/**
* Gets rss page size.
*
* @return page size
*/
int getRssPageSize();
/**
* Get qi niu yun zone.
*
* @return qiniu zone
*/
@NonNull
@Deprecated
Zone getQnYunZone();
/**
* Get qiniu oss region.
*
* @return qiniu region
*/
@NonNull
Region getQiniuRegion();
/**
* Gets locale.
*
* @return locale user set or default locale
*/
@NonNull
Locale getLocale();
/**
* Gets blog base url. (Without /)
*
* @return blog base url (If blog url isn't present, current machine IP address will be default)
*/
@NonNull
String getBlogBaseUrl();
/**
* Gets blog title.
*
* @return blog title.
*/
@NonNull
String getBlogTitle();
/**
* Gets global seo keywords.
*
* @return keywords
*/
String getSeoKeywords();
/**
* Get global seo description.
*
* @return description
*/
String getSeoDescription();
/**
* Gets blog birthday.
*
* @return birthday timestamp
*/
long getBirthday();
/**
* Get post permalink type.
*
* @return PostPermalinkType
*/
PostPermalinkType getPostPermalinkType();
/**
* Get sheet permalink type.
*
* @return SheetPermalinkType
*/
SheetPermalinkType getSheetPermalinkType();
/**
* Get sheet custom prefix.
*
* @return sheet prefix.
*/
String getSheetPrefix();
/**
* Get links page custom prefix.
*
* @return links page prefix.
*/
String getLinksPrefix();
/**
* Get photos page custom prefix.
*
* @return photos page prefix.
*/
String getPhotosPrefix();
/**
* Get journals page custom prefix.
*
* @return journals page prefix.
*/
String getJournalsPrefix();
/**
* Get archives custom prefix.
*
* @return archives prefix.
*/
String getArchivesPrefix();
/**
* Get categories custom prefix.
*
* @return categories prefix.
*/
String getCategoriesPrefix();
/**
* Get tags custom prefix.
*
* @return tags prefix.
*/
String getTagsPrefix();
/**
* Get custom path suffix.
*
* @return path suffix.
*/
String getPathSuffix();
/**
* Is enabled absolute path.
*
* @return true or false.
*/
Boolean isEnabledAbsolutePath();
/**
* Converts to option output dto.
*

View File

@ -0,0 +1,93 @@
package run.halo.app.service.impl;
import static java.util.stream.Collectors.toMap;
import com.qiniu.storage.Region;
import java.util.Locale;
import java.util.Map;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import run.halo.app.model.dto.OptionSimpleDTO;
import run.halo.app.model.params.OptionQuery;
import run.halo.app.service.ClientOptionService;
import run.halo.app.service.OptionService;
/**
* The client only provides filtered data
*
* @author LIlGG
* @date 2021/8/2
*/
@Service
public class ClientOptionServiceImpl implements ClientOptionService {
private final OptionService optionService;
private final OptionFilter optionFilter;
ClientOptionServiceImpl(OptionService optionService) {
this.optionService = optionService;
this.optionFilter = new OptionFilter(optionService);
}
@Override
@Transactional
public Map<String, Object> listOptions() {
Map<String, Object> options = optionService.listOptions();
return optionFilter.filter(options.keySet()).parallelStream()
.collect(toMap(optionName -> optionName, options::get));
}
@Override
public Page<OptionSimpleDTO> pageDtosBy(Pageable pageable, OptionQuery optionQuery) {
return optionService.pageDtosBy(pageable, optionQuery);
}
@Override
public int getPostPageSize() {
return optionService.getPostPageSize();
}
@Override
public int getArchivesPageSize() {
return optionService.getArchivesPageSize();
}
@Override
public int getCommentPageSize() {
return optionService.getCommentPageSize();
}
@Override
public int getRssPageSize() {
return optionService.getRssPageSize();
}
@Override
public Region getQiniuRegion() {
return optionService.getQiniuRegion();
}
@Override
public Locale getLocale() {
return optionService.getLocale();
}
@Override
public String getBlogBaseUrl() {
return optionService.getBlogBaseUrl();
}
@Override
public long getBirthday() {
return optionService.getBirthday();
}
@Override
public void flush() {
optionService.flush();
}
}

View File

@ -228,32 +228,6 @@ public class OptionServiceImpl extends AbstractCrudService<Option, Integer>
});
}
@Override
public Map<String, Object> listOptions(Collection<String> keys) {
if (CollectionUtils.isEmpty(keys)) {
return Collections.emptyMap();
}
Map<String, Object> optionMap = listOptions();
Map<String, Object> result = new HashMap<>(keys.size());
keys.stream()
.filter(optionMap::containsKey)
.forEach(key -> result.put(key, optionMap.get(key)));
return result;
}
@Override
public List<OptionDTO> listDtos() {
List<OptionDTO> result = new LinkedList<>();
listOptions().forEach((key, value) -> result.add(new OptionDTO(key, value)));
return result;
}
@Override
public Page<OptionSimpleDTO> pageDtosBy(Pageable pageable, OptionQuery optionQuery) {
Assert.notNull(pageable, "Page info must not be null");
@ -297,100 +271,6 @@ public class OptionServiceImpl extends AbstractCrudService<Option, Integer>
};
}
@Override
public Object getByKeyOfNullable(String key) {
return getByKey(key).orElse(null);
}
@Override
public Object getByKeyOfNonNull(String key) {
return getByKey(key).orElseThrow(
() -> new MissingPropertyException("You have to config " + key + " setting"));
}
@Override
public Optional<Object> getByKey(String key) {
Assert.hasText(key, "Option key must not be blank");
return Optional.ofNullable(listOptions().get(key));
}
@Override
public <T> Optional<T> getByKey(String key, Class<T> valueType) {
return getByKey(key).map(value -> PropertyEnum.convertTo(value.toString(), valueType));
}
@Override
public Object getByPropertyOfNullable(PropertyEnum property) {
return getByProperty(property).orElse(null);
}
@Override
public Object getByPropertyOfNonNull(PropertyEnum property) {
Assert.notNull(property, "Blog property must not be null");
return getByKeyOfNonNull(property.getValue());
}
@Override
public Optional<Object> getByProperty(PropertyEnum property) {
Assert.notNull(property, "Blog property must not be null");
return getByKey(property.getValue());
}
@Override
public <T> Optional<T> getByProperty(PropertyEnum property, Class<T> propertyType) {
return getByProperty(property)
.map(propertyValue -> PropertyEnum.convertTo(propertyValue.toString(), propertyType));
}
@Override
public <T> T getByPropertyOrDefault(PropertyEnum property, Class<T> propertyType,
T defaultValue) {
Assert.notNull(property, "Blog property must not be null");
return getByProperty(property, propertyType).orElse(defaultValue);
}
@Override
public <T> T getByPropertyOrDefault(PropertyEnum property, Class<T> propertyType) {
return getByProperty(property, propertyType).orElse(property.defaultValue(propertyType));
}
@Override
public <T> T getByKeyOrDefault(String key, Class<T> valueType, T defaultValue) {
return getByKey(key, valueType).orElse(defaultValue);
}
@Override
public <T extends Enum<T>> Optional<T> getEnumByProperty(PropertyEnum property,
Class<T> valueType) {
return getByProperty(property)
.map(value -> PropertyEnum.convertToEnum(value.toString(), valueType));
}
@Override
public <T extends Enum<T>> T getEnumByPropertyOrDefault(PropertyEnum property,
Class<T> valueType, T defaultValue) {
return getEnumByProperty(property, valueType).orElse(defaultValue);
}
@Override
public <V, E extends Enum<E> & ValueEnum<V>> Optional<E> getValueEnumByProperty(
PropertyEnum property,
Class<V> valueType, Class<E> enumType) {
return getByProperty(property).map(value -> ValueEnum
.valueToEnum(enumType, PropertyEnum.convertTo(value.toString(), valueType)));
}
@Override
public <V, E extends Enum<E> & ValueEnum<V>> E getValueEnumByPropertyOrDefault(
PropertyEnum property,
Class<V> valueType, Class<E> enumType, E defaultValue) {
return getValueEnumByProperty(property, valueType, enumType).orElse(defaultValue);
}
@Override
public int getPostPageSize() {
try {
@ -438,36 +318,6 @@ public class OptionServiceImpl extends AbstractCrudService<Option, Integer>
}
}
@Override
public Zone getQnYunZone() {
return getByProperty(QiniuOssProperties.OSS_ZONE).map(qiniuZone -> {
Zone zone;
switch (qiniuZone.toString()) {
case "z0":
zone = Zone.zone0();
break;
case "z1":
zone = Zone.zone1();
break;
case "z2":
zone = Zone.zone2();
break;
case "na0":
zone = Zone.zoneNa0();
break;
case "as0":
zone = Zone.zoneAs0();
break;
default:
// Default is detecting zone automatically
zone = Zone.autoZone();
}
return zone;
}).orElseGet(Zone::autoZone);
}
@Override
public Region getQiniuRegion() {
return getByProperty(QiniuOssProperties.OSS_ZONE).map(qiniuZone -> {
@ -525,21 +375,6 @@ public class OptionServiceImpl extends AbstractCrudService<Option, Integer>
return blogUrl;
}
@Override
public String getBlogTitle() {
return getByProperty(BlogProperties.BLOG_TITLE).orElse("").toString();
}
@Override
public String getSeoKeywords() {
return getByProperty(SeoProperties.KEYWORDS).orElse("").toString();
}
@Override
public String getSeoDescription() {
return getByProperty(SeoProperties.DESCRIPTION).orElse("").toString();
}
@Override
public long getBirthday() {
return getByProperty(PrimaryProperties.BIRTHDAY, Long.class).orElseGet(() -> {
@ -609,12 +444,6 @@ public class OptionServiceImpl extends AbstractCrudService<Option, Integer>
PermalinkProperties.PATH_SUFFIX.defaultValue());
}
@Override
public Boolean isEnabledAbsolutePath() {
return getByPropertyOrDefault(OtherProperties.GLOBAL_ABSOLUTE_PATH_ENABLED, Boolean.class,
true);
}
@Override
public OptionSimpleDTO convertToDto(Option option) {
Assert.notNull(option, "Option must not be null");

View File

@ -0,0 +1,71 @@
package run.halo.app.service.impl;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNull;
import static run.halo.app.service.OptionService.OPTIONS_KEY;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.ActiveProfiles;
import run.halo.app.cache.AbstractStringCacheStore;
import run.halo.app.model.properties.AliOssProperties;
import run.halo.app.model.properties.CommentProperties;
/**
* @author LIlGG
* @date 2021/8/2
*/
@SpringBootTest
@ActiveProfiles("test")
class ClientOptionServiceImplTest {
@Autowired
AbstractStringCacheStore cacheStore;
@Autowired
ClientOptionServiceImpl clientOptionService;
Map<String, Object> map = new HashMap<>();
{
map.put(AliOssProperties.OSS_DOMAIN.getValue(), "1");
map.put(CommentProperties.CONTENT_PLACEHOLDER.getValue(), "2");
map.put(CommentProperties.GRAVATAR_SOURCE.getValue(), "3");
}
@BeforeEach
void setUp() {
cacheStore.putAny(OPTIONS_KEY, map);
}
@Test
void listOptionsTest() {
Map<String, Object> options = clientOptionService.listOptions();
assertFalse(options.containsKey(AliOssProperties.OSS_DOMAIN.getValue()));
}
@Test
void listOptionsKeyTest() {
List<String> keys = new ArrayList<>();
keys.add(AliOssProperties.OSS_DOMAIN.getValue());
keys.add(CommentProperties.CONTENT_PLACEHOLDER.getValue());
keys.add(CommentProperties.GRAVATAR_SOURCE.getValue());
Map<String, Object> options = clientOptionService.listOptions(keys);
assertFalse(options.containsKey(AliOssProperties.OSS_DOMAIN.getValue()));
}
@Test
void getByKeyTest() {
assertNull(clientOptionService.getByKey(AliOssProperties.OSS_DOMAIN.getValue())
.orElse(null));
}
}