diff --git a/src/main/java/run/halo/app/controller/content/api/OptionController.java b/src/main/java/run/halo/app/controller/content/api/OptionController.java index 7160a3f31..e5d1bcd8d 100644 --- a/src/main/java/run/halo/app/controller/content/api/OptionController.java +++ b/src/main/java/run/halo/app/controller/content/api/OptionController.java @@ -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); } } diff --git a/src/main/java/run/halo/app/listener/freemarker/FreemarkerConfigAwareListener.java b/src/main/java/run/halo/app/listener/freemarker/FreemarkerConfigAwareListener.java index 9c3777571..1f7131c1b 100644 --- a/src/main/java/run/halo/app/listener/freemarker/FreemarkerConfigAwareListener.java +++ b/src/main/java/run/halo/app/listener/freemarker/FreemarkerConfigAwareListener.java @@ -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, diff --git a/src/main/java/run/halo/app/service/ClientOptionService.java b/src/main/java/run/halo/app/service/ClientOptionService.java new file mode 100644 index 000000000..71cbb48c6 --- /dev/null +++ b/src/main/java/run/halo/app/service/ClientOptionService.java @@ -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(); +} diff --git a/src/main/java/run/halo/app/service/OptionProvideService.java b/src/main/java/run/halo/app/service/OptionProvideService.java new file mode 100644 index 000000000..7742fa817 --- /dev/null +++ b/src/main/java/run/halo/app/service/OptionProvideService.java @@ -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); + } +} diff --git a/src/main/java/run/halo/app/service/OptionService.java b/src/main/java/run/halo/app/service/OptionService.java index e099ff28a..72e6412a0 100755 --- a/src/main/java/run/halo/app/service/OptionService.java +++ b/src/main/java/run/halo/app/service/OptionService.java @@ -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. * diff --git a/src/main/java/run/halo/app/service/impl/ClientOptionServiceImpl.java b/src/main/java/run/halo/app/service/impl/ClientOptionServiceImpl.java new file mode 100644 index 000000000..101e691bd --- /dev/null +++ b/src/main/java/run/halo/app/service/impl/ClientOptionServiceImpl.java @@ -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(); + } +} diff --git a/src/main/java/run/halo/app/service/impl/OptionServiceImpl.java b/src/main/java/run/halo/app/service/impl/OptionServiceImpl.java index 681549fe8..ce6f2b1ba 100644 --- a/src/main/java/run/halo/app/service/impl/OptionServiceImpl.java +++ b/src/main/java/run/halo/app/service/impl/OptionServiceImpl.java @@ -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"); diff --git a/src/test/java/run/halo/app/service/impl/ClientOptionServiceImplTest.java b/src/test/java/run/halo/app/service/impl/ClientOptionServiceImplTest.java new file mode 100644 index 000000000..bf5f2a9cd --- /dev/null +++ b/src/test/java/run/halo/app/service/impl/ClientOptionServiceImplTest.java @@ -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)); + } +}