From 133e54106dbc18f891eedfb9f59ca0deba8eeff2 Mon Sep 17 00:00:00 2001 From: guqing <38999863+guqing@users.noreply.github.com> Date: Thu, 20 Jul 2023 16:59:56 +0800 Subject: [PATCH] refactor: optimize the usage of comment widget extension point (#4249) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit #### What type of PR is this? /kind improvement /area core /milestone 2.8.x #### What this PR does / why we need it: 优化评论扩展点的使用方式 how to test it? 测试评论插件是否正常可用 #### Does this PR introduce a user-facing change? ```release-note 优化评论扩展点的使用方式 ``` --- .../DefaultExtensionGetter.java | 31 +++++++++++++------ .../dialect/CommentElementTagProcessor.java | 17 +++++----- .../extensionpoint-definitions.yaml | 15 +++++++-- .../CommentElementTagProcessorTest.java | 15 +++++---- 4 files changed, 52 insertions(+), 26 deletions(-) diff --git a/application/src/main/java/run/halo/app/plugin/extensionpoint/DefaultExtensionGetter.java b/application/src/main/java/run/halo/app/plugin/extensionpoint/DefaultExtensionGetter.java index 78520d07e..2c7c7e98d 100644 --- a/application/src/main/java/run/halo/app/plugin/extensionpoint/DefaultExtensionGetter.java +++ b/application/src/main/java/run/halo/app/plugin/extensionpoint/DefaultExtensionGetter.java @@ -1,11 +1,14 @@ package run.halo.app.plugin.extensionpoint; import java.util.Comparator; +import java.util.List; import java.util.Set; import java.util.stream.Stream; import lombok.RequiredArgsConstructor; import org.pf4j.ExtensionPoint; import org.springframework.context.ApplicationContext; +import org.springframework.core.annotation.AnnotationAwareOrderComparator; +import org.springframework.lang.NonNull; import org.springframework.stereotype.Component; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; @@ -32,14 +35,17 @@ public class DefaultExtensionGetter implements ExtensionGetter { .switchIfEmpty(Mono.just(ExtensionPointEnabled.EMPTY)) .mapNotNull(enabled -> { var implClassNames = enabled.getOrDefault(extensionPoint.getName(), Set.of()); - return pluginManager.getExtensions(extensionPoint) + List allExtensions = getAllExtensions(extensionPoint); + if (allExtensions.isEmpty()) { + return null; + } + return allExtensions .stream() .filter(impl -> implClassNames.contains(impl.getClass().getName())) .findFirst() // Fallback to local implementation of the extension point. // This will happen when no proper configuration is found. - .orElseGet(() -> - applicationContext.getBeanProvider(extensionPoint).getIfAvailable()); + .orElseGet(() -> allExtensions.get(0)); }); } @@ -74,16 +80,23 @@ public class DefaultExtensionGetter implements ExtensionGetter { if (type == ExtensionPointDefinition.ExtensionPointType.SINGLETON) { return getEnabledExtension(extensionPoint).flux(); } - Stream pluginExtsStream = pluginManager.getExtensions(extensionPoint) - .stream(); - Stream systemExtsStream = applicationContext.getBeanProvider(extensionPoint) - .orderedStream(); + // TODO If the type is sortable, may need to process the returned order. - return Flux.just(pluginExtsStream, systemExtsStream) - .flatMap(Flux::fromStream); + return Flux.fromIterable(getAllExtensions(extensionPoint)); }); } + @NonNull + List getAllExtensions(Class extensionPoint) { + Stream pluginExtsStream = pluginManager.getExtensions(extensionPoint) + .stream(); + Stream systemExtsStream = applicationContext.getBeanProvider(extensionPoint) + .orderedStream(); + return Stream.concat(systemExtsStream, pluginExtsStream) + .sorted(new AnnotationAwareOrderComparator()) + .toList(); + } + Mono fetchExtensionPointDefinition( Class extensionPoint) { // TODO Optimize query diff --git a/application/src/main/java/run/halo/app/theme/dialect/CommentElementTagProcessor.java b/application/src/main/java/run/halo/app/theme/dialect/CommentElementTagProcessor.java index 7f01467a0..b4db33e1d 100644 --- a/application/src/main/java/run/halo/app/theme/dialect/CommentElementTagProcessor.java +++ b/application/src/main/java/run/halo/app/theme/dialect/CommentElementTagProcessor.java @@ -1,6 +1,5 @@ package run.halo.app.theme.dialect; -import java.util.List; import org.springframework.context.ApplicationContext; import org.thymeleaf.context.ITemplateContext; import org.thymeleaf.model.IProcessableElementTag; @@ -8,7 +7,7 @@ import org.thymeleaf.processor.element.AbstractElementTagProcessor; import org.thymeleaf.processor.element.IElementTagStructureHandler; import org.thymeleaf.spring6.context.SpringContextUtils; import org.thymeleaf.templatemode.TemplateMode; -import run.halo.app.plugin.ExtensionComponentsFinder; +import run.halo.app.plugin.extensionpoint.ExtensionGetter; /** @@ -44,15 +43,15 @@ public class CommentElementTagProcessor extends AbstractElementTagProcessor { protected void doProcess(ITemplateContext context, IProcessableElementTag tag, IElementTagStructureHandler structureHandler) { final ApplicationContext appCtx = SpringContextUtils.getApplicationContext(context); - ExtensionComponentsFinder componentsFinder = - appCtx.getBean(ExtensionComponentsFinder.class); - List commentWidgets = componentsFinder.getExtensions(CommentWidget.class); - if (commentWidgets.isEmpty()) { + ExtensionGetter extensionGetter = appCtx.getBean(ExtensionGetter.class); + CommentWidget commentWidget = + extensionGetter.getEnabledExtensionByDefinition(CommentWidget.class) + .next() + .block(); + if (commentWidget == null) { structureHandler.replaceWith("", false); return; } - // TODO if find more than one comment widget, query CommentWidget setting to decide which - // one to use. - commentWidgets.get(0).render(context, tag, structureHandler); + commentWidget.render(context, tag, structureHandler); } } diff --git a/application/src/main/resources/extensions/extensionpoint-definitions.yaml b/application/src/main/resources/extensions/extensionpoint-definitions.yaml index 3072f6a2a..375b24504 100644 --- a/application/src/main/resources/extensions/extensionpoint-definitions.yaml +++ b/application/src/main/resources/extensions/extensionpoint-definitions.yaml @@ -18,7 +18,7 @@ spec: className: run.halo.app.theme.ReactivePostContentHandler displayName: ReactivePostContentHandler type: MULTI_INSTANCE - description: "Provides a way to extend the post content to be displayed in the theme-side." + description: "Provides a way to extend the post content to be displayed on the theme-side." --- apiVersion: plugin.halo.run/v1alpha1 @@ -29,4 +29,15 @@ spec: className: run.halo.app.theme.ReactiveSinglePageContentHandler displayName: ReactiveSinglePageContentHandler type: MULTI_INSTANCE - description: "Provides a way to extend the single page content to be displayed in the theme-side." + description: "Provides a way to extend the single page content to be displayed on the theme-side." + +--- +apiVersion: plugin.halo.run/v1alpha1 +kind: ExtensionPointDefinition +metadata: + name: comment-widget +spec: + className: run.halo.app.theme.dialect.CommentWidget + displayName: CommentWidget + type: SINGLETON + description: "Provides an extension point for the comment widget on the theme-side." diff --git a/application/src/test/java/run/halo/app/theme/dialect/CommentElementTagProcessorTest.java b/application/src/test/java/run/halo/app/theme/dialect/CommentElementTagProcessorTest.java index c4cc602db..c93bdf373 100644 --- a/application/src/test/java/run/halo/app/theme/dialect/CommentElementTagProcessorTest.java +++ b/application/src/test/java/run/halo/app/theme/dialect/CommentElementTagProcessorTest.java @@ -4,7 +4,6 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.when; -import java.util.List; import java.util.Map; import java.util.Set; import org.junit.jupiter.api.BeforeEach; @@ -24,7 +23,9 @@ import org.thymeleaf.spring6.expression.ThymeleafEvaluationContext; import org.thymeleaf.templateresolver.StringTemplateResolver; import org.thymeleaf.templateresource.ITemplateResource; import org.thymeleaf.templateresource.StringTemplateResource; +import reactor.core.publisher.Flux; import run.halo.app.plugin.ExtensionComponentsFinder; +import run.halo.app.plugin.extensionpoint.ExtensionGetter; /** * Tests for {@link CommentElementTagProcessor}. @@ -41,7 +42,7 @@ class CommentElementTagProcessorTest { private ApplicationContext applicationContext; @Mock - private ExtensionComponentsFinder componentsFinder; + private ExtensionGetter extensionGetter; private TemplateEngine templateEngine; @@ -51,14 +52,16 @@ class CommentElementTagProcessorTest { templateEngine = new TemplateEngine(); templateEngine.setDialects(Set.of(haloProcessorDialect, new SpringStandardDialect())); templateEngine.addTemplateResolver(new TestTemplateResolver()); - when(applicationContext.getBean(eq(ExtensionComponentsFinder.class))) - .thenReturn(componentsFinder); + when(applicationContext.getBean(eq(ExtensionGetter.class))) + .thenReturn(extensionGetter); } @Test void doProcess() { Context context = getContext(); + when(extensionGetter.getEnabledExtensionByDefinition(eq(CommentWidget.class))) + .thenReturn(Flux.empty()); String result = templateEngine.process("commentWidget", context); assertThat(result).isEqualTo(""" @@ -70,8 +73,8 @@ class CommentElementTagProcessorTest { """); - when(componentsFinder.getExtensions(CommentWidget.class)) - .thenReturn(List.of(new DefaultCommentWidget())); + when(extensionGetter.getEnabledExtensionByDefinition(eq(CommentWidget.class))) + .thenReturn(Flux.just(new DefaultCommentWidget())); result = templateEngine.process("commentWidget", context); assertThat(result).isEqualTo("""