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 index dbabb940b..0e2b6b985 100644 --- a/src/main/java/run/halo/app/controller/admin/api/StaticPageController.java +++ b/src/main/java/run/halo/app/controller/admin/api/StaticPageController.java @@ -1,10 +1,14 @@ package run.halo.app.controller.admin.api; +import io.swagger.annotations.ApiOperation; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; +import run.halo.app.model.support.StaticPageFile; import run.halo.app.service.StaticPageService; +import java.util.List; + /** * @author ryan0up * @date 2019/12/25 @@ -19,8 +23,21 @@ public class StaticPageController { this.staticPageService = staticPageService; } + @GetMapping + @ApiOperation("List static page files.") + public List list() { + return staticPageService.listFile(); + } + @GetMapping("generate") + @ApiOperation("Generate static page files.") public void generate() { staticPageService.generate(); } + + @GetMapping("deploy") + @ApiOperation("Deploy static page to remove platform") + public void deploy() { + staticPageService.deploy(); + } } 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..f493bc486 --- /dev/null +++ b/src/main/java/run/halo/app/handler/staticdeploy/NetlifyStaticDeployHandler.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; + +/** + * Netlify deploy handler. + * + * @author ryanwang + * @date 2019-12-26 + */ +@Slf4j +@Component +public class NetlifyStaticDeployHandler implements StaticDeployHandler { + + private final OptionService optionService; + + public NetlifyStaticDeployHandler(OptionService optionService) { + this.optionService = optionService; + } + + @Override + public void deploy() { + + } + + @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..22ece8fa2 --- /dev/null +++ b/src/main/java/run/halo/app/handler/staticdeploy/StaticDeployHandlers.java @@ -0,0 +1,64 @@ +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 file handler + addFileHandlers(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(); + } + } + + 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 addFileHandlers(@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..79de7687b --- /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(1), + + /** + * Deploy static pages in netlify. + */ + NETLIFY(2); + + 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/StaticPageFile.java b/src/main/java/run/halo/app/model/support/StaticPageFile.java new file mode 100644 index 000000000..240db30b6 --- /dev/null +++ b/src/main/java/run/halo/app/model/support/StaticPageFile.java @@ -0,0 +1,35 @@ +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 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/service/StaticPageService.java b/src/main/java/run/halo/app/service/StaticPageService.java index 31531c0ec..fc40e2a9c 100644 --- a/src/main/java/run/halo/app/service/StaticPageService.java +++ b/src/main/java/run/halo/app/service/StaticPageService.java @@ -1,5 +1,9 @@ package run.halo.app.service; +import run.halo.app.model.support.StaticPageFile; + +import java.util.List; + /** * Static Page service interface. * @@ -17,4 +21,16 @@ public interface StaticPageService { * Generate pages. */ void generate(); + + /** + * Deploy static pages. + */ + void deploy(); + + /** + * 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/impl/StaticPageServiceImpl.java b/src/main/java/run/halo/app/service/impl/StaticPageServiceImpl.java index eb55ae4fc..0d1824e04 100644 --- a/src/main/java/run/halo/app/service/impl/StaticPageServiceImpl.java +++ b/src/main/java/run/halo/app/service/impl/StaticPageServiceImpl.java @@ -10,18 +10,24 @@ import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Sort; import org.springframework.lang.NonNull; +import org.springframework.lang.Nullable; import org.springframework.stereotype.Service; import org.springframework.ui.ModelMap; import org.springframework.ui.freemarker.FreeMarkerTemplateUtils; +import org.springframework.util.Assert; import org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer; import run.halo.app.config.properties.HaloProperties; import run.halo.app.exception.ServiceException; +import run.halo.app.handler.staticdeploy.StaticDeployHandlers; import run.halo.app.handler.theme.config.support.ThemeProperty; import run.halo.app.model.dto.PhotoDTO; import run.halo.app.model.entity.*; import run.halo.app.model.enums.PostStatus; +import run.halo.app.model.enums.StaticDeployType; import run.halo.app.model.properties.PostProperties; +import run.halo.app.model.properties.StaticDeployProperties; import run.halo.app.model.support.HaloConst; +import run.halo.app.model.support.StaticPageFile; import run.halo.app.model.vo.PostDetailVO; import run.halo.app.model.vo.PostListVO; import run.halo.app.model.vo.SheetDetailVO; @@ -33,9 +39,12 @@ import java.io.IOException; import java.io.UnsupportedEncodingException; import java.net.URLEncoder; import java.nio.charset.StandardCharsets; +import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; +import java.util.LinkedList; import java.util.List; +import java.util.stream.Stream; import static org.springframework.data.domain.Sort.Direction.DESC; @@ -79,6 +88,8 @@ public class StaticPageServiceImpl implements StaticPageService { private final FreeMarkerConfigurer freeMarkerConfigurer; + private final StaticDeployHandlers staticDeployHandlers; + public StaticPageServiceImpl(PostService postService, PostCategoryService postCategoryService, PostTagService postTagService, @@ -92,7 +103,8 @@ public class StaticPageServiceImpl implements StaticPageService { ThemeService themeService, HaloProperties haloProperties, OptionService optionService, - FreeMarkerConfigurer freeMarkerConfigurer) throws IOException { + FreeMarkerConfigurer freeMarkerConfigurer, + StaticDeployHandlers staticDeployHandlers) throws IOException { this.postService = postService; this.postCategoryService = postCategoryService; this.postTagService = postTagService; @@ -107,6 +119,7 @@ public class StaticPageServiceImpl implements StaticPageService { this.haloProperties = haloProperties; this.optionService = optionService; this.freeMarkerConfigurer = freeMarkerConfigurer; + this.staticDeployHandlers = staticDeployHandlers; pagesDir = Paths.get(haloProperties.getWorkDir(), PAGES_FOLDER); FileUtils.createIfAbsent(pagesDir); @@ -138,6 +151,47 @@ public class StaticPageServiceImpl implements StaticPageService { } } + @Override + public void deploy() { + StaticDeployType type = getStaticDeployType(); + + staticDeployHandlers.deploy(type); + } + + @Override + public List listFile() { + return listStaticPageFileTree(pagesDir); + } + + @Nullable + private List listStaticPageFileTree(@NonNull Path topPath) { + Assert.notNull(topPath, "Top path must not be null"); + + if (!Files.isDirectory(topPath)) { + return null; + } + + try (Stream pathStream = Files.list(topPath)) { + List staticPageFiles = new LinkedList<>(); + + pathStream.forEach(path -> { + StaticPageFile staticPageFile = new StaticPageFile(); + staticPageFile.setName(path.getFileName().toString()); + staticPageFile.setIsFile(Files.isRegularFile(path)); + if (Files.isDirectory(path)) { + staticPageFile.setChildren(listStaticPageFileTree(path)); + } + + staticPageFiles.add(staticPageFile); + }); + + staticPageFiles.sort(new StaticPageFile()); + return staticPageFiles; + } catch (IOException e) { + throw new ServiceException("Failed to list sub files", e); + } + } + /** * Clean static pages folder */ @@ -714,4 +768,14 @@ public class StaticPageServiceImpl implements StaticPageService { Path path = Paths.get(pagesDir.toString(), subPath); return path.toFile(); } + + /** + * Get static deploy type from options. + * + * @return static deploy type + */ + @NonNull + private StaticDeployType getStaticDeployType() { + return optionService.getEnumByPropertyOrDefault(StaticDeployProperties.DEPLOY_TYPE, StaticDeployType.class, StaticDeployType.GIT); + } }