メンバーがコミュニティ機能と対話する際には、通知やゲーミフィケーション(スコアおよびバッジ)のような非同期リスナーを呼び出す OSGi イベントが送信されます。
コンポーネントの SocialEvent インスタンスでは、トピックに対して発生するアクションがイベントとして記録されます。SocialEvent には、アクションに関連付けられている動詞を返すメソッドが用意されています。アクションと動詞には、n-1 の関係があります。
次の各表では、このリリースに用意されているコミュニティコンポーネントで使用可能なトピックごとに、それぞれ定義されている動詞の説明を示します。
カレンダーコンポーネント
SocialEvent トピック = com/adobe/cq/social/calendar
動詞 | 説明 |
POST | メンバーがカレンダーイベントを作成する |
ADD | メンバーがカレンダーイベントについてコメントする |
UPDATE | メンバーのカレンダーイベントまたはコメントが編集される |
DELETE | メンバーのカレンダーイベントまたはコメントが削除される |
コメントコンポーネント
SocialEvent トピック = com/adobe/cq/social/comment
動詞 | 説明 |
POST | メンバーがコメントを作成する |
ADD | メンバーがコメントに返信する |
UPDATE | メンバーのコメントが編集される |
DELETE | メンバーのコメントが削除される |
ファイルライブラリコンポーネント
SocialEvent トピック = com/adobe/cq/social/fileLibrary
動詞 | 説明 |
POST | メンバーがフォルダーを作成する |
ATTACH | メンバーがファイルをアップロードする |
UPDATE | メンバーがフォルダーまたはファイルを更新する |
DELETE | メンバーがフォルダーまたはファイルを削除する |
フォーラムコンポーネント
SocialEvent トピック = com/adobe/cq/social/forum
動詞 | 説明 |
POST | メンバーがフォーラムトピックを作成する |
ADD | メンバーがフォーラムトピックに返信する |
UPDATE | メンバーのフォーラムトピックまたは返信が編集される |
DELETE | メンバーのフォーラムトピックまたは返信が削除される |
ジャーナルコンポーネント
SocialEvent トピック = com/adobe/cq/social/journal
動詞 | 説明 |
POST | メンバーがブログ記事を作成する |
ADD | メンバーがブログ記事にコメントする |
UPDATE | メンバーのブログ記事またはコメントが編集される |
DELETE | メンバーのブログ記事またはコメントが削除される |
Q&A コンポーネント
SocialEvent トピック = com/adobe/cq/social/qna
動詞 | 説明 |
POST | メンバーが Q&A の質問を作成する |
ADD | メンバーが Q&A の回答を作成する |
UPDATE | メンバーの Q&A の質問または回答が編集される |
SELECT | メンバーの回答が選択される |
UNSELECT | メンバーの回答の選択が解除される |
DELETE | メンバーの Q&A の質問または回答が削除される |
レビューコンポーネント
SocialEvent トピック = com/adobe/cq/social/review
動詞 | 説明 |
POST | メンバーがレビューを作成する |
UPDATE | メンバーのレビューが編集される |
DELETE | メンバーのレビューが削除される |
評価コンポーネント
SocialEvent topic = com/adobe/cq/social/tally
動詞 | 説明 |
ADD RATING | メンバーのコンテンツの評価が上がった |
REMOVE RATING | メンバーのコンテンツの評価が下がった |
投票コンポーネント
SocialEvent topic = com/adobe/cq/social/tally
動詞 | 説明 |
ADD VOTING | メンバーのコンテンツに賛成票が投じられた |
REMOVE VOTING | メンバーのコンテンツに反対票が投じられた |
モデレート対応コンポーネント
SocialEvent トピック = com/adobe/cq/social/moderation
動詞 | 説明 |
DENY | メンバーのコンテンツが拒否される |
FLAG-AS-INAPPROPRIATE | メンバーのコンテンツにフラグが付けられる |
UNFLAG-AS-INAPPROPRIATE | メンバーのコンテンツのフラグが解除される |
ACCEPT | メンバーのコンテンツがモデレーターにより承認される |
CLOSE | メンバーがコメントの編集と返信を閉じる |
OPEN | メンバーがコメントを再オープン |
カスタムコンポーネントの場合、SocialEvent 抽象クラスを拡張して、コンポーネントのイベントがトピックに対して発生するアクションとして記録されるようにする必要があります。
カスタムイベントは、各アクションに対して適切な動詞が返されるように、メソッド getVerb() をオーバーライドします。アクションに対して返される動詞の中には、共通して使用されるもの(POST など)もあれば、コンポーネント専用のもの(ADD RATING など)もあります。アクションと動詞には、n-1 の関係があります。
注意:
カスタム拡張が製品の既存の実装よりも低いランクで登録されていることを確認します。
package com.mycompany.recipe; import org.osgi.service.event.Event; import com.adobe.cq.social.scf.core.SocialEvent; import com.adobe.granite.activitystreams.ObjectTypes; import com.adobe.granite.activitystreams.Verbs; /* * The Recipe type, passed to RecipeEvent(), would be a custom Recipe class * that extends either * com.adobe.cq.social.scf.SocialComponent * or * com.adobe.cq.social.scf.SocialCollectionComponent * See https://docs.adobe.com/docs/en/aem/6-2/develop/communities/scf/server-customize.html */ /** * Defines events that are triggered on a custom component, "Recipe". */ public class RecipeEvent extends SocialEvent<RecipeEvent.RecipeActions> { private static final long serialVersionUID = 1L; protected static final String PARENT_PATH = "PARENT_PATH"; /** * The event topic suffix for Recipe events */ public static final String RECIPE_TOPIC = "recipe"; /** * @param recipe - the recipe resource on which the event was triggered * @param userId - the user id of the user who triggered the action * @param action - the recipe action that triggered this event */ public RecipeEvent(final Recipe recipe, final String userId, final RecipeEvent.RecipeActions action) { String recipePath = recipe.getResource().getPath(); String parentPath = (recipe.getParentComponent() != null) ? recipe.getParentComponent().getResource().getPath() : recipe.getSourceComponentId(); this(recipePath, userId, parentPath, action); } /** * @param recipePath - the path to the recipe resource (jcr node) on which the event was triggered * @param userId - the user id of the user who triggered the action * @param parentPath - the path to the parent node of the recipe resource * @param action - the recipe action that triggered this event */ public RecipeEvent(final String recipePath, final String userId, final String parentPath) { super(RECIPE_TOPIC, recipePath, userId, action, new BaseEventObject(recipePath, ObjectTypes.ARTICLE), new BaseEventObject(parentPath, ObjectTypes.COLLECTION), new HashMap<String, Object>(1) { private static final long serialVersionUID = 1L; { if (parentPath != null) { this.put(PARENT_PATH, parentPath); } } }); } private RecipeEvent (final Event event) { super(event); } /** * List of available recipe actions that can trigger a recipe event. */ public static enum RecipeActions implements SocialEvent.SocialActions { RecipeAdded, RecipeModified, RecipeDeleted; @Override public String getVerb() { switch (this) { case RecipeAdded: return Verbs.POST; case RecipeModified: return Verbs.UPDATE; case RecipeDeleted: return Verbs.DELETE; default: throw new IllegalArgumentException("Unsupported action"); } } } }
アクティビティストリームに現れる内容を変更するために、イベントをリスニングできます。
次の疑似コードのサンプルでは、コメントコンポーネントの DELETE イベントをアクティビティストリームから削除します。
最新の機能パックが必要です。
package my.company.comments; import java.util.Collections; import java.util.Map; import org.apache.commons.lang.StringUtils; import org.apache.felix.scr.annotations.Activate; import org.apache.felix.scr.annotations.Component; import org.apache.felix.scr.annotations.Modified; import org.apache.felix.scr.annotations.Property; import org.apache.felix.scr.annotations.Service; import org.apache.sling.api.resource.Resource; import org.apache.sling.commons.osgi.PropertiesUtil; import org.osgi.service.component.ComponentContext; import com.adobe.cq.social.activitystreams.listener.api.ActivityStreamProviderExtension; import com.adobe.cq.social.commons.events.CommentEvent.CommentActions; import com.adobe.cq.social.scf.core.SocialEvent; @Service @Component(metatype = true, label = "My Comment Delete Event Filter", description = "Prevents comment DELETE events from showing up in activity streams") public class CommentDeleteEventActivityFilter implements ActivityStreamProviderExtension { @Property(name = "ranking", intValue = 10) protected int ranking; @Activate public void activate(final ComponentContext ctx) { ranking = PropertiesUtil.toInteger(ctx.getProperties().get("ranking"), 10); } @Modified public void update(final Map<String, Object> props) { ranking = PropertiesUtil.toInteger(props.get("ranking"), 10); } @Override public boolean evaluate(final SocialEvent<?> evt, final Resource resource) { if (evt.getAction() != null && evt.getAction() instanceof SocialEvent.SocialActions) { final SocialEvent.SocialActions action = evt.getAction(); if (StringUtils.equals(action.getVerb(), CommentActions.DELETED.getVerb())) { return false; } } return true; } @Override public Map<String, ? extends Object> getActivityProperties(final SocialEvent<?> arg0, final Resource arg1) { return Collections.<String, Object>emptyMap(); } @Override public Map<String, ? extends Object> getActorProperties(final SocialEvent<?> arg0, final Resource arg1) { return Collections.<String, Object>emptyMap(); } @Override public String getName() { return "My Comment Delete Event Filter"; } @Override public Map<String, ? extends Object> getObjectProperties(final SocialEvent<?> arg0, final Resource arg1) { return Collections.<String, Object>emptyMap(); } /* Ensure a custom extension is registered with a ranking lower than any existing implementation in the product. */ @Override public int getRanking() { return this.ranking; } @Override public Map<String, ? extends Object> getTargetProperties(final SocialEvent<?> arg0, final Resource arg1) { return Collections.<String, Object>emptyMap(); } @Override public String[] getStreamProviderPid() { return new String[]{"*"}; } }