diff --git a/src/main/java/run/halo/app/Application.java b/src/main/java/run/halo/app/Application.java index 4735c15b8..6b7852598 100755 --- a/src/main/java/run/halo/app/Application.java +++ b/src/main/java/run/halo/app/Application.java @@ -33,6 +33,7 @@ public class Application extends SpringBootServletInitializer { // Run application context = SpringApplication.run(Application.class, args); + } /** diff --git a/src/main/java/run/halo/app/controller/admin/api/DataProcessController.java b/src/main/java/run/halo/app/controller/admin/api/DataProcessController.java new file mode 100644 index 000000000..fccf379c5 --- /dev/null +++ b/src/main/java/run/halo/app/controller/admin/api/DataProcessController.java @@ -0,0 +1,50 @@ +package run.halo.app.controller.admin.api; + +import io.swagger.annotations.ApiOperation; +import org.springframework.web.bind.annotation.*; +import run.halo.app.service.DataProcessService; +import run.halo.app.service.ThemeSettingService; + +/** + * @author ryanwang + * @date 2019-12-29 + */ +@RestController +@RequestMapping("/api/admin/data/process") +public class DataProcessController { + + private final DataProcessService dataProcessService; + + private final ThemeSettingService themeSettingService; + + public DataProcessController(DataProcessService dataProcessService, + ThemeSettingService themeSettingService) { + this.dataProcessService = dataProcessService; + this.themeSettingService = themeSettingService; + } + + @PutMapping("url/replace") + @ApiOperation("Replace url in all table.") + public void replaceUrl(@RequestParam("oldUrl") String oldUrl, + @RequestParam("newUrl") String newUrl) { + dataProcessService.replaceAllUrl(oldUrl, newUrl); + } + + @DeleteMapping("themes/settings/inactivated") + @ApiOperation("Delete inactivated theme settings.") + public void deleteInactivatedThemeSettings() { + themeSettingService.deleteInactivated(); + } + + @DeleteMapping("tags/unused") + @ApiOperation("Delete unused tags") + public void deleteUnusedTags() { + // TODO + } + + @DeleteMapping("categories/unused") + @ApiOperation("Delete unused categories") + public void deleteUnusedCategories() { + // TODO + } +} diff --git a/src/main/java/run/halo/app/controller/admin/api/StaticPageController.java b/src/main/java/run/halo/app/controller/admin/api/StaticPageController.java new file mode 100644 index 000000000..2a0b95a6f --- /dev/null +++ b/src/main/java/run/halo/app/controller/admin/api/StaticPageController.java @@ -0,0 +1,92 @@ +package run.halo.app.controller.admin.api; + +import cn.hutool.core.io.FileUtil; +import io.swagger.annotations.ApiOperation; +import org.springframework.http.HttpEntity; +import org.springframework.http.HttpHeaders; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.client.RestTemplate; +import run.halo.app.model.properties.NetlifyStaticDeployProperties; +import run.halo.app.model.support.StaticPageFile; +import run.halo.app.service.OptionService; +import run.halo.app.service.StaticPageService; + +import java.io.FileNotFoundException; +import java.nio.file.Path; +import java.util.Collections; +import java.util.List; + +/** + * Static page controller. + * + * @author ryanwang + * @date 2019-12-25 + */ +@RestController +@RequestMapping("/api/admin/static_page") +public class StaticPageController { + + private final static String DEPLOY_API = "https://api.netlify.com/api/v1/sites/%s/deploys"; + + private final OptionService optionService; + + private final RestTemplate httpsRestTemplate; + + private final StaticPageService staticPageService; + + public StaticPageController(StaticPageService staticPageService, + OptionService optionService, + RestTemplate httpsRestTemplate) { + this.staticPageService = staticPageService; + this.optionService = optionService; + this.httpsRestTemplate = httpsRestTemplate; + + MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter = new MappingJackson2HttpMessageConverter(); + mappingJackson2HttpMessageConverter.setSupportedMediaTypes(Collections.singletonList(MediaType.ALL)); + this.httpsRestTemplate.getMessageConverters().add(mappingJackson2HttpMessageConverter); + } + + @GetMapping + @ApiOperation("List static page files.") + public List list() { + return staticPageService.listFile(); + } + + @GetMapping("generate") + @ApiOperation("Generate static page files.") + public void generate() { + staticPageService.generate(); + } + + @PostMapping("deploy") + @ApiOperation("Deploy static page to remove platform") + public void deploy() { + staticPageService.deploy(); + } + + @GetMapping("netlify") + public void testNetlify() throws FileNotFoundException { + String domain = optionService.getByPropertyOfNonNull(NetlifyStaticDeployProperties.NETLIFY_DOMAIN).toString(); + String siteId = optionService.getByPropertyOfNonNull(NetlifyStaticDeployProperties.NETLIFY_SITE_ID).toString(); + String token = optionService.getByPropertyOfNonNull(NetlifyStaticDeployProperties.NETLIFY_TOKEN).toString(); + + HttpHeaders headers = new HttpHeaders(); + + headers.set("Content-Type", "application/zip"); + headers.set(HttpHeaders.AUTHORIZATION, "Bearer " + token); + + Path path = staticPageService.zipStaticPagesDirectory(); + + byte[] bytes = FileUtil.readBytes(path.toFile()); + + HttpEntity httpEntity = new HttpEntity<>(bytes, headers); + + ResponseEntity responseEntity = httpsRestTemplate.postForEntity(String.format(DEPLOY_API, siteId), httpEntity, Object.class); + } +} diff --git a/src/main/java/run/halo/app/handler/migrate/CnBlogsMigrateHandler.java b/src/main/java/run/halo/app/handler/migrate/CnBlogsMigrateHandler.java index bdd512d6d..55f4f6930 100644 --- a/src/main/java/run/halo/app/handler/migrate/CnBlogsMigrateHandler.java +++ b/src/main/java/run/halo/app/handler/migrate/CnBlogsMigrateHandler.java @@ -1,5 +1,7 @@ package run.halo.app.handler.migrate; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; import org.springframework.web.multipart.MultipartFile; import run.halo.app.model.enums.MigrateType; @@ -9,6 +11,8 @@ import run.halo.app.model.enums.MigrateType; * @author ryanwang * @date 2019-10-30 */ +@Slf4j +@Component public class CnBlogsMigrateHandler implements MigrateHandler { @Override diff --git a/src/main/java/run/halo/app/handler/migrate/MigrateHandlers.java b/src/main/java/run/halo/app/handler/migrate/MigrateHandlers.java index e7ac60f11..325c8fe92 100644 --- a/src/main/java/run/halo/app/handler/migrate/MigrateHandlers.java +++ b/src/main/java/run/halo/app/handler/migrate/MigrateHandlers.java @@ -31,7 +31,7 @@ public class MigrateHandlers { public MigrateHandlers(ApplicationContext applicationContext) { // Add all migrate handler - addFileHandlers(applicationContext.getBeansOfType(MigrateHandler.class).values()); + addMigrateHandlers(applicationContext.getBeansOfType(MigrateHandler.class).values()); } @NonNull @@ -56,7 +56,7 @@ public class MigrateHandlers { * @return current migrate handlers */ @NonNull - private MigrateHandlers addFileHandlers(@Nullable Collection migrateHandlers) { + private MigrateHandlers addMigrateHandlers(@Nullable Collection migrateHandlers) { if (!CollectionUtils.isEmpty(migrateHandlers)) { this.migrateHandlers.addAll(migrateHandlers); } diff --git a/src/main/java/run/halo/app/handler/staticdeploy/GitStaticDeployHandler.java b/src/main/java/run/halo/app/handler/staticdeploy/GitStaticDeployHandler.java new file mode 100644 index 000000000..0b94b0059 --- /dev/null +++ b/src/main/java/run/halo/app/handler/staticdeploy/GitStaticDeployHandler.java @@ -0,0 +1,33 @@ +package run.halo.app.handler.staticdeploy; + +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; +import run.halo.app.model.enums.StaticDeployType; +import run.halo.app.service.OptionService; + +/** + * Git deploy handler. + * + * @author ryanwang + * @date 2019-12-26 + */ +@Slf4j +@Component +public class GitStaticDeployHandler implements StaticDeployHandler { + + private final OptionService optionService; + + public GitStaticDeployHandler(OptionService optionService) { + this.optionService = optionService; + } + + @Override + public void deploy() { + + } + + @Override + public boolean supportType(StaticDeployType type) { + return StaticDeployType.GIT.equals(type); + } +} diff --git a/src/main/java/run/halo/app/handler/staticdeploy/NetlifyStaticDeployHandler.java b/src/main/java/run/halo/app/handler/staticdeploy/NetlifyStaticDeployHandler.java new file mode 100644 index 000000000..dddad86e1 --- /dev/null +++ b/src/main/java/run/halo/app/handler/staticdeploy/NetlifyStaticDeployHandler.java @@ -0,0 +1,67 @@ +package run.halo.app.handler.staticdeploy; + +import cn.hutool.core.io.FileUtil; +import lombok.extern.slf4j.Slf4j; +import org.springframework.http.HttpEntity; +import org.springframework.http.HttpHeaders; +import org.springframework.http.ResponseEntity; +import org.springframework.stereotype.Component; +import org.springframework.web.client.RestTemplate; +import run.halo.app.model.enums.StaticDeployType; +import run.halo.app.model.properties.NetlifyStaticDeployProperties; +import run.halo.app.service.OptionService; +import run.halo.app.service.StaticPageService; + +import java.nio.file.Path; + +/** + * Netlify deploy handler. + * + * @author ryanwang + * @date 2019-12-26 + */ +@Slf4j +@Component +public class NetlifyStaticDeployHandler implements StaticDeployHandler { + + private final static String DEPLOY_API = "https://api.netlify.com/api/v1/sites/%s/deploys"; + + private final OptionService optionService; + + private final RestTemplate httpsRestTemplate; + + private final StaticPageService staticPageService; + + public NetlifyStaticDeployHandler(OptionService optionService, + RestTemplate httpsRestTemplate, + StaticPageService staticPageService) { + this.optionService = optionService; + this.httpsRestTemplate = httpsRestTemplate; + this.staticPageService = staticPageService; + } + + @Override + public void deploy() { + String domain = optionService.getByPropertyOfNonNull(NetlifyStaticDeployProperties.NETLIFY_DOMAIN).toString(); + String siteId = optionService.getByPropertyOfNonNull(NetlifyStaticDeployProperties.NETLIFY_SITE_ID).toString(); + String token = optionService.getByPropertyOfNonNull(NetlifyStaticDeployProperties.NETLIFY_TOKEN).toString(); + + HttpHeaders headers = new HttpHeaders(); + + headers.set("Content-Type", "application/zip"); + headers.set(HttpHeaders.AUTHORIZATION, "Bearer " + token); + + Path path = staticPageService.zipStaticPagesDirectory(); + + byte[] bytes = FileUtil.readBytes(path.toFile()); + + HttpEntity httpEntity = new HttpEntity<>(bytes, headers); + + ResponseEntity responseEntity = httpsRestTemplate.postForEntity(String.format(DEPLOY_API, siteId), httpEntity, Object.class); + } + + @Override + public boolean supportType(StaticDeployType type) { + return StaticDeployType.NETLIFY.equals(type); + } +} diff --git a/src/main/java/run/halo/app/handler/staticdeploy/StaticDeployHandler.java b/src/main/java/run/halo/app/handler/staticdeploy/StaticDeployHandler.java new file mode 100644 index 000000000..f4da08737 --- /dev/null +++ b/src/main/java/run/halo/app/handler/staticdeploy/StaticDeployHandler.java @@ -0,0 +1,26 @@ +package run.halo.app.handler.staticdeploy; + +import org.springframework.lang.Nullable; +import run.halo.app.model.enums.StaticDeployType; + +/** + * Static deploy handler interface class. + * + * @author ryanwang + * @date 2019-12-26 + */ +public interface StaticDeployHandler { + + /** + * do deploy. + */ + void deploy(); + + /** + * Checks if the given type is supported. + * + * @param type deploy type + * @return true if supported; false or else + */ + boolean supportType(@Nullable StaticDeployType type); +} diff --git a/src/main/java/run/halo/app/handler/staticdeploy/StaticDeployHandlers.java b/src/main/java/run/halo/app/handler/staticdeploy/StaticDeployHandlers.java new file mode 100644 index 000000000..4a8b8138f --- /dev/null +++ b/src/main/java/run/halo/app/handler/staticdeploy/StaticDeployHandlers.java @@ -0,0 +1,65 @@ +package run.halo.app.handler.staticdeploy; + +import lombok.extern.slf4j.Slf4j; +import org.springframework.context.ApplicationContext; +import org.springframework.lang.NonNull; +import org.springframework.lang.Nullable; +import org.springframework.stereotype.Component; +import org.springframework.util.Assert; +import org.springframework.util.CollectionUtils; +import run.halo.app.exception.FileOperationException; +import run.halo.app.model.enums.StaticDeployType; + +import java.util.Collection; +import java.util.LinkedList; + +/** + * Static deploy handlers. + * + * @author ryanwang + * @date 2019-12-26 + */ +@Slf4j +@Component +public class StaticDeployHandlers { + + private final Collection staticDeployHandlers = new LinkedList<>(); + + public StaticDeployHandlers(ApplicationContext applicationContext) { + // Add all static deploy handler + addStaticDeployHandlers(applicationContext.getBeansOfType(StaticDeployHandler.class).values()); + } + + + /** + * do deploy. + * + * @param staticDeployType static deploy type + */ + public void deploy(@NonNull StaticDeployType staticDeployType) { + Assert.notNull(staticDeployType, "Static deploy type must not be null"); + + for (StaticDeployHandler staticDeployHandler : staticDeployHandlers) { + if (staticDeployHandler.supportType(staticDeployType)) { + staticDeployHandler.deploy(); + return; + } + } + + throw new FileOperationException("No available static deploy handler to deploy static pages").setErrorData(staticDeployType); + } + + /** + * Adds static deploy handlers. + * + * @param staticDeployHandlers static deploy handler collection + * @return current file handlers + */ + @NonNull + public StaticDeployHandlers addStaticDeployHandlers(@Nullable Collection staticDeployHandlers) { + if (!CollectionUtils.isEmpty(staticDeployHandlers)) { + this.staticDeployHandlers.addAll(staticDeployHandlers); + } + return this; + } +} diff --git a/src/main/java/run/halo/app/model/enums/StaticDeployType.java b/src/main/java/run/halo/app/model/enums/StaticDeployType.java new file mode 100644 index 000000000..4dcd9a50d --- /dev/null +++ b/src/main/java/run/halo/app/model/enums/StaticDeployType.java @@ -0,0 +1,36 @@ +package run.halo.app.model.enums; + +/** + * Static deploy type. + * + * @author ryanwang + * @date 2019-12-26 + */ +public enum StaticDeployType implements ValueEnum { + + /** + * Deploy static pages in remote git repository, such as github pages,gitee pages,coding pages.etc. + */ + GIT(0), + + /** + * Deploy static pages in netlify. + */ + NETLIFY(1); + + private Integer value; + + StaticDeployType(Integer value) { + this.value = value; + } + + /** + * Get enum value. + * + * @return enum value + */ + @Override + public Integer getValue() { + return value; + } +} diff --git a/src/main/java/run/halo/app/model/properties/GitStaticDeployProperties.java b/src/main/java/run/halo/app/model/properties/GitStaticDeployProperties.java new file mode 100644 index 000000000..e52bdc12a --- /dev/null +++ b/src/main/java/run/halo/app/model/properties/GitStaticDeployProperties.java @@ -0,0 +1,76 @@ +package run.halo.app.model.properties; + +/** + * Git static deploy properties. + * + * @author ryanwang + * @date 2019-12-26 + */ +public enum GitStaticDeployProperties implements PropertyEnum { + + /** + * Git static deploy domain. + */ + GIT_DOMAIN("git_static_deploy_domain", String.class, ""), + + /** + * Git static deploy repository. + */ + GIT_REPOSITORY("git_static_deploy_repository", String.class, ""), + + /** + * Git static deploy branch. + */ + GIT_BRANCH("git_static_deploy_branch", String.class, "master"), + + /** + * Git static deploy username. + */ + GIT_USERNAME("git_static_deploy_username", String.class, ""), + + /** + * Git static deploy email. + */ + GIT_EMAIL("git_static_deploy_email", String.class, ""), + + /** + * Git static deploy token. + */ + GIT_TOKEN("git_static_deploy_token", String.class, ""), + + /** + * Git static deploy cname. + */ + GIT_CNAME("git_static_deploy_cname", String.class, ""); + + private final String value; + + private final Class type; + + private final String defaultValue; + + GitStaticDeployProperties(String value, Class type, String defaultValue) { + this.defaultValue = defaultValue; + if (!PropertyEnum.isSupportedType(type)) { + throw new IllegalArgumentException("Unsupported blog property type: " + type); + } + + this.value = value; + this.type = type; + } + + @Override + public Class getType() { + return type; + } + + @Override + public String defaultValue() { + return defaultValue; + } + + @Override + public String getValue() { + return value; + } +} diff --git a/src/main/java/run/halo/app/model/properties/NetlifyStaticDeployProperties.java b/src/main/java/run/halo/app/model/properties/NetlifyStaticDeployProperties.java new file mode 100644 index 000000000..ac5574859 --- /dev/null +++ b/src/main/java/run/halo/app/model/properties/NetlifyStaticDeployProperties.java @@ -0,0 +1,56 @@ +package run.halo.app.model.properties; + +/** + * Netlify static deploy properties. + * + * @author ryanwang + * @date 2019-12-26 + */ +public enum NetlifyStaticDeployProperties implements PropertyEnum { + + /** + * Netlify static deploy domain. + */ + NETLIFY_DOMAIN("netlify_static_deploy_domain", String.class, ""), + + /** + * Netlify static deploy site id. + */ + NETLIFY_SITE_ID("netlify_static_deploy_site_id", String.class, ""), + + /** + * Netlify static deploy token. + */ + NETLIFY_TOKEN("netlify_static_deploy_token", String.class, ""); + + private final String value; + + private final Class type; + + private final String defaultValue; + + NetlifyStaticDeployProperties(String value, Class type, String defaultValue) { + this.defaultValue = defaultValue; + if (!PropertyEnum.isSupportedType(type)) { + throw new IllegalArgumentException("Unsupported blog property type: " + type); + } + + this.value = value; + this.type = type; + } + + @Override + public Class getType() { + return type; + } + + @Override + public String defaultValue() { + return defaultValue; + } + + @Override + public String getValue() { + return value; + } +} diff --git a/src/main/java/run/halo/app/model/properties/PropertyEnum.java b/src/main/java/run/halo/app/model/properties/PropertyEnum.java index 65a57290e..32e680ff1 100644 --- a/src/main/java/run/halo/app/model/properties/PropertyEnum.java +++ b/src/main/java/run/halo/app/model/properties/PropertyEnum.java @@ -155,6 +155,9 @@ public interface PropertyEnum extends ValueEnum { propertyEnumClasses.add(SeoProperties.class); propertyEnumClasses.add(UpOssProperties.class); propertyEnumClasses.add(ApiProperties.class); + propertyEnumClasses.add(StaticDeployProperties.class); + propertyEnumClasses.add(GitStaticDeployProperties.class); + propertyEnumClasses.add(NetlifyStaticDeployProperties.class); Map result = new HashMap<>(); diff --git a/src/main/java/run/halo/app/model/properties/StaticDeployProperties.java b/src/main/java/run/halo/app/model/properties/StaticDeployProperties.java new file mode 100644 index 000000000..f1222bed5 --- /dev/null +++ b/src/main/java/run/halo/app/model/properties/StaticDeployProperties.java @@ -0,0 +1,45 @@ +package run.halo.app.model.properties; + +import run.halo.app.model.enums.StaticDeployType; + +/** + * Static deploy properties. + * + * @author ryanwang + * @date 2019-12-26 + */ +public enum StaticDeployProperties implements PropertyEnum { + + /** + * static deploy type + */ + DEPLOY_TYPE("static_deploy_type", StaticDeployType.class, StaticDeployType.GIT.name()); + + private final String value; + + private final Class type; + + private final String defaultValue; + + + StaticDeployProperties(String value, Class type, String defaultValue) { + this.value = value; + this.type = type; + this.defaultValue = defaultValue; + } + + @Override + public Class getType() { + return type; + } + + @Override + public String defaultValue() { + return defaultValue; + } + + @Override + public String getValue() { + return value; + } +} diff --git a/src/main/java/run/halo/app/model/support/HaloConst.java b/src/main/java/run/halo/app/model/support/HaloConst.java index c4e34a704..d8f45327b 100644 --- a/src/main/java/run/halo/app/model/support/HaloConst.java +++ b/src/main/java/run/halo/app/model/support/HaloConst.java @@ -30,6 +30,11 @@ public class HaloConst { */ public final static String HALO_BACKUP_PREFIX = "halo-backup-"; + /** + * Static pages pack prefix. + */ + public final static String STATIC_PAGE_PACK_PREFIX = "static-pages-"; + /** * Default theme name. */ diff --git a/src/main/java/run/halo/app/model/support/StaticFile.java b/src/main/java/run/halo/app/model/support/StaticFile.java index e1de4146a..c7f05e693 100644 --- a/src/main/java/run/halo/app/model/support/StaticFile.java +++ b/src/main/java/run/halo/app/model/support/StaticFile.java @@ -16,6 +16,8 @@ import java.util.List; @ToString public class StaticFile implements Comparator { + private String id; + private String name; private String path; diff --git a/src/main/java/run/halo/app/model/support/StaticPageFile.java b/src/main/java/run/halo/app/model/support/StaticPageFile.java new file mode 100644 index 000000000..f92139d1a --- /dev/null +++ b/src/main/java/run/halo/app/model/support/StaticPageFile.java @@ -0,0 +1,37 @@ +package run.halo.app.model.support; + +import lombok.Data; + +import java.util.Comparator; +import java.util.List; + +/** + * Static page dto. + * + * @author ryanwang + * @date 2019-12-26 + */ +@Data +public class StaticPageFile implements Comparator { + + private String id; + + private String name; + + private Boolean isFile; + + private List children; + + @Override + public int compare(StaticPageFile leftFile, StaticPageFile rightFile) { + if (leftFile.isFile && !rightFile.isFile) { + return 1; + } + + if (!leftFile.isFile && rightFile.isFile) { + return -1; + } + + return leftFile.getName().compareTo(rightFile.getName()); + } +} diff --git a/src/main/java/run/halo/app/repository/ThemeSettingRepository.java b/src/main/java/run/halo/app/repository/ThemeSettingRepository.java index 8ea8b50e3..9a504c199 100644 --- a/src/main/java/run/halo/app/repository/ThemeSettingRepository.java +++ b/src/main/java/run/halo/app/repository/ThemeSettingRepository.java @@ -42,4 +42,11 @@ public interface ThemeSettingRepository extends BaseRepository findByThemeIdAndKey(@NonNull String themeId, @NonNull String key); + + /** + * Deletes inactivated theme settings. + * + * @param activatedThemeId activated theme id. + */ + void deleteByThemeIdIsNot(@NonNull String activatedThemeId); } diff --git a/src/main/java/run/halo/app/service/AttachmentService.java b/src/main/java/run/halo/app/service/AttachmentService.java index a57b360f3..ec35d13db 100644 --- a/src/main/java/run/halo/app/service/AttachmentService.java +++ b/src/main/java/run/halo/app/service/AttachmentService.java @@ -83,4 +83,13 @@ public interface AttachmentService extends CrudService { * @return list of type. */ List listAllType(); + + /** + * Replace attachment url in batch. + * + * @param oldUrl old blog url. + * @param newUrl new blog url. + * @return replaced attachments. + */ + List replaceUrl(@NonNull String oldUrl, @NonNull String newUrl); } diff --git a/src/main/java/run/halo/app/service/DataProcessService.java b/src/main/java/run/halo/app/service/DataProcessService.java new file mode 100644 index 000000000..adf9d253d --- /dev/null +++ b/src/main/java/run/halo/app/service/DataProcessService.java @@ -0,0 +1,20 @@ +package run.halo.app.service; + +import org.springframework.lang.NonNull; + +/** + * Data process service interface. + * + * @author ryanwang + * @date 2019-12-29 + */ +public interface DataProcessService { + + /** + * Replace all url. + * + * @param oldUrl old url must not be null. + * @param newUrl new url must not be null. + */ + void replaceAllUrl(@NonNull String oldUrl, @NonNull String newUrl); +} diff --git a/src/main/java/run/halo/app/service/OptionService.java b/src/main/java/run/halo/app/service/OptionService.java index 7f8763425..ef29ca479 100755 --- a/src/main/java/run/halo/app/service/OptionService.java +++ b/src/main/java/run/halo/app/service/OptionService.java @@ -338,6 +338,15 @@ public interface OptionService extends CrudService { */ long getBirthday(); + /** + * Replace option url in batch. + * + * @param oldUrl old blog url. + * @param newUrl new blog url. + * @return replaced options. + */ + List replaceUrl(@NonNull String oldUrl, @NonNull String newUrl); + /** * Converts to option output dto. * diff --git a/src/main/java/run/halo/app/service/PhotoService.java b/src/main/java/run/halo/app/service/PhotoService.java index 105fd99e5..2437affbb 100644 --- a/src/main/java/run/halo/app/service/PhotoService.java +++ b/src/main/java/run/halo/app/service/PhotoService.java @@ -80,4 +80,13 @@ public interface PhotoService extends CrudService { * @return list of teams */ List listAllTeams(); + + /** + * Replace photo url in batch. + * + * @param oldUrl old blog url. + * @param newUrl new blog url. + * @return replaced photos. + */ + List replaceUrl(@NonNull String oldUrl, @NonNull String newUrl); } diff --git a/src/main/java/run/halo/app/service/StaticPageService.java b/src/main/java/run/halo/app/service/StaticPageService.java new file mode 100644 index 000000000..72afcafed --- /dev/null +++ b/src/main/java/run/halo/app/service/StaticPageService.java @@ -0,0 +1,53 @@ +package run.halo.app.service; + +import run.halo.app.model.support.StaticPageFile; + +import java.nio.file.Path; +import java.util.List; + +import static run.halo.app.model.support.HaloConst.FILE_SEPARATOR; +import static run.halo.app.model.support.HaloConst.TEMP_DIR; +import static run.halo.app.utils.HaloUtils.ensureSuffix; + +/** + * Static Page service interface. + * + * @author ryanwang + * @date 2019-12-25 + */ +public interface StaticPageService { + + /** + * Static page folder location. + */ + String PAGES_FOLDER = "static_pages"; + + + String STATIC_PAGE_PACK_DIR = ensureSuffix(TEMP_DIR, FILE_SEPARATOR) + "static-pages-pack" + FILE_SEPARATOR; + + String[] USELESS_FILE_SUFFIX = {"ftl", "md", "yaml", "yml", "gitignore"}; + + /** + * Generate pages. + */ + void generate(); + + /** + * Deploy static pages. + */ + void deploy(); + + /** + * Zip static pages directory. + * + * @return zip path + */ + Path zipStaticPagesDirectory(); + + /** + * List file of generated static page. + * + * @return a list of generated static page. + */ + List listFile(); +} diff --git a/src/main/java/run/halo/app/service/ThemeService.java b/src/main/java/run/halo/app/service/ThemeService.java index 01c7e8668..9aaa500da 100644 --- a/src/main/java/run/halo/app/service/ThemeService.java +++ b/src/main/java/run/halo/app/service/ThemeService.java @@ -64,6 +64,11 @@ public interface ThemeService { */ String RENDER_TEMPLATE = "themes/%s/%s"; + /** + * Render template with suffix. + */ + String RENDER_TEMPLATE_SUFFIX = "themes/%s/%s.ftl"; + /** * Theme cache key. */ @@ -231,6 +236,15 @@ public interface ThemeService { @NonNull String render(@NonNull String pageName); + /** + * Renders a theme page. + * + * @param pageName must not be blank + * @return full path of the theme page + */ + @NonNull + String renderWithSuffix(@NonNull String pageName); + /** * Gets current theme id. * diff --git a/src/main/java/run/halo/app/service/ThemeSettingService.java b/src/main/java/run/halo/app/service/ThemeSettingService.java index bec2c5af1..f71c33973 100644 --- a/src/main/java/run/halo/app/service/ThemeSettingService.java +++ b/src/main/java/run/halo/app/service/ThemeSettingService.java @@ -55,4 +55,18 @@ public interface ThemeSettingService { */ @NonNull Map listAsMapBy(@NonNull String themeId); + + /** + * Replace theme setting url in batch. + * + * @param oldUrl old blog url. + * @param newUrl new blog url. + * @return replaced theme settings. + */ + List replaceUrl(@NonNull String oldUrl, @NonNull String newUrl); + + /** + * Delete unused theme setting. + */ + void deleteInactivated(); } diff --git a/src/main/java/run/halo/app/service/base/BaseCommentService.java b/src/main/java/run/halo/app/service/base/BaseCommentService.java index 890304c10..070992f0b 100644 --- a/src/main/java/run/halo/app/service/base/BaseCommentService.java +++ b/src/main/java/run/halo/app/service/base/BaseCommentService.java @@ -304,4 +304,13 @@ public interface BaseCommentService extends CrudSer */ Page filterIpAddress(@NonNull Page commentPage); + /** + * Replace comment url in batch. + * + * @param oldUrl old blog url. + * @param newUrl new blog url. + * @return replaced comments. + */ + List replaceUrl(@NonNull String oldUrl, @NonNull String newUrl); + } diff --git a/src/main/java/run/halo/app/service/base/BasePostService.java b/src/main/java/run/halo/app/service/base/BasePostService.java index e81cda626..45610a7ff 100644 --- a/src/main/java/run/halo/app/service/base/BasePostService.java +++ b/src/main/java/run/halo/app/service/base/BasePostService.java @@ -287,4 +287,14 @@ public interface BasePostService extends CrudService updateStatusByIds(@NonNull List ids, @NonNull PostStatus status); + + /** + * Replace post blog url in batch. + * + * @param oldUrl old blog url. + * @param newUrl new blog url. + * @return replaced posts. + */ + @NonNull + List replaceUrl(@NonNull String oldUrl, @NonNull String newUrl); } diff --git a/src/main/java/run/halo/app/service/impl/AttachmentServiceImpl.java b/src/main/java/run/halo/app/service/impl/AttachmentServiceImpl.java index faa6f19f7..3fc6a7340 100644 --- a/src/main/java/run/halo/app/service/impl/AttachmentServiceImpl.java +++ b/src/main/java/run/halo/app/service/impl/AttachmentServiceImpl.java @@ -183,6 +183,22 @@ public class AttachmentServiceImpl extends AbstractCrudService replaceUrl(String oldUrl, String newUrl) { + List attachments = listAll(); + List replaced = new ArrayList<>(); + attachments.forEach(attachment -> { + if (StringUtils.isNotEmpty(attachment.getPath())) { + attachment.setPath(attachment.getPath().replaceAll(oldUrl, newUrl)); + } + if (StringUtils.isNotEmpty(attachment.getThumbPath())) { + attachment.setThumbPath(attachment.getThumbPath().replaceAll(oldUrl, newUrl)); + } + replaced.add(attachment); + }); + return updateInBatch(replaced); + } + @Override public Attachment create(Attachment attachment) { Assert.notNull(attachment, "Attachment must not be null"); diff --git a/src/main/java/run/halo/app/service/impl/BaseCommentServiceImpl.java b/src/main/java/run/halo/app/service/impl/BaseCommentServiceImpl.java index 05e86334a..de6193c28 100644 --- a/src/main/java/run/halo/app/service/impl/BaseCommentServiceImpl.java +++ b/src/main/java/run/halo/app/service/impl/BaseCommentServiceImpl.java @@ -610,6 +610,20 @@ public abstract class BaseCommentServiceImpl extend return commentPage; } + @Override + public List replaceUrl(String oldUrl, String newUrl) { + List comments = listAll(); + List replaced = new ArrayList<>(); + comments.forEach(comment -> { + if (StringUtils.isNotEmpty(comment.getAuthorUrl())) { + comment.setAuthorUrl(comment.getAuthorUrl().replaceAll(oldUrl, newUrl)); + } + replaced.add(comment); + }); + List updated = updateInBatch(replaced); + return convertTo(updated); + } + /** * Get children comments recursively. * diff --git a/src/main/java/run/halo/app/service/impl/BasePostServiceImpl.java b/src/main/java/run/halo/app/service/impl/BasePostServiceImpl.java index 43436dbaa..f1fa768e0 100644 --- a/src/main/java/run/halo/app/service/impl/BasePostServiceImpl.java +++ b/src/main/java/run/halo/app/service/impl/BasePostServiceImpl.java @@ -29,10 +29,7 @@ import run.halo.app.utils.HaloUtils; import run.halo.app.utils.MarkdownUtils; import run.halo.app.utils.ServiceUtils; -import java.util.Collections; -import java.util.Date; -import java.util.List; -import java.util.Optional; +import java.util.*; import java.util.regex.Matcher; import java.util.regex.Pattern; import java.util.stream.Collectors; @@ -395,6 +392,26 @@ public abstract class BasePostServiceImpl extends Abstrac }).collect(Collectors.toList()); } + @Override + public List replaceUrl(String oldUrl, String newUrl) { + List posts = listAll(); + List replaced = new ArrayList<>(); + posts.forEach(post -> { + if (StringUtils.isNotEmpty(post.getThumbnail())) { + post.setThumbnail(post.getThumbnail().replaceAll(oldUrl, newUrl)); + } + if (StringUtils.isNotEmpty(post.getOriginalContent())) { + post.setOriginalContent(post.getOriginalContent().replaceAll(oldUrl, newUrl)); + } + if (StringUtils.isNotEmpty(post.getFormatContent())) { + post.setFormatContent(post.getFormatContent().replaceAll(oldUrl, newUrl)); + } + replaced.add(post); + }); + List updated = updateInBatch(replaced); + return updated.stream().map(this::convertToDetail).collect(Collectors.toList()); + } + @Override public POST create(POST post) { // Check title diff --git a/src/main/java/run/halo/app/service/impl/DataProcessServiceImpl.java b/src/main/java/run/halo/app/service/impl/DataProcessServiceImpl.java new file mode 100644 index 000000000..84a5a681e --- /dev/null +++ b/src/main/java/run/halo/app/service/impl/DataProcessServiceImpl.java @@ -0,0 +1,65 @@ +package run.halo.app.service.impl; + +import org.springframework.stereotype.Service; +import run.halo.app.service.*; + +/** + * DataProcessService implementation. + * + * @author ryanwang + * @date 2019-12-29 + */ +@Service +public class DataProcessServiceImpl implements DataProcessService { + + private final PostService postService; + + private final SheetService sheetService; + + private final PostCommentService postCommentService; + + private final SheetCommentService sheetCommentService; + + private final JournalCommentService journalCommentService; + + private final AttachmentService attachmentService; + + private final OptionService optionService; + + private final PhotoService photoService; + + private final ThemeSettingService themeSettingService; + + public DataProcessServiceImpl(PostService postService, + SheetService sheetService, + PostCommentService postCommentService, + SheetCommentService sheetCommentService, + JournalCommentService journalCommentService, + AttachmentService attachmentService, + OptionService optionService, + PhotoService photoService, + ThemeSettingService themeSettingService) { + this.postService = postService; + this.sheetService = sheetService; + this.postCommentService = postCommentService; + this.sheetCommentService = sheetCommentService; + this.journalCommentService = journalCommentService; + this.attachmentService = attachmentService; + this.optionService = optionService; + this.photoService = photoService; + this.themeSettingService = themeSettingService; + } + + @Override + public void replaceAllUrl(String oldUrl, String newUrl) { + postService.replaceUrl(oldUrl, newUrl); + sheetService.replaceUrl(oldUrl, newUrl); + postCommentService.replaceUrl(oldUrl, newUrl); + sheetCommentService.replaceUrl(oldUrl, newUrl); + journalCommentService.replaceUrl(oldUrl, newUrl); + attachmentService.replaceUrl(oldUrl, newUrl); + optionService.replaceUrl(oldUrl, newUrl); + photoService.replaceUrl(oldUrl, newUrl); + themeSettingService.replaceUrl(oldUrl, newUrl); + } +} 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 4f5c7a79b..a0e7ffb3f 100644 --- a/src/main/java/run/halo/app/service/impl/OptionServiceImpl.java +++ b/src/main/java/run/halo/app/service/impl/OptionServiceImpl.java @@ -36,6 +36,7 @@ import run.halo.app.utils.ValidationUtils; import javax.persistence.criteria.Predicate; import java.util.*; +import java.util.stream.Collectors; /** * OptionService implementation class @@ -460,6 +461,21 @@ public class OptionServiceImpl extends AbstractCrudService impl }); } + @Override + public List replaceUrl(String oldUrl, String newUrl) { + List