如何限制CQ5 / Custom组件每页只添加一次。?当作者要将第二次相同的组件添加到同一页面时,我想限制组件拖放到页面中。
答案 0 :(得分:5)
一种选择是将组件直接包含在模板的JSP中,并将其从sidekick中的可用组件列表中排除。为此,请将组件直接添加到JSP(此示例中为基础轮播):
<cq:include path="carousel" resourceType="foundation/components/carousel" />
要从sidekick中隐藏组件,请设置:
componentGroup: .hidden
或使用设计模式将其从“允许的组件”列表中排除。
如果您需要允许用户创建没有此组件的页面,您可以提供省略cq:include
的第二个模板。
答案 1 :(得分:3)
感谢Rampant,我已按照您的方法和链接说明了。 Posting link again : please follow this blog 这真的很有帮助。无论我做了什么,我都会发布实现。 它对我来说很好。绝对可以提高代码质量,这是原始代码,仅供参考。
1.Servlet Filter
请记住,如果任何资源被引用,则此过滤器将执行。因此,您需要在最后过滤内容以进行进一步处理。 附: chain.doFilter(请求,响应);是必须的。或cq将被绞死,不会显示任何内容。
@SlingFilter(generateComponent = false, generateService = true, order = -700,
scope = SlingFilterScope.REQUEST)
@Component(immediate = true, metatype = false)
public class ComponentRestrictorFilter implements Filter {
public void init(FilterConfig filterConfig) throws ServletException {}
@Reference
private ResourceResolverFactory resolverFactory;
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
WCMMode mode = WCMMode.fromRequest(request);
if (mode == WCMMode.EDIT) {
SlingHttpServletRequest slingRequest = (SlingHttpServletRequest) request;
PageManager pageManager = slingRequest.getResource().getResourceResolver().adaptTo(PageManager.class);
Page currentPage = pageManager.getContainingPage(slingRequest.getResource());
logger.error("***mode" + mode);
if (currentPage != null )) {
ComponentRestrictor restrictor = new ComponentRestrictor(currentPage.getPath(), RESTRICTED_COMPONENT);
restrictor.removeDuplicateEntry(resolverFactory,pageManager);
}
chain.doFilter(request, response);
}
}
public void destroy() {}
}
2.ComponentRestrictor class
public class ComponentRestrictor {
private String targetPage;
private String component;
private Pattern pattern;
private Set<Resource> duplicateResource = new HashSet<Resource>();
private Logger logger = LoggerFactory.getLogger(ComponentRestrictor.class);
private Resource resource = null;
private ResourceResolver resourceResolver = null;
private ComponentRestrictorHelper helper = new ComponentRestrictorHelper();
public ComponentRestrictor(String targetPage_, String component_){
targetPage = targetPage_ + "/jcr:content";
component = component_;
}
public void removeDuplicateEntry(ResourceResolverFactory resolverFactory, PageManager pageManager) {
pattern = Pattern.compile("([\"']|^)(" + component + ")(\\S|$)");
findReference(resolverFactory, pageManager);
}
private void findReference(ResourceResolverFactory resolverFactory, PageManager pageManager) {
try {
resourceResolver = resolverFactory.getAdministrativeResourceResolver(null);
resource = resourceResolver.getResource(this.targetPage);
if (resource == null)
return;
search(resource);
helper.removeDuplicateResource(pageManager,duplicateResource);
} catch (LoginException e) {
logger.error("Exception while getting the ResourceResolver " + e.getMessage());
}
resourceResolver.close();
}
private void search(Resource parentResource) {
searchReferencesInContent(parentResource);
for (Iterator<Resource> iter = parentResource.listChildren(); iter.hasNext();) {
Resource child = iter.next();
search(child);
}
}
private void searchReferencesInContent(Resource resource) {
ValueMap map = ResourceUtil.getValueMap(resource);
for (String key : map.keySet()) {
if (!helper.checkKey(key)) {
continue;
}
String[] values = map.get(key, new String[0]);
for (String value : values) {
if (pattern.matcher(value).find()) {
logger.error("resource**" + resource.getPath());
duplicateResource.add(resource);
}
}
}
}
}
3.删除节点/资源 无论您要删除/删除哪个资源,只需使用PageManager api
pageManeger.delete(resource,false);
那就是!!!你很高兴。
答案 2 :(得分:1)
这些选项看起来都不容易实现。我发现的最佳方法是使用ACS Commons Implementation,它非常简单,可以被任何项目采用。
以下是链接以及如何配置它: https://github.com/Adobe-Consulting-Services/acs-aem-commons/pull/639
享受编码!!!
答案 3 :(得分:0)
如果这确实是一项要求,最好的方法可能如下:
请注意,您无法阻止显示对话框,但至少作者已指示该特定组件只能使用一次。
答案 4 :(得分:0)
听起来需要澄清要求(并理解为什么)。
如果作者可以接受培训,让他们通过创作和审核工作流程来管理组件的限制。
如果只有一个固定位置可以显示组件,那么页面组件应该包含内容组件,并让组件具有“启用”切换属性以确定它是否应该呈现任何内容。组件的组应该是.hidden以防止从sidekick中拖出。
如果组件有一组固定的位置,页面组件可以有一个位置列表的下拉列表(包括“无”)。然后,页面呈现组件将有条件地将组件包括在正确的位置。再次,防止从sidekick拖动组件。
在“难以想象”的情况下,组件可以出现在页面的任何位置,由作者添加,但仅限于1个实例 - 使用包装器组件来管理包括(不可碎片的)组件。让作者在页面上拖动包装器多次,但包装器应查询页面的资源并确定它是否是第一个实例,如果是,则包括结束组件。否则,包装器什么都不做。
根据我们的经验(在CQ上2年),通过代码实现这种类型的业务规则会产生一个脆弱的解决方案。此外,要求有改变的习惯。如果通过代码强制执行,则需要开发工作,而不是让作者更快地进行更改。典雅。
答案 5 :(得分:0)
这些选项都不是那么好。如果您真的想要一个强大的解决方案来解决这个问题(限制页面上没有硬编码位置的项目数),那么最好的方法是使用servlet过滤器链OSGI服务,您可以在其中管理实例数,然后使用资源解析器来删除违规实例。
基本要点是:
cq:editConfig
javax.servlet.Filter
的OSGI服务,该服务封装了您的业务规则。有关详细信息,请参阅此处: Using a servlet filter to limit the number of instances of a component per page or parsys
此方法可让您管理每页或每parsys
个项目的数量,并以其他提供的解决方案无法实现的方式应用其他可能复杂的业务规则。