如何限制组件每页只添加一次

问题描述 投票:3回答:6

如何限制CQ5 / Custom组件每页只添加一次。当作者要将第二次相同的组件添加到同一页面时,我想限制组件拖放到页面中。

cq5 aem
6个回答
5
投票

一种选择是将组件直接包含在模板的JSP中,并将其从sidekick中的可用组件列表中排除。为此,请将组件直接添加到JSP(此示例中的基础轮播):

<cq:include path="carousel" resourceType="foundation/components/carousel" />

要从sidekick中隐藏组件,请设置:

componentGroup: .hidden

或使用设计模式将其从“允许的组件”列表中排除。

如果您需要允许用户创建没有此组件的页面,您可以提供第二个模板,省略cq:include


3
投票

谢谢Rampant,我已经按照您的方法和链接说明了。 Posting link again : please follow this blog这真的很有帮助。无论我做了什么,我都会发布实现。它对我来说很好。绝对可以提高代码质量,这是原始代码,仅供参考。

1.Servlet过滤器

请记住,如果任何资源被引用,则此过滤器将执行。因此,您需要在最后过滤内容以进行进一步处理。附: 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类

    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);

而已 !!!你已准备好出发。


1
投票

这些选项看起来都不容易实现。我发现的最佳方法是使用ACS Commons Implementation,它非常简单,可以被任何项目采用。

这是链接以及如何配置它:https://github.com/Adobe-Consulting-Services/acs-aem-commons/pull/639

享受编码!!!


0
投票

如果不对ui代码进行大规模的黑客攻击,你就无法阻止它,即便如此,你只能从ui的一个方面阻止它。还有crxde,然后是POST内容的能力。

如果这确实是一项要求,最好的方法可能如下:

  1. 让组件检查pageContext对象中的特殊值(使用REQUEST_SCOPE)
  2. 如果找不到值,则渲染组件和设置值
  3. 否则,打印出一个组件只能使用一次的消息

请注意,您无法阻止显示对话框,但至少作者已指示该特定组件只能使用一次。


0
投票

听起来需要澄清要求(并理解为什么)。

如果可以对作者进行培训,则让他们通过创作和审核工作流程来管理组件的限制。

如果只有一个固定位置可以显示组件,那么页面组件应该包含内容组件,并让组件具有“启用”切换属性以确定它是否应该呈现任何内容。组件的组应该是.hidden以防止从sidekick拖动。

如果组件有一组固定的位置,则页面组件可以有一个位置列表的下拉列表(包括“无”)。然后,页面呈现组件将有条件地将组件包括在正确的位置。同样,防止从sidekick拖动组件。

在“难以想象”的情况下,组件可以出现在页面的任何位置,由作者添加,但仅限于1个实例 - 使用包装器组件来管理包括(不可碎片的)组件。让作者在页面上拖动包装器多次,但包装器应查询页面的资源并确定它是否是第一个实例,如果是,则包括结束组件。否则,包装器什么都不做。

根据我们的经验(在CQ上> 2年),通过代码实现这种类型的业务规则会产生一个脆弱的解决方案。此外,要求有改变的习惯。如果通过代码强制执行,则需要开发工作,而不是让作者更快更优雅地进行更改。


0
投票

这些选择都不是那么好。如果您真的想要一个强大的解决方案来解决这个问题(限制页面上没有硬编码位置的项目数),那么最好的方法是使用servlet过滤器链OSGI服务,您可以在其中管理实例数,然后使用资源解析器来删除违规实例。

基本要点是:

  1. 使用cq:editConfig刷新编辑页面
  2. 创建一个实现javax.servlet.Filter的OSGI服务,该服务封装了您的业务规则。
  3. 根据业务规则使用过滤器删除多余的组件
  4. 继续页面处理。

有关详细信息,请参阅此处:Using a servlet filter to limit the number of instances of a component per page or parsys

这种方法可以让您管理每页或每个parsys的项目数,并以其他提供的解决方案根本无法应用的方式应用其他可能复杂的业务规则。

© www.soinside.com 2019 - 2024. All rights reserved.