How can I specify the opposite of a customer segment

95 views Asked by At

In components you don't have an exclusion segment: enter image description here

My subject is to create the opposite of a customer segment.
If I have a customer segment DEVELOPER then I would like to create EXCEPT_DEVELOPER ("Everyone can see this component except DEVELOPER").

We want to override/enhance the core method of Intershop which retrieve the assignement.
The goal to check if the user is in the EXCEPT customer segment dynamically.

...
...
forEach(CustomerSegment csItem : customerSegmentList) { 
   if(csItem.contains("EXCEPT")){ //EXCEPT~DEVELOPER
      String customerSegmentToExcept = csItem.split("~")[1]; //DEVELOPER
      if(currentUser.isIn(customerSegmentToExcept)) //current user is in customer segment DEVELOPER
         return "Don't display component";
   }
}
...
...
return "Display component";

What do you think ? Do you have some advice or another method to achieve this please ? Thank you !

2

There are 2 answers

0
Johannes Metzner On BEST ANSWER

The way to override or enhance the pagelet assignment lookup is to provide a custom PageletVisibilityFilter. In 2016 I gave a speech on that topic at the Intershop Developer Conference.

In general, they are wired in a position/priority based list of out-of-the-box filters and they are executed from highest to lowest priority when a content-entry-point (e.g slot, placeholder, page, include) is rendered.

You need to implement that interface:

/**
 * A pagelet visibility filter is a class that decides if a pagelet 
 * is visible to the end user or not. The <code>decide</code> method is invoked 
 * to get the decision from the implementation. 
 */
public interface PageletVisibilityFilter
{
    /**
     * Returns the decision if a pagelet should be filtered or not.
     * 
     * @param pagelet the pagelet which visibility is tested
     * 
     * @return the decision for the pagelet visibility
     * 
     * @see PageletVisibilityFilterReply
     */
    public PageletVisibilityFilterReply decide(Pagelet pagelet);
}

And register that implementation with the component framework. A quick look into app_sf_responsive revealed the place where to instantiate and wire your instance.

<instance name="pageletABTestGroupVisibilityFilter" with="PageletABTestGroupVisibilityFilter" />
<fulfill requirement="pageletVisibilityFilter" of="pageletVisibilityFilterCtnr" with="pageletABTestGroupVisibilityFilter" />

Be prepared to override the original out-of-the-box filter for customer segments to express that complement logic your're trying to achieve.

0
P Jain On

This is inline with what Johannes recommended. Here is how I went about it

  1. Write an implementations.component
<implementation name="PageletUserGroupVisibilityFilterNegated" class="YOUR.CUSTOM.JAVA.CLASS">
  <implements contract="PageletVisibilityFilter" />
</implementation>   
  1. Write an instances.component
<instance name="pageletUserGroupVisibilityFilterNegated" with="PageletUserGroupVisibilityFilterNegated" />
<replace name="pageletUserGroupVisibilityFilter" with="PageletUserGroupVisibilityFilterNegated" delegate="pageletUserGroupVisibilityFilterNegated" />
  1. Now write the class PageletUserGroupVisibilityFilterNegated to support this wiring. Get the OOB PageletUserGroupVisibilityFilter.java and change the way decide method returns accept. Here is the key code snippet of the java. In my logic if there is a Customer Segment ID which ends with "EXCLUDE" then the logic switches else it continues to operate with original logic.
final Collection<UserGroup> currentUserUserGroups = getCurrentUserGroups();
boolean accept = false;
for(final Assignment<Pagelet, UserGroup> assignment : assignments)
{
    if (currentUserUserGroups.contains(assignment.getTo()))
    {
         if(assignment.getTo().getID().endsWith("_EXCLUDE"))
         {
             //return DENY as soon as at least one user group of the assignment is contained within current user's user groups and ends with _EXCLUDE
             return PageletVisibilityFilterReply.DENY;
         }
         else if (currentUserUserGroups.contains(assignment.getTo()))
         {
             accept = true;
         }
    }
}
if (accept) {
    //return ACCEPT as at least one user group of the assignment is contained within current user's user groups
    return PageletVisibilityFilterReply.ACCEPT;
}