From 8af5abd585a12b4edbe0fd17c6c327f30974716f Mon Sep 17 00:00:00 2001 From: Thorsten Marx Date: Mon, 13 Jan 2025 20:15:14 +0100 Subject: [PATCH 1/2] separate template components and shortcodes --- ...gisterTemplateComponentExtensionPoint.java | 37 ++++++++++ .../com/condation/cms/api/hooks/Hooks.java | 1 + .../hooks/TemplateComponentsWrapper.java | 53 ++++++++++++++ .../cms/extensions/hooks/TemplateHooks.java | 10 +++ .../cms/templates/DynamicConfiguration.java | 13 ++-- .../templates/components/ComponentMap.java | 59 ++++++++++++++++ .../components/TemplateComponents.java | 70 +++++++++++++++++++ .../module/CMSModuleTemplateEngine.java | 28 ++++++-- .../tags/component/ComponentTag.java | 11 +-- .../TemplateEngineComponentTest.java | 10 +-- .../cms/templates/TemplateFeatureTest.java | 9 ++- 11 files changed, 276 insertions(+), 25 deletions(-) create mode 100644 cms-api/src/main/java/com/condation/cms/api/extensions/RegisterTemplateComponentExtensionPoint.java create mode 100644 cms-extensions/src/main/java/com/condation/cms/extensions/hooks/TemplateComponentsWrapper.java create mode 100644 cms-templates/src/main/java/com/condation/cms/templates/components/ComponentMap.java create mode 100644 cms-templates/src/main/java/com/condation/cms/templates/components/TemplateComponents.java diff --git a/cms-api/src/main/java/com/condation/cms/api/extensions/RegisterTemplateComponentExtensionPoint.java b/cms-api/src/main/java/com/condation/cms/api/extensions/RegisterTemplateComponentExtensionPoint.java new file mode 100644 index 000000000..21f099930 --- /dev/null +++ b/cms-api/src/main/java/com/condation/cms/api/extensions/RegisterTemplateComponentExtensionPoint.java @@ -0,0 +1,37 @@ +package com.condation.cms.api.extensions; + +/*- + * #%L + * cms-api + * %% + * Copyright (C) 2023 - 2024 CondationCMS + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program. If not, see + * . + * #L% + */ + + +import com.condation.cms.api.model.Parameter; +import java.util.Map; +import java.util.function.Function; + +/** + * + * @author t.marx + */ +public abstract class RegisterTemplateComponentExtensionPoint extends AbstractExtensionPoint { + + public abstract Map> components (); +} diff --git a/cms-api/src/main/java/com/condation/cms/api/hooks/Hooks.java b/cms-api/src/main/java/com/condation/cms/api/hooks/Hooks.java index 61a5ce042..17781464a 100644 --- a/cms-api/src/main/java/com/condation/cms/api/hooks/Hooks.java +++ b/cms-api/src/main/java/com/condation/cms/api/hooks/Hooks.java @@ -33,6 +33,7 @@ public enum Hooks { NAVIGATION_LIST("system/navigation/%s/list"), CONTENT_SHORTCODE("system/content/shortcodes"), CONTENT_FILTER("system/content/filter"), + TEMPLATE_COMPONENT("system/template/component"), DB_QUERY_OPERATIONS("system/db/query/operations"), SCHEDULER_REGISTER("system/scheduler/register"), SCHEDULER_REMOVE("system/scheduler/remove"), diff --git a/cms-extensions/src/main/java/com/condation/cms/extensions/hooks/TemplateComponentsWrapper.java b/cms-extensions/src/main/java/com/condation/cms/extensions/hooks/TemplateComponentsWrapper.java new file mode 100644 index 000000000..1a5d1ec38 --- /dev/null +++ b/cms-extensions/src/main/java/com/condation/cms/extensions/hooks/TemplateComponentsWrapper.java @@ -0,0 +1,53 @@ +package com.condation.cms.extensions.hooks; + +/*- + * #%L + * cms-extensions + * %% + * Copyright (C) 2023 - 2024 CondationCMS + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program. If not, see + * . + * #L% + */ + + +import com.condation.cms.api.model.Parameter; +import java.util.Map; +import java.util.function.Function; +import lombok.Getter; +import lombok.RequiredArgsConstructor; + +/** + * + * @author t.marx + */ +@RequiredArgsConstructor +public class TemplateComponentsWrapper { + + @Getter + private final Map> components; + + public void put(final String name, final Function function) { + components.put(name, function); + } + + public boolean contains(final String name) { + return components.containsKey(name); + } + + public void remove(final String name) { + components.remove(name); + } +} diff --git a/cms-extensions/src/main/java/com/condation/cms/extensions/hooks/TemplateHooks.java b/cms-extensions/src/main/java/com/condation/cms/extensions/hooks/TemplateHooks.java index adf7cb2ee..91b6c42c2 100644 --- a/cms-extensions/src/main/java/com/condation/cms/extensions/hooks/TemplateHooks.java +++ b/cms-extensions/src/main/java/com/condation/cms/extensions/hooks/TemplateHooks.java @@ -28,8 +28,10 @@ import com.condation.cms.api.feature.Feature; import com.condation.cms.api.feature.features.HookSystemFeature; import com.condation.cms.api.hooks.Hooks; +import com.condation.cms.api.model.Parameter; import com.condation.cms.api.request.RequestContext; import java.util.Map; +import java.util.function.Function; import lombok.RequiredArgsConstructor; /** @@ -59,4 +61,12 @@ public TemplateFunctionWrapper getTemplateFunctions () { return templateFunctions; } + + public TemplateComponentsWrapper getComponents (Map> components) { + var componentsWrapper = new TemplateComponentsWrapper(components); + requestContext.get(HookSystemFeature.class).hookSystem() + .execute(Hooks.TEMPLATE_COMPONENT.hook(), Map.of("components", componentsWrapper)); + + return componentsWrapper; + } } diff --git a/cms-templates/src/main/java/com/condation/cms/templates/DynamicConfiguration.java b/cms-templates/src/main/java/com/condation/cms/templates/DynamicConfiguration.java index 5329e73ab..6c33d40f6 100644 --- a/cms-templates/src/main/java/com/condation/cms/templates/DynamicConfiguration.java +++ b/cms-templates/src/main/java/com/condation/cms/templates/DynamicConfiguration.java @@ -23,6 +23,7 @@ */ import com.condation.cms.api.request.RequestContext; import com.condation.cms.content.shortcodes.ShortCodes; +import com.condation.cms.templates.components.TemplateComponents; import com.condation.cms.templates.tags.component.EndComponentTag; import com.condation.cms.templates.tags.component.ComponentTag; import java.util.Collections; @@ -34,17 +35,17 @@ * * @author t.marx */ -public record DynamicConfiguration(ShortCodes shortCodes, Map components, RequestContext requestContext) { +public record DynamicConfiguration(TemplateComponents templateComponents, Map components, RequestContext requestContext) { public static final DynamicConfiguration EMPTY = new DynamicConfiguration( - new ShortCodes(Collections.emptyMap(), null), + new TemplateComponents(Collections.emptyMap()), Collections.emptyMap(), null ); public DynamicConfiguration { - for (var tag : shortCodes.getShortCodeNames()) { - var openTag = new ComponentTag(tag, shortCodes); + for (var tag : templateComponents.getComponentNames()) { + var openTag = new ComponentTag(tag, templateComponents); var closeTag = new EndComponentTag(tag); components.put(openTag.getName(), openTag); @@ -52,8 +53,8 @@ public record DynamicConfiguration(ShortCodes shortCodes, Map } } - public DynamicConfiguration(ShortCodes shortcodes, RequestContext requestContext) { - this(shortcodes, new HashMap<>(), requestContext); + public DynamicConfiguration(TemplateComponents templateComponents, RequestContext requestContext) { + this(templateComponents, new HashMap<>(), requestContext); } public boolean hasComponent(String name) { diff --git a/cms-templates/src/main/java/com/condation/cms/templates/components/ComponentMap.java b/cms-templates/src/main/java/com/condation/cms/templates/components/ComponentMap.java new file mode 100644 index 000000000..185fa791d --- /dev/null +++ b/cms-templates/src/main/java/com/condation/cms/templates/components/ComponentMap.java @@ -0,0 +1,59 @@ +package com.condation.cms.templates.components; + +/*- + * #%L + * cms-content + * %% + * Copyright (C) 2023 - 2024 CondationCMS + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program. If not, see + * . + * #L% + */ + +import com.condation.cms.api.model.Parameter; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; +import java.util.Set; +import java.util.function.Function; + +/** + * + * @author t.marx + */ +public class ComponentMap { + + private final Map> tags = new HashMap<>(); + + public Set names () { + return Collections.unmodifiableSet(tags.keySet()); + } + + public void put(String codeName, Function function) { + tags.put(codeName, function); + } + + public void putAll(Map> tags) { + this.tags.putAll(tags); + } + + public boolean has(String codeName) { + return tags.containsKey(codeName); + } + + public Function get(String name) { + return tags.getOrDefault(name, (params) -> ""); + } +} diff --git a/cms-templates/src/main/java/com/condation/cms/templates/components/TemplateComponents.java b/cms-templates/src/main/java/com/condation/cms/templates/components/TemplateComponents.java new file mode 100644 index 000000000..f806da06d --- /dev/null +++ b/cms-templates/src/main/java/com/condation/cms/templates/components/TemplateComponents.java @@ -0,0 +1,70 @@ +package com.condation.cms.templates.components; + +/*- + * #%L + * cms-content + * %% + * Copyright (C) 2023 - 2024 CondationCMS + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program. If not, see + * . + * #L% + */ + + +import com.condation.cms.api.model.Parameter; +import com.condation.cms.api.request.RequestContext; +import java.util.Collections; +import java.util.Map; +import java.util.Set; +import java.util.function.Function; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +/** + * + * @author t.marx + */ +@Slf4j +public class TemplateComponents { + + private final ComponentMap componentMap; + + public TemplateComponents (Map> components) { + this.componentMap = new ComponentMap(); + this.componentMap.putAll(components); + } + + public Set getComponentNames () { + return componentMap.names(); + } + + public String execute (String name, Map parameters, RequestContext requestContext) { + if (!componentMap.has(name)) { + return ""; + } + try { + Parameter params; + if (parameters != null) { + params = new Parameter(parameters); + } else { + params = new Parameter(); + } + return componentMap.get(name).apply(params); + } catch (Exception e) { + log.error("",e); + } + return ""; + } +} diff --git a/cms-templates/src/main/java/com/condation/cms/templates/module/CMSModuleTemplateEngine.java b/cms-templates/src/main/java/com/condation/cms/templates/module/CMSModuleTemplateEngine.java index f55e64243..0e6398a4b 100644 --- a/cms-templates/src/main/java/com/condation/cms/templates/module/CMSModuleTemplateEngine.java +++ b/cms-templates/src/main/java/com/condation/cms/templates/module/CMSModuleTemplateEngine.java @@ -23,19 +23,27 @@ */ import com.condation.cms.api.cache.CacheManager; import com.condation.cms.api.db.DB; +import com.condation.cms.api.extensions.RegisterTemplateComponentExtensionPoint; +import com.condation.cms.api.feature.features.InjectorFeature; +import com.condation.cms.api.model.Parameter; +import com.condation.cms.api.request.RequestContext; import com.condation.cms.api.template.TemplateEngine; import com.condation.cms.api.theme.Theme; -import com.condation.cms.content.RenderContext; -import com.condation.cms.content.template.functions.shortcode.ShortCodeTemplateFunction; +import com.condation.cms.extensions.hooks.TemplateHooks; import com.condation.cms.templates.CMSTemplateEngine; import com.condation.cms.templates.DynamicConfiguration; import com.condation.cms.templates.TemplateEngineFactory; import com.condation.cms.templates.TemplateLoader; +import com.condation.cms.templates.components.TemplateComponents; import com.condation.cms.templates.loaders.CompositeTemplateLoader; import com.condation.cms.templates.loaders.FileTemplateLoader; +import com.condation.modules.api.ModuleManager; import java.io.IOException; import java.time.Duration; import java.util.ArrayList; +import java.util.HashMap; +import java.util.Map; +import java.util.function.Function; /** * @@ -115,10 +123,22 @@ public String render(String template, Model model) throws IOException { } private DynamicConfiguration createDynamicConfiguration(Model model) { - var shortCodes = model.requestContext.get(RenderContext.class).shortCodes(); - DynamicConfiguration dynamicConfig = new DynamicConfiguration(shortCodes, model.requestContext); + DynamicConfiguration dynamicConfig = new DynamicConfiguration( + createTemplateComponents(model.requestContext), model.requestContext); return dynamicConfig; } + + private TemplateComponents createTemplateComponents(RequestContext requestContext) { + Map> components = new HashMap<>(); + + var injector = requestContext.get(InjectorFeature.class).injector(); + + injector.getInstance(ModuleManager.class).extensions(RegisterTemplateComponentExtensionPoint.class) + .forEach(extension -> components.putAll(extension.components())); + + var wrapper = requestContext.get(TemplateHooks.class).getComponents(components); + return new TemplateComponents(wrapper.getComponents()); + } @Override public String renderFromString(String templateString, Model model) throws IOException { diff --git a/cms-templates/src/main/java/com/condation/cms/templates/tags/component/ComponentTag.java b/cms-templates/src/main/java/com/condation/cms/templates/tags/component/ComponentTag.java index c8760c187..816e66e19 100644 --- a/cms-templates/src/main/java/com/condation/cms/templates/tags/component/ComponentTag.java +++ b/cms-templates/src/main/java/com/condation/cms/templates/tags/component/ComponentTag.java @@ -24,6 +24,7 @@ import com.condation.cms.content.shortcodes.ShortCodes; import com.condation.cms.templates.Component; +import com.condation.cms.templates.components.TemplateComponents; import com.condation.cms.templates.exceptions.RenderException; import com.condation.cms.templates.parser.ComponentNode; import com.condation.cms.templates.renderer.Renderer; @@ -42,19 +43,19 @@ @RequiredArgsConstructor public class ComponentTag implements Component { - private final String shortCodeName; + private final String componentName; - private final ShortCodes shortCodes; + private final TemplateComponents components; @Override public String getName() { - return shortCodeName; + return componentName; } @Override public Optional getCloseingName() { - return Optional.of("end%s".formatted(shortCodeName)); + return Optional.of("end%s".formatted(componentName)); } @Override @@ -66,7 +67,7 @@ public void render(ComponentNode node, Renderer.Context context, Writer writer) params.put("_content", content); - var shortCodeResult = shortCodes.execute(shortCodeName, params, context.dynamicConfiguration().requestContext()); + var shortCodeResult = components.execute(componentName, params, context.dynamicConfiguration().requestContext()); if (!Strings.isNullOrEmpty(shortCodeResult)) { writer.write(shortCodeResult); } diff --git a/cms-templates/src/test/java/com/condation/cms/templates/TemplateEngineComponentTest.java b/cms-templates/src/test/java/com/condation/cms/templates/TemplateEngineComponentTest.java index f1c94cde3..e72981be5 100644 --- a/cms-templates/src/test/java/com/condation/cms/templates/TemplateEngineComponentTest.java +++ b/cms-templates/src/test/java/com/condation/cms/templates/TemplateEngineComponentTest.java @@ -23,6 +23,7 @@ */ import com.condation.cms.content.shortcodes.ShortCodes; import com.condation.cms.content.shortcodes.TagParser; +import com.condation.cms.templates.components.TemplateComponents; import com.condation.cms.templates.exceptions.ParserException; import com.condation.cms.templates.exceptions.RenderException; import com.condation.cms.templates.loaders.StringTemplateLoader; @@ -38,12 +39,12 @@ */ public class TemplateEngineComponentTest extends AbstractTemplateEngineTest { - static ShortCodes shortCodes; + static TemplateComponents components; static DynamicConfiguration dynamicConfiguration; @BeforeAll public void setupShortCodes() { - shortCodes = new ShortCodes( + components = new TemplateComponents( Map.of( "tag1", (params) -> { return "Hello"; @@ -53,10 +54,9 @@ public void setupShortCodes() { }, "tag3", (param) -> { return "
%s
".formatted(param.get("_content")); - }), - new TagParser(null) + }) ); - dynamicConfiguration = new DynamicConfiguration(shortCodes, null); + dynamicConfiguration = new DynamicConfiguration(components, null); } @Override diff --git a/cms-templates/src/test/java/com/condation/cms/templates/TemplateFeatureTest.java b/cms-templates/src/test/java/com/condation/cms/templates/TemplateFeatureTest.java index 0576e5574..998c233a5 100644 --- a/cms-templates/src/test/java/com/condation/cms/templates/TemplateFeatureTest.java +++ b/cms-templates/src/test/java/com/condation/cms/templates/TemplateFeatureTest.java @@ -21,8 +21,8 @@ * . * #L% */ -import com.condation.cms.content.shortcodes.ShortCodes; import com.condation.cms.content.shortcodes.TagParser; +import com.condation.cms.templates.components.TemplateComponents; import com.condation.cms.templates.loaders.StringTemplateLoader; import com.google.gson.Gson; import com.google.gson.GsonBuilder; @@ -77,12 +77,11 @@ void test_features(String templateFile) throws Exception { } private DynamicConfiguration createDynamicConfig () { - ShortCodes shortCodes = new ShortCodes( + TemplateComponents components = new TemplateComponents( Map.of( "hello", (params) -> "hello " + params.get("name") - ), - new TagParser(null)); - return new DynamicConfiguration(shortCodes, null); + )); + return new DynamicConfiguration(components, null); } private Map getData (String filename) throws IOException { From 32438a5f5cc41a10e47fa44d7c4a7af263781b51 Mon Sep 17 00:00:00 2001 From: Thorsten Marx Date: Mon, 13 Jan 2025 20:16:32 +0100 Subject: [PATCH 2/2] refactor --- .../cms/templates/module/CMSModuleTemplateEngine.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/cms-templates/src/main/java/com/condation/cms/templates/module/CMSModuleTemplateEngine.java b/cms-templates/src/main/java/com/condation/cms/templates/module/CMSModuleTemplateEngine.java index 0e6398a4b..3951e64c1 100644 --- a/cms-templates/src/main/java/com/condation/cms/templates/module/CMSModuleTemplateEngine.java +++ b/cms-templates/src/main/java/com/condation/cms/templates/module/CMSModuleTemplateEngine.java @@ -133,7 +133,8 @@ private TemplateComponents createTemplateComponents(RequestContext requestContex var injector = requestContext.get(InjectorFeature.class).injector(); - injector.getInstance(ModuleManager.class).extensions(RegisterTemplateComponentExtensionPoint.class) + injector.getInstance(ModuleManager.class) + .extensions(RegisterTemplateComponentExtensionPoint.class) .forEach(extension -> components.putAll(extension.components())); var wrapper = requestContext.get(TemplateHooks.class).getComponents(components);