Forum
* Erweitert, so daß per Konfiguration eingestellt werden kann, ob ein Autor einen eigenen Beitrag löschen darf, falls es der letzte Eintrag im Thread ist * Dateien werden nun als Download Verknüpft, nicht mehr als direkte Ansicht git-svn-id: https://svn.libreccm.org/ccm/trunk@1407 8810af33-2d31-482b-a856-94f89814c4dfmaster
parent
d29337b7f1
commit
e7f5bd0a98
|
|
@ -731,6 +731,18 @@ public class Forum extends Application {
|
||||||
party)));
|
party)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* checks if the user can delete posts in this forum
|
||||||
|
*/
|
||||||
|
public boolean canDelete(Party party) {
|
||||||
|
return ((getConfig().canAdminEditPosts()
|
||||||
|
|| getConfig().canAuthorDeletePosts())
|
||||||
|
&& PermissionService.checkPermission(
|
||||||
|
new PermissionDescriptor(PrivilegeDescriptor.DELETE,
|
||||||
|
this,
|
||||||
|
party)));
|
||||||
|
}
|
||||||
|
|
||||||
public boolean canAdminister(Party party) {
|
public boolean canAdminister(Party party) {
|
||||||
return PermissionService.checkPermission(
|
return PermissionService.checkPermission(
|
||||||
new PermissionDescriptor(PrivilegeDescriptor.ADMIN,
|
new PermissionDescriptor(PrivilegeDescriptor.ADMIN,
|
||||||
|
|
|
||||||
|
|
@ -49,6 +49,7 @@ public class ForumConfig extends AbstractConfig {
|
||||||
|
|
||||||
private Parameter m_adminEditPosts;
|
private Parameter m_adminEditPosts;
|
||||||
private Parameter m_authorEditPosts;
|
private Parameter m_authorEditPosts;
|
||||||
|
private Parameter m_authorDeletePosts;
|
||||||
private Parameter m_digestUserEmail;
|
private Parameter m_digestUserEmail;
|
||||||
private Parameter m_replyHostName;
|
private Parameter m_replyHostName;
|
||||||
private Parameter m_disablePageCaching;
|
private Parameter m_disablePageCaching;
|
||||||
|
|
@ -74,6 +75,10 @@ public class ForumConfig extends AbstractConfig {
|
||||||
"com.arsdigita.forum.author_can_edit_posts",
|
"com.arsdigita.forum.author_can_edit_posts",
|
||||||
Parameter.REQUIRED,
|
Parameter.REQUIRED,
|
||||||
Boolean.TRUE);
|
Boolean.TRUE);
|
||||||
|
m_authorDeletePosts = new BooleanParameter(
|
||||||
|
"com.arsdigita.forum.author_can_delete_posts",
|
||||||
|
Parameter.REQUIRED,
|
||||||
|
Boolean.TRUE);
|
||||||
m_replyHostName = new StringParameter(
|
m_replyHostName = new StringParameter(
|
||||||
"com.arsdigita.forum.reply_host_name",
|
"com.arsdigita.forum.reply_host_name",
|
||||||
Parameter.OPTIONAL,
|
Parameter.OPTIONAL,
|
||||||
|
|
@ -134,6 +139,7 @@ public class ForumConfig extends AbstractConfig {
|
||||||
register(m_digestUserEmail);
|
register(m_digestUserEmail);
|
||||||
register(m_adminEditPosts);
|
register(m_adminEditPosts);
|
||||||
register(m_authorEditPosts);
|
register(m_authorEditPosts);
|
||||||
|
register(m_authorDeletePosts);
|
||||||
register(m_replyHostName);
|
register(m_replyHostName);
|
||||||
register(m_adapters);
|
register(m_adapters);
|
||||||
register(m_disablePageCaching);
|
register(m_disablePageCaching);
|
||||||
|
|
@ -162,6 +168,10 @@ public class ForumConfig extends AbstractConfig {
|
||||||
return ((Boolean)get(m_authorEditPosts)).booleanValue();
|
return ((Boolean)get(m_authorEditPosts)).booleanValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
boolean canAuthorDeletePosts() {
|
||||||
|
return ((Boolean)get(m_authorDeletePosts)).booleanValue();
|
||||||
|
}
|
||||||
|
|
||||||
public String getDigestUserEmail() {
|
public String getDigestUserEmail() {
|
||||||
String email = (String)get(m_digestUserEmail);
|
String email = (String)get(m_digestUserEmail);
|
||||||
if (email == null) {
|
if (email == null) {
|
||||||
|
|
|
||||||
|
|
@ -24,10 +24,15 @@ com.arsdigita.forum.admin_only_to_create_topics.format=[boolean]
|
||||||
com.arsdigita.forum.admin_only_to_create_topics.example=true|false
|
com.arsdigita.forum.admin_only_to_create_topics.example=true|false
|
||||||
|
|
||||||
com.arsdigita.forum.author_can_edit_posts.title=Authors can edit posts
|
com.arsdigita.forum.author_can_edit_posts.title=Authors can edit posts
|
||||||
com.arsdigita.forum.author_can_edit_posts.purpose=Whether authors can edijt their posts
|
com.arsdigita.forum.author_can_edit_posts.purpose=Whether authors can edit their posts
|
||||||
com.arsdigita.forum.author_can_edit_posts.format=[boolean]
|
com.arsdigita.forum.author_can_edit_posts.format=[boolean]
|
||||||
com.arsdigita.forum.author_can_edit_posts.example=true|false
|
com.arsdigita.forum.author_can_edit_posts.example=true|false
|
||||||
|
|
||||||
|
com.arsdigita.forum.author_can_delete_posts.title=Authors can delete posts
|
||||||
|
com.arsdigita.forum.author_can_delete_posts.purpose=Whether authors can delete their posts as long it is the last in the thread
|
||||||
|
com.arsdigita.forum.author_can_delete_posts.format=[boolean]
|
||||||
|
com.arsdigita.forum.author_can_delete_posts.example=true|false
|
||||||
|
|
||||||
com.arsdigita.forum.disable_page_caching.title=Disable client & middleware page caching
|
com.arsdigita.forum.disable_page_caching.title=Disable client & middleware page caching
|
||||||
com.arsdigita.forum.disable_page_caching.purpose=Disable caching, particularly for situations where users share PCs
|
com.arsdigita.forum.disable_page_caching.purpose=Disable caching, particularly for situations where users share PCs
|
||||||
com.arsdigita.forum.disable_page_caching.format=[boolean]
|
com.arsdigita.forum.disable_page_caching.format=[boolean]
|
||||||
|
|
|
||||||
|
|
@ -157,6 +157,16 @@ public final class ForumContext {
|
||||||
return m_canAdminister;
|
return m_canAdminister;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public boolean canDelete(Post post) {
|
||||||
|
Party party = Kernel.getContext().getParty();
|
||||||
|
|
||||||
|
return post.canDelete(party);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @return
|
* @return
|
||||||
|
|
|
||||||
|
|
@ -114,39 +114,31 @@ import com.arsdigita.util.Assert;
|
||||||
* @author Nobuko Asakai (nasakai@redhat.com)
|
* @author Nobuko Asakai (nasakai@redhat.com)
|
||||||
*/
|
*/
|
||||||
public class Post extends ThreadedMessage {
|
public class Post extends ThreadedMessage {
|
||||||
private static final Logger s_log = Logger.getLogger(Post.class);
|
|
||||||
|
|
||||||
|
private static final Logger s_log = Logger.getLogger(Post.class);
|
||||||
/** PDL property for marking the approval state of a message, one
|
/** PDL property for marking the approval state of a message, one
|
||||||
* of 'approved', 'rejected', 'reapprove', 'supressed' */
|
* of 'approved', 'rejected', 'reapprove', 'supressed' */
|
||||||
public static final String STATUS = "status";
|
public static final String STATUS = "status";
|
||||||
|
|
||||||
/** ID of the administrator who last changed the status of a
|
/** ID of the administrator who last changed the status of a
|
||||||
* message */
|
* message */
|
||||||
public static final String MODERATOR = "moderator";
|
public static final String MODERATOR = "moderator";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 0..n association with PostImageAttachments
|
* 0..n association with PostImageAttachments
|
||||||
*/
|
*/
|
||||||
public static final String IMAGE_ATTACHMENTS = "images";
|
public static final String IMAGE_ATTACHMENTS = "images";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 0..n association with PostFileAttachments
|
* 0..n association with PostFileAttachments
|
||||||
*/
|
*/
|
||||||
public static final String FILE_ATTACHMENTS = "files";
|
public static final String FILE_ATTACHMENTS = "files";
|
||||||
|
|
||||||
/** The status strings */
|
/** The status strings */
|
||||||
public static final String PENDING = "pending";
|
public static final String PENDING = "pending";
|
||||||
public static final String APPROVED = "approved";
|
public static final String APPROVED = "approved";
|
||||||
public static final String REJECTED = "rejected";
|
public static final String REJECTED = "rejected";
|
||||||
public static final String REAPPROVE = "reapprove";
|
public static final String REAPPROVE = "reapprove";
|
||||||
public static final String SUPPRESSED = "suppressed";
|
public static final String SUPPRESSED = "suppressed";
|
||||||
|
|
||||||
|
|
||||||
public static final String POST_STATUS_SUBQUERY =
|
public static final String POST_STATUS_SUBQUERY =
|
||||||
"com.arsdigita.forum.threadModerationStatus";
|
"com.arsdigita.forum.threadModerationStatus";
|
||||||
|
|
||||||
private Party m_moderator;
|
private Party m_moderator;
|
||||||
|
|
||||||
// referred to afterSave method
|
// referred to afterSave method
|
||||||
private boolean m_wasNew;
|
private boolean m_wasNew;
|
||||||
|
|
||||||
|
|
@ -155,13 +147,13 @@ public class Post extends ThreadedMessage {
|
||||||
* other words, all bboard messages are ThreadedMessages.
|
* other words, all bboard messages are ThreadedMessages.
|
||||||
*/
|
*/
|
||||||
public static final String BASE_DATA_OBJECT_TYPE =
|
public static final String BASE_DATA_OBJECT_TYPE =
|
||||||
"com.arsdigita.forum.Post";
|
"com.arsdigita.forum.Post";
|
||||||
|
|
||||||
private Post() {
|
private Post() {
|
||||||
this(BASE_DATA_OBJECT_TYPE);
|
this(BASE_DATA_OBJECT_TYPE);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Post(String typeName) {
|
public Post(String typeName) {
|
||||||
super(typeName);
|
super(typeName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -169,9 +161,9 @@ public class Post extends ThreadedMessage {
|
||||||
super(oid);
|
super(oid);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Post(BigDecimal id) {
|
public Post(BigDecimal id) {
|
||||||
this(new OID(BASE_DATA_OBJECT_TYPE, id));
|
this(new OID(BASE_DATA_OBJECT_TYPE, id));
|
||||||
}
|
}
|
||||||
|
|
||||||
public Post(DataObject obj) {
|
public Post(DataObject obj) {
|
||||||
super(obj);
|
super(obj);
|
||||||
|
|
@ -217,10 +209,10 @@ public class Post extends ThreadedMessage {
|
||||||
|
|
||||||
BigDecimal id = getID();
|
BigDecimal id = getID();
|
||||||
// XXX this isn't really the host we want
|
// XXX this isn't really the host we want
|
||||||
setRFCMessageID(id + ".bboard@" +
|
setRFCMessageID(id + ".bboard@"
|
||||||
Forum.getConfig().getReplyHostName());
|
+ Forum.getConfig().getReplyHostName());
|
||||||
setReplyTo(getRefersTo() + ".bboard@" +
|
setReplyTo(getRefersTo() + ".bboard@"
|
||||||
Forum.getConfig().getReplyHostName());
|
+ Forum.getConfig().getReplyHostName());
|
||||||
|
|
||||||
super.beforeSave();
|
super.beforeSave();
|
||||||
|
|
||||||
|
|
@ -239,8 +231,8 @@ public class Post extends ThreadedMessage {
|
||||||
|
|
||||||
s_log.info("Setting context for " + getOID() + " to " + root.getOID());
|
s_log.info("Setting context for " + getOID() + " to " + root.getOID());
|
||||||
PermissionService.setContext(this, root);
|
PermissionService.setContext(this, root);
|
||||||
s_log.info( "Setting context for " + root.getOID() + " to " +
|
s_log.info("Setting context for " + root.getOID() + " to "
|
||||||
forum.getOID());
|
+ forum.getOID());
|
||||||
PermissionService.setContext(root, forum);
|
PermissionService.setContext(root, forum);
|
||||||
// originally this was created in beforeSave, but this was when only
|
// originally this was created in beforeSave, but this was when only
|
||||||
// noticeboard (reply disabled) forums could have a lifecycle. Now that
|
// noticeboard (reply disabled) forums could have a lifecycle. Now that
|
||||||
|
|
@ -251,7 +243,7 @@ public class Post extends ThreadedMessage {
|
||||||
if (m_wasNew) {
|
if (m_wasNew) {
|
||||||
if (getRoot() == null && forum.getExpireAfter() > 0) {
|
if (getRoot() == null && forum.getExpireAfter() > 0) {
|
||||||
s_log.info("Creating expiration lifecycle for " + getOID());
|
s_log.info("Creating expiration lifecycle for " + getOID());
|
||||||
setLifecycle(forum.getLifecycleDefinition());
|
setLifecycle(forum.getLifecycleDefinition());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
m_wasNew = false;
|
m_wasNew = false;
|
||||||
|
|
@ -263,7 +255,7 @@ public class Post extends ThreadedMessage {
|
||||||
while (files.next()) {
|
while (files.next()) {
|
||||||
PostFileAttachment file =
|
PostFileAttachment file =
|
||||||
(PostFileAttachment) DomainObjectFactory.newInstance(
|
(PostFileAttachment) DomainObjectFactory.newInstance(
|
||||||
files.getDataObject());
|
files.getDataObject());
|
||||||
if (getStatus().equals(APPROVED)) {
|
if (getStatus().equals(APPROVED)) {
|
||||||
file.setLive();
|
file.setLive();
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -277,15 +269,16 @@ public class Post extends ThreadedMessage {
|
||||||
/**
|
/**
|
||||||
* Sends out the notifications for any subscriptions to the forum
|
* Sends out the notifications for any subscriptions to the forum
|
||||||
* or thread to which this message belongs. Only sends
|
* or thread to which this message belongs. Only sends
|
||||||
* notifications if the post is approved.
|
* notifications if the post is approved.
|
||||||
*/
|
*/
|
||||||
public void sendNotifications(final String context) {
|
public void sendNotifications(final String context) {
|
||||||
KernelExcursion ex = new KernelExcursion() {
|
KernelExcursion ex = new KernelExcursion() {
|
||||||
protected void excurse() {
|
|
||||||
setEffectiveParty(Kernel.getSystemParty());
|
protected void excurse() {
|
||||||
doSendNotifications(context);
|
setEffectiveParty(Kernel.getSystemParty());
|
||||||
}
|
doSendNotifications(context);
|
||||||
};
|
}
|
||||||
|
};
|
||||||
ex.run();
|
ex.run();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -295,59 +288,58 @@ public class Post extends ThreadedMessage {
|
||||||
*/
|
*/
|
||||||
public void sendModeratorAlerts() {
|
public void sendModeratorAlerts() {
|
||||||
|
|
||||||
if (!getStatus().equals(APPROVED)) {
|
if (!getStatus().equals(APPROVED)) {
|
||||||
// don't send if pre-approved (ie posted by a moderator)
|
// don't send if pre-approved (ie posted by a moderator)
|
||||||
KernelExcursion ex = new KernelExcursion() {
|
KernelExcursion ex = new KernelExcursion() {
|
||||||
|
|
||||||
protected void excurse() {
|
protected void excurse() {
|
||||||
setEffectiveParty(Kernel.getSystemParty());
|
setEffectiveParty(Kernel.getSystemParty());
|
||||||
doSendModeratorAlerts();
|
doSendModeratorAlerts();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
ex.run();
|
ex.run();
|
||||||
} else {
|
} else {
|
||||||
s_log.debug("not sending moderator alerts because the post " +
|
s_log.debug("not sending moderator alerts because the post "
|
||||||
"was pre-approved (created by an approver)");
|
+ "was pre-approved (created by an approver)");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void doSendNotifications(String context) {
|
private void doSendNotifications(String context) {
|
||||||
s_log.debug("sending user notifications");
|
s_log.debug("sending user notifications");
|
||||||
Forum forum = getForum();
|
Forum forum = getForum();
|
||||||
if (getStatus().equals(APPROVED)) {
|
if (getStatus().equals(APPROVED)) {
|
||||||
s_log.debug("Sending forum level subsriptions");
|
s_log.debug("Sending forum level subsriptions");
|
||||||
DataCollection subscriptions = forum.getSubscriptions();
|
DataCollection subscriptions = forum.getSubscriptions();
|
||||||
|
|
||||||
while (subscriptions.next()) {
|
while (subscriptions.next()) {
|
||||||
ForumSubscription subscription = (ForumSubscription)
|
ForumSubscription subscription = (ForumSubscription) DomainObjectFactory.newInstance(
|
||||||
DomainObjectFactory.newInstance(
|
|
||||||
subscriptions.getDataObject());
|
subscriptions.getDataObject());
|
||||||
s_log.debug("notification to " + subscription.getOID());
|
s_log.debug("notification to " + subscription.getOID());
|
||||||
|
|
||||||
subscription.sendNotification(Post.this, Forum.getConfig()
|
subscription.sendNotification(Post.this, Forum.getConfig().deleteNotifications());
|
||||||
.deleteNotifications());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
s_log.debug("Sending thread level subsriptions");
|
s_log.debug("Sending thread level subsriptions");
|
||||||
if (context == null || !context.equals(PostForm.NEW_CONTEXT)) {
|
if (context == null || !context.equals(PostForm.NEW_CONTEXT)) {
|
||||||
|
|
||||||
ThreadSubscription sub =
|
ThreadSubscription sub =
|
||||||
ThreadSubscription.getThreadSubscription(getThread());
|
ThreadSubscription.getThreadSubscription(getThread());
|
||||||
if (sub == null) {
|
if (sub == null) {
|
||||||
s_log.error(
|
s_log.error(
|
||||||
"Got a null ThreadSubscription from "
|
"Got a null ThreadSubscription from "
|
||||||
+ "Post # "
|
+ "Post # "
|
||||||
+ getID());
|
+ getID());
|
||||||
} else {
|
} else {
|
||||||
sub.sendNotification(this, Forum.getConfig().deleteNotifications());
|
sub.sendNotification(this, Forum.getConfig().deleteNotifications());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
s_log.debug("Not sending notifications because the " +
|
s_log.debug("Not sending notifications because the "
|
||||||
"message is not approved");
|
+ "message is not approved");
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void doSendModeratorAlerts() {
|
private void doSendModeratorAlerts() {
|
||||||
if (s_log.isDebugEnabled()) {
|
if (s_log.isDebugEnabled()) {
|
||||||
|
|
@ -361,18 +353,16 @@ public class Post extends ThreadedMessage {
|
||||||
DataCollection alerts = forum.getModerationAlerts();
|
DataCollection alerts = forum.getModerationAlerts();
|
||||||
|
|
||||||
while (alerts.next()) {
|
while (alerts.next()) {
|
||||||
ModerationAlert alert
|
ModerationAlert alert = (ModerationAlert) DomainObjectFactory.newInstance(
|
||||||
= (ModerationAlert)
|
alerts.getDataObject());
|
||||||
DomainObjectFactory.newInstance(
|
s_log.debug("Processing moderation alert " + alert.getOID());
|
||||||
alerts.getDataObject());
|
alert.sendNotification(this, Forum.getConfig().deleteNotifications());
|
||||||
s_log.debug("Processing moderation alert " + alert.getOID());
|
|
||||||
alert.sendNotification(this, Forum.getConfig().deleteNotifications());
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
s_log.debug("Not sending moderator alerts because the " +
|
s_log.debug("Not sending moderator alerts because the "
|
||||||
"forum is not moderated");
|
+ "forum is not moderated");
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the Forum that contains this post. Just a wrapper for the
|
* Set the Forum that contains this post. Just a wrapper for the
|
||||||
|
|
@ -381,7 +371,6 @@ public class Post extends ThreadedMessage {
|
||||||
*
|
*
|
||||||
* @param forum the Forum that contains this post.
|
* @param forum the Forum that contains this post.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public void setForum(Forum forum) {
|
public void setForum(Forum forum) {
|
||||||
setRefersTo(forum);
|
setRefersTo(forum);
|
||||||
}
|
}
|
||||||
|
|
@ -399,12 +388,10 @@ public class Post extends ThreadedMessage {
|
||||||
*
|
*
|
||||||
* @param category the Category for this post.
|
* @param category the Category for this post.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public void mapCategory(Category category)
|
public void mapCategory(Category category)
|
||||||
throws PersistenceException {
|
throws PersistenceException {
|
||||||
if (isNew()) {
|
if (isNew()) {
|
||||||
throw new PersistenceException
|
throw new PersistenceException("Post must be persistent to map categories");
|
||||||
("Post must be persistent to map categories");
|
|
||||||
}
|
}
|
||||||
category.addChild(this);
|
category.addChild(this);
|
||||||
category.save();
|
category.save();
|
||||||
|
|
@ -413,34 +400,33 @@ public class Post extends ThreadedMessage {
|
||||||
/**
|
/**
|
||||||
* Clears categories for this post. Used when editing a post
|
* Clears categories for this post. Used when editing a post
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public void clearCategories() {
|
public void clearCategories() {
|
||||||
DataCollection categories =
|
DataCollection categories =
|
||||||
SessionManager.getSession().retrieve(
|
SessionManager.getSession().retrieve(
|
||||||
Category.BASE_DATA_OBJECT_TYPE);
|
Category.BASE_DATA_OBJECT_TYPE);
|
||||||
categories.addEqualsFilter(
|
categories.addEqualsFilter(
|
||||||
Category.CHILD_OBJECTS + "." + ACSObject.ID,
|
Category.CHILD_OBJECTS + "." + ACSObject.ID,
|
||||||
getID());
|
getID());
|
||||||
while (categories.next()) {
|
while (categories.next()) {
|
||||||
Category cat =
|
Category cat =
|
||||||
(Category) DomainObjectFactory.newInstance(
|
(Category) DomainObjectFactory.newInstance(
|
||||||
categories.getDataObject());
|
categories.getDataObject());
|
||||||
cat.removeChild(this);
|
cat.removeChild(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
// above is slower than data operation implementation below,
|
// above is slower than data operation implementation below,
|
||||||
// but data op caused problems in persistence. If edited post
|
// but data op caused problems in persistence. If edited post
|
||||||
// had topic unchanged, then attempt was made to assign topic
|
// had topic unchanged, then attempt was made to assign topic
|
||||||
// category before data op had cleared existing. Hence exception
|
// category before data op had cleared existing. Hence exception
|
||||||
// - attempt to map object to same cat twice
|
// - attempt to map object to same cat twice
|
||||||
|
|
||||||
/*
|
/*
|
||||||
DataOperation clearCategories =
|
DataOperation clearCategories =
|
||||||
SessionManager.getSession().retrieveDataOperation(
|
SessionManager.getSession().retrieveDataOperation(
|
||||||
"com.arsdigita.forum.clearCategories");
|
"com.arsdigita.forum.clearCategories");
|
||||||
clearCategories.setParameter("postID", this.getID());
|
clearCategories.setParameter("postID", this.getID());
|
||||||
clearCategories.execute();
|
clearCategories.execute();
|
||||||
return;*/
|
return;*/
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -451,41 +437,41 @@ public class Post extends ThreadedMessage {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* creates a ThreadSubscription, and returns it but only if this is a root,
|
* creates a ThreadSubscription, and returns it but only if this is a root,
|
||||||
* else return null
|
* else return null
|
||||||
* Note, you must save() the Post before calling this method.
|
* Note, you must save() the Post before calling this method.
|
||||||
*/
|
*/
|
||||||
public ThreadSubscription createThreadSubscription() {
|
public ThreadSubscription createThreadSubscription() {
|
||||||
ThreadSubscription sub = null;
|
ThreadSubscription sub = null;
|
||||||
if (getRoot() == null) {
|
if (getRoot() == null) {
|
||||||
sub = new ThreadSubscription();
|
sub = new ThreadSubscription();
|
||||||
sub.setThread(getThread());
|
sub.setThread(getThread());
|
||||||
sub.save();
|
sub.save();
|
||||||
}
|
}
|
||||||
return sub;
|
return sub;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ThreadSubscription getSubscription() {
|
public ThreadSubscription getSubscription() {
|
||||||
MessageThread thread;
|
MessageThread thread;
|
||||||
if (getRoot() != null) {
|
if (getRoot() != null) {
|
||||||
thread = getRootMsg().getThread();
|
thread = getRootMsg().getThread();
|
||||||
} else {
|
} else {
|
||||||
thread = getThread();
|
thread = getThread();
|
||||||
}
|
}
|
||||||
DataCollection subscriptions =
|
DataCollection subscriptions =
|
||||||
SessionManager.getSession().retrieve(
|
SessionManager.getSession().retrieve(
|
||||||
ThreadSubscription.BASE_DATA_OBJECT_TYPE);
|
ThreadSubscription.BASE_DATA_OBJECT_TYPE);
|
||||||
subscriptions.addEqualsFilter(
|
subscriptions.addEqualsFilter(
|
||||||
ThreadSubscription.THREAD,
|
ThreadSubscription.THREAD,
|
||||||
thread.getID());
|
thread.getID());
|
||||||
ThreadSubscription subscription = null;
|
ThreadSubscription subscription = null;
|
||||||
while (subscriptions.next()) {
|
while (subscriptions.next()) {
|
||||||
subscription =
|
subscription =
|
||||||
(ThreadSubscription) DomainObjectFactory.newInstance(
|
(ThreadSubscription) DomainObjectFactory.newInstance(
|
||||||
subscriptions.getDataObject());
|
subscriptions.getDataObject());
|
||||||
|
|
||||||
}
|
}
|
||||||
return subscription;
|
return subscription;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -498,64 +484,78 @@ public class Post extends ThreadedMessage {
|
||||||
Party author = getFrom(); //determin sender / author of message
|
Party author = getFrom(); //determin sender / author of message
|
||||||
// cg added - for anonymous posts, don't allow editing, else everyone
|
// cg added - for anonymous posts, don't allow editing, else everyone
|
||||||
// could edit everyone else's posts
|
// could edit everyone else's posts
|
||||||
return ( !author.equals(Kernel.getPublicUser())
|
return (!author.equals(Kernel.getPublicUser())
|
||||||
&& Forum.getConfig().canAuthorEditPosts()
|
&& Forum.getConfig().canAuthorEditPosts()
|
||||||
&& author.equals(party) )
|
&& author.equals(party))
|
||||||
|| getForum().canEdit(party);
|
|| getForum().canEdit(party);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determines if the User has permission to delete this Post.
|
||||||
|
* Note that you probably don't want to use this over and
|
||||||
|
* over for a list of messages because the permission check
|
||||||
|
* on the forum is not cached.
|
||||||
|
*/
|
||||||
|
public boolean canDelete(Party party) {
|
||||||
|
Party author = getFrom(); //determin sender / author of message
|
||||||
|
// cg added - for anonymous posts, don't allow editing, else everyone
|
||||||
|
// could edit everyone else's posts
|
||||||
|
return (!author.equals(Kernel.getPublicUser())
|
||||||
|
&& Forum.getConfig().canAuthorDeletePosts()
|
||||||
|
&& author.equals(party))
|
||||||
|
|| getForum().canDelete(party);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setStatus(String status) {
|
public void setStatus(String status) {
|
||||||
Assert.isTrue(
|
Assert.isTrue(
|
||||||
(status.equals(APPROVED)
|
(status.equals(APPROVED)
|
||||||
|| status.equals(REJECTED)
|
|| status.equals(REJECTED)
|
||||||
|| status.equals(REAPPROVE)
|
|| status.equals(REAPPROVE)
|
||||||
|| status.equals(SUPPRESSED)
|
|| status.equals(SUPPRESSED)
|
||||||
|| status.equals(PENDING)
|
|| status.equals(PENDING)),
|
||||||
),
|
"The status must be one of " + APPROVED
|
||||||
"The status must be one of " + APPROVED
|
+ ", " + REJECTED
|
||||||
+ ", " + REJECTED
|
+ ", " + REAPPROVE
|
||||||
+ ", " + REAPPROVE
|
+ ", " + SUPPRESSED
|
||||||
+ ", "+ SUPPRESSED
|
+ ", the input was " + status);
|
||||||
+ ", the input was " + status
|
|
||||||
);
|
|
||||||
|
|
||||||
set(STATUS, status);
|
set(STATUS, status);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* set the status of a new post according to the priviliges of
|
* set the status of a new post according to the priviliges of
|
||||||
* the current user - used by UI when creating new post or reply
|
* the current user - used by UI when creating new post or reply
|
||||||
* @param state
|
* @param state
|
||||||
*/
|
*/
|
||||||
public void setStatus(PageState state) {
|
public void setStatus(PageState state) {
|
||||||
setStatus(state, null);
|
setStatus(state, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* set the status of an edited post according to the privileges
|
* set the status of an edited post according to the privileges
|
||||||
* of the current user and the status of the post that is being
|
* of the current user and the status of the post that is being
|
||||||
* edited - used by the edit post UI
|
* edited - used by the edit post UI
|
||||||
* @param state
|
* @param state
|
||||||
* @param previousStatus
|
* @param previousStatus
|
||||||
*/
|
*/
|
||||||
public void setStatus(PageState state, String previousStatus) {
|
public void setStatus(PageState state, String previousStatus) {
|
||||||
ForumContext ctx = ForumContext.getContext(state);
|
ForumContext ctx = ForumContext.getContext(state);
|
||||||
Forum forum = ctx.getForum();
|
Forum forum = ctx.getForum();
|
||||||
// set status of edited post
|
// set status of edited post
|
||||||
if (forum.isModerated() && !ctx.canModerate()) {
|
if (forum.isModerated() && !ctx.canModerate()) {
|
||||||
if (Post.APPROVED.equals(previousStatus)) {
|
if (Post.APPROVED.equals(previousStatus)) {
|
||||||
setStatus(Post.REAPPROVE);
|
setStatus(Post.REAPPROVE);
|
||||||
} else {
|
} else {
|
||||||
setStatus(Post.PENDING);
|
setStatus(Post.PENDING);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
setStatus(Post.APPROVED);
|
setStatus(Post.APPROVED);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getStatus() {
|
public String getStatus() {
|
||||||
return (String)get(STATUS);
|
return (String) get(STATUS);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setModerator(Party moderator) {
|
public void setModerator(Party moderator) {
|
||||||
|
|
@ -566,26 +566,24 @@ public class Post extends ThreadedMessage {
|
||||||
if (m_moderator == null) {
|
if (m_moderator == null) {
|
||||||
DataObject moderatorData = (DataObject) get(MODERATOR);
|
DataObject moderatorData = (DataObject) get(MODERATOR);
|
||||||
if (moderatorData != null) {
|
if (moderatorData != null) {
|
||||||
m_moderator = (Party) DomainObjectFactory.newInstance
|
m_moderator = (Party) DomainObjectFactory.newInstance(moderatorData);
|
||||||
(moderatorData);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return m_moderator;
|
return m_moderator;
|
||||||
}
|
}
|
||||||
|
|
||||||
// note that the replies to this post are deleted in beforeDelete() of
|
// note that the replies to this post are deleted in beforeDelete() of
|
||||||
// ThreadedMessage (and hence beforeDelete is called recursively on their replies)
|
// ThreadedMessage (and hence beforeDelete is called recursively on their replies)
|
||||||
|
|
||||||
protected void beforeDelete() {
|
protected void beforeDelete() {
|
||||||
s_log.debug("Post - before delete " + getID());
|
s_log.debug("Post - before delete " + getID());
|
||||||
|
|
||||||
// threaded message recursively deletes children
|
// threaded message recursively deletes children
|
||||||
super.beforeDelete();
|
super.beforeDelete();
|
||||||
// remove any nt_requests
|
// remove any nt_requests
|
||||||
DataCollection requests =
|
DataCollection requests =
|
||||||
SessionManager.getSession().retrieve(
|
SessionManager.getSession().retrieve(
|
||||||
Notification.BASE_DATA_OBJECT_TYPE);
|
Notification.BASE_DATA_OBJECT_TYPE);
|
||||||
requests.addEqualsFilter(Notification.MESSAGE_ID, this.getID());
|
requests.addEqualsFilter(Notification.MESSAGE_ID, this.getID());
|
||||||
while (requests.next()) {
|
while (requests.next()) {
|
||||||
Notification no = new Notification(requests.getDataObject().getOID());
|
Notification no = new Notification(requests.getDataObject().getOID());
|
||||||
no.setMessageDelete(Boolean.FALSE);
|
no.setMessageDelete(Boolean.FALSE);
|
||||||
|
|
@ -593,23 +591,23 @@ public class Post extends ThreadedMessage {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (getRoot() == null) {
|
if (getRoot() == null) {
|
||||||
s_log.debug(
|
s_log.debug(
|
||||||
"Root post - get rid of thread subscription and thread");
|
"Root post - get rid of thread subscription and thread");
|
||||||
// This posting is the root of the thread. Remove the thread subscription and thread
|
// This posting is the root of the thread. Remove the thread subscription and thread
|
||||||
MessageThread thread = getThread();
|
MessageThread thread = getThread();
|
||||||
ThreadSubscription sub =
|
ThreadSubscription sub =
|
||||||
ThreadSubscription.getThreadSubscription(thread);
|
ThreadSubscription.getThreadSubscription(thread);
|
||||||
if (sub != null) {
|
if (sub != null) {
|
||||||
// if unconfirmed post, then threadsubscription has not been created
|
// if unconfirmed post, then threadsubscription has not been created
|
||||||
sub.delete();
|
sub.delete();
|
||||||
|
|
||||||
}
|
}
|
||||||
if (thread != null) {
|
if (thread != null) {
|
||||||
thread.delete();
|
thread.delete();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// package access only
|
// package access only
|
||||||
void setLifecycle(LifecycleDefinition life) {
|
void setLifecycle(LifecycleDefinition life) {
|
||||||
|
|
@ -619,91 +617,86 @@ public class Post extends ThreadedMessage {
|
||||||
cycle.save();
|
cycle.save();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addImage(PostImageAttachment image) {
|
public void addImage(PostImageAttachment image) {
|
||||||
DataAssociation images = (DataAssociation) get(Post.IMAGE_ATTACHMENTS);
|
DataAssociation images = (DataAssociation) get(Post.IMAGE_ATTACHMENTS);
|
||||||
image.addToAssociation(images);
|
image.addToAssociation(images);
|
||||||
long currentImageCount = images.getDataAssociationCursor().size();
|
long currentImageCount = images.getDataAssociationCursor().size();
|
||||||
image.setImageOrder((int) currentImageCount);
|
image.setImageOrder((int) currentImageCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void removeImage(PostImageAttachment image) {
|
public void removeImage(PostImageAttachment image) {
|
||||||
DataAssociation images = (DataAssociation) get(Post.IMAGE_ATTACHMENTS);
|
DataAssociation images = (DataAssociation) get(Post.IMAGE_ATTACHMENTS);
|
||||||
image.removeFromAssociation(images);
|
image.removeFromAssociation(images);
|
||||||
renumberImages();
|
renumberImages();
|
||||||
}
|
}
|
||||||
|
|
||||||
// image order for a new image is based on the count of existing
|
// image order for a new image is based on the count of existing
|
||||||
// images, hence necessary to fill in any gaps when images are deleted
|
// images, hence necessary to fill in any gaps when images are deleted
|
||||||
private void renumberImages() {
|
private void renumberImages() {
|
||||||
int count = 1;
|
int count = 1;
|
||||||
DataAssociationCursor images = getImages();
|
DataAssociationCursor images = getImages();
|
||||||
while (images.next()) {
|
while (images.next()) {
|
||||||
PostImageAttachment image =
|
PostImageAttachment image =
|
||||||
(PostImageAttachment) DomainObjectFactory.newInstance(
|
(PostImageAttachment) DomainObjectFactory.newInstance(
|
||||||
images.getDataObject());
|
images.getDataObject());
|
||||||
image.setImageOrder(count);
|
image.setImageOrder(count);
|
||||||
count++;
|
count++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public DataAssociationCursor getImages() {
|
public DataAssociationCursor getImages() {
|
||||||
DataAssociationCursor images =
|
DataAssociationCursor images =
|
||||||
((DataAssociation) get(Post.IMAGE_ATTACHMENTS))
|
((DataAssociation) get(Post.IMAGE_ATTACHMENTS)).getDataAssociationCursor();
|
||||||
.getDataAssociationCursor();
|
images.addOrder(PostImageAttachment.IMAGE_ORDER);
|
||||||
images.addOrder(PostImageAttachment.IMAGE_ORDER);
|
return images;
|
||||||
return images;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
public void addFile(PostFileAttachment file) {
|
public void addFile(PostFileAttachment file) {
|
||||||
DataAssociation files = (DataAssociation) get(Post.FILE_ATTACHMENTS);
|
DataAssociation files = (DataAssociation) get(Post.FILE_ATTACHMENTS);
|
||||||
file.addToAssociation(files);
|
file.addToAssociation(files);
|
||||||
PermissionService.setContext(file, this);
|
PermissionService.setContext(file, this);
|
||||||
long currentFileCount = files.getDataAssociationCursor().size();
|
long currentFileCount = files.getDataAssociationCursor().size();
|
||||||
file.setFileOrder((int) currentFileCount);
|
file.setFileOrder((int) currentFileCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void removeFile(PostFileAttachment file) {
|
public void removeFile(PostFileAttachment file) {
|
||||||
DataAssociation files = (DataAssociation) get(Post.FILE_ATTACHMENTS);
|
DataAssociation files = (DataAssociation) get(Post.FILE_ATTACHMENTS);
|
||||||
file.removeFromAssociation(files);
|
file.removeFromAssociation(files);
|
||||||
renumberFiles();
|
renumberFiles();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// file order for a new file is based on the count of existing
|
// file order for a new file is based on the count of existing
|
||||||
// files, hence necessary to fill in any gaps when images are deleted
|
// files, hence necessary to fill in any gaps when images are deleted
|
||||||
|
private void renumberFiles() {
|
||||||
|
int count = 1;
|
||||||
|
DataAssociationCursor files = getFiles();
|
||||||
|
while (files.next()) {
|
||||||
|
PostFileAttachment file =
|
||||||
|
(PostFileAttachment) DomainObjectFactory.newInstance(
|
||||||
|
files.getDataObject());
|
||||||
|
file.setFileOrder(count);
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
|
||||||
private void renumberFiles() {
|
}
|
||||||
int count = 1;
|
|
||||||
DataAssociationCursor files = getFiles();
|
|
||||||
while (files.next()) {
|
|
||||||
PostFileAttachment file =
|
|
||||||
(PostFileAttachment) DomainObjectFactory.newInstance(
|
|
||||||
files.getDataObject());
|
|
||||||
file.setFileOrder(count);
|
|
||||||
count++;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
public DataAssociationCursor getFiles() {
|
||||||
|
DataAssociationCursor files =
|
||||||
|
((DataAssociation) get(Post.FILE_ATTACHMENTS)).getDataAssociationCursor();
|
||||||
|
files.addOrder(PostFileAttachment.FILE_ORDER);
|
||||||
|
return files;
|
||||||
|
|
||||||
public DataAssociationCursor getFiles() {
|
}
|
||||||
DataAssociationCursor files =
|
|
||||||
((DataAssociation) get(Post.FILE_ATTACHMENTS))
|
|
||||||
.getDataAssociationCursor();
|
|
||||||
files.addOrder(PostFileAttachment.FILE_ORDER);
|
|
||||||
return files;
|
|
||||||
|
|
||||||
}
|
/**
|
||||||
|
* used by thread to prevent counting unapproved posts in the
|
||||||
|
* reply count.
|
||||||
/**
|
*
|
||||||
* used by thread to prevent counting unapproved posts in the
|
*/
|
||||||
* reply count.
|
// should really be static - revisit this - refer to MessageThread for use
|
||||||
*
|
protected void addReplyFilter(DataCollection replies) {
|
||||||
*/
|
replies.addEqualsFilter(STATUS, APPROVED);
|
||||||
// should really be static - revisit this - refer to MessageThread for use
|
|
||||||
protected void addReplyFilter(DataCollection replies) {
|
|
||||||
replies.addEqualsFilter(STATUS, APPROVED);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -18,16 +18,14 @@
|
||||||
*/
|
*/
|
||||||
package com.arsdigita.forum;
|
package com.arsdigita.forum;
|
||||||
|
|
||||||
import com.arsdigita.cms.ContentItem;
|
import com.arsdigita.cms.Asset;
|
||||||
import com.arsdigita.cms.dispatcher.AssetURLFinder;
|
import com.arsdigita.cms.dispatcher.AssetURLFinder;
|
||||||
|
|
||||||
import com.arsdigita.kernel.NoValidURLException;
|
import com.arsdigita.kernel.NoValidURLException;
|
||||||
import com.arsdigita.kernel.URLFinder;
|
import com.arsdigita.kernel.URLFinder;
|
||||||
import com.arsdigita.kernel.URLService;
|
|
||||||
import com.arsdigita.persistence.DataObject;
|
|
||||||
import com.arsdigita.persistence.OID;
|
import com.arsdigita.persistence.OID;
|
||||||
import com.arsdigita.persistence.SessionManager;
|
import com.arsdigita.web.Web;
|
||||||
import com.arsdigita.util.Assert;
|
import com.arsdigita.web.WebConfig;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author chris.gilbert@westsussex.gov.uk
|
* @author chris.gilbert@westsussex.gov.uk
|
||||||
|
|
@ -36,32 +34,41 @@ import com.arsdigita.util.Assert;
|
||||||
*/
|
*/
|
||||||
public class PostFileAttachmentURLFinder implements URLFinder {
|
public class PostFileAttachmentURLFinder implements URLFinder {
|
||||||
|
|
||||||
private static final AssetURLFinder s_assetFinder = new AssetURLFinder();
|
private static final AssetURLFinder s_assetFinder = new AssetURLFinder();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* find URL for a file attachment by finding its post
|
* find URL for a file attachment by finding its post
|
||||||
*
|
*
|
||||||
* @param oid the OID of the file attachment
|
* @param oid the OID of the file attachment
|
||||||
* @param content the context of the search (ie draft/live)
|
* @param content the context of the search (ie draft/live)
|
||||||
*/
|
*/
|
||||||
public String find(OID oid, String context) throws NoValidURLException {
|
public String find(OID oid, String context) throws NoValidURLException {
|
||||||
// a draft attachment is one where the post hasn't been saved yet
|
// a draft attachment is one where the post hasn't been saved yet
|
||||||
// the behaviour is the same as far as finding the url goes
|
// the behaviour is the same as far as finding the url goes
|
||||||
return find(oid);
|
return find(oid);
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* find URL for the context of a file attachment. Delegates to
|
* find URL for the context of a file attachment. Delegates to
|
||||||
* AssetURLFinder.
|
* AssetURLFinder.
|
||||||
*
|
*
|
||||||
* @param oid the OID of the file attachment
|
* @param oid the OID of the file attachment
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public String find(OID oid) throws NoValidURLException {
|
public String find(OID oid) throws NoValidURLException {
|
||||||
return s_assetFinder.find(oid);
|
WebConfig config = Web.getConfig();
|
||||||
}
|
|
||||||
|
StringBuilder url = new StringBuilder();
|
||||||
|
url.append(config.getDispatcherServletPath());
|
||||||
|
url.append(config.getDispatcherContextPath());
|
||||||
|
url.append("/cms-service/download/asset/?asset_id=");
|
||||||
|
url.append(oid.get(Asset.ID).toString());
|
||||||
|
|
||||||
|
return url.toString();
|
||||||
|
// return s_assetFinder.find(oid);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -356,7 +356,7 @@ public class AttachedFilesStep
|
||||||
while(files.next()) {
|
while(files.next()) {
|
||||||
PostFileAttachment file = (PostFileAttachment) DomainObjectFactory.newInstance(
|
PostFileAttachment file = (PostFileAttachment) DomainObjectFactory.newInstance(
|
||||||
files.getDataObject());
|
files.getDataObject());
|
||||||
DomainObjectXMLRenderer xr = new DomainObjectXMLRenderer(p.newChildElement(FORUM_XML_PREFIX + "files"));
|
DomainObjectXMLRenderer xr = new DomainObjectXMLRenderer(p.newChildElement(FORUM_XML_PREFIX + ":files", FORUM_XML_NS));
|
||||||
xr.setWrapRoot(false);
|
xr.setWrapRoot(false);
|
||||||
xr.setWrapAttributes(true);
|
xr.setWrapAttributes(true);
|
||||||
xr.setWrapObjects(false);
|
xr.setWrapObjects(false);
|
||||||
|
|
|
||||||
|
|
@ -31,7 +31,7 @@ import java.math.BigDecimal;
|
||||||
|
|
||||||
public interface Constants {
|
public interface Constants {
|
||||||
|
|
||||||
static final String FORUM_XML_PREFIX = "forum";
|
static final String FORUM_XML_PREFIX = "forum";
|
||||||
static final String FORUM_XML_NS = "http://www.arsdigita.com/forum/1.0";
|
static final String FORUM_XML_NS = "http://www.arsdigita.com/forum/1.0";
|
||||||
|
|
||||||
static final String FORUM_MODE_VIEW = "view";
|
static final String FORUM_MODE_VIEW = "view";
|
||||||
|
|
|
||||||
|
|
@ -68,18 +68,15 @@ import com.arsdigita.xml.XML;
|
||||||
public class DiscussionPostsList extends SimpleComponent implements Constants {
|
public class DiscussionPostsList extends SimpleComponent implements Constants {
|
||||||
|
|
||||||
private static final Logger s_log =
|
private static final Logger s_log =
|
||||||
Logger.getLogger(DiscussionPostsList.class);
|
Logger.getLogger(DiscussionPostsList.class);
|
||||||
|
|
||||||
private IntegerParameter m_pageNumber =
|
private IntegerParameter m_pageNumber =
|
||||||
new IntegerParameter(PAGINATOR_PARAM);
|
new IntegerParameter(PAGINATOR_PARAM);
|
||||||
private int m_pageSize = Forum.getConfig().getThreadPageSize();
|
private int m_pageSize = Forum.getConfig().getThreadPageSize();
|
||||||
|
|
||||||
private static final String ACTION_EDIT = "edit";
|
private static final String ACTION_EDIT = "edit";
|
||||||
private static final String ACTION_DELETE = "delete";
|
private static final String ACTION_DELETE = "delete";
|
||||||
private static final String ACTION_REPLY = "reply";
|
private static final String ACTION_REPLY = "reply";
|
||||||
private static final String ACTION_APPROVE = "approve";
|
private static final String ACTION_APPROVE = "approve";
|
||||||
private static final String ACTION_REJECT = "reject";
|
private static final String ACTION_REJECT = "reject";
|
||||||
|
|
||||||
private DiscussionThreadSimpleView m_threadMessagesPanel;
|
private DiscussionThreadSimpleView m_threadMessagesPanel;
|
||||||
private ACSObjectSelectionModel m_post;
|
private ACSObjectSelectionModel m_post;
|
||||||
|
|
||||||
|
|
@ -90,12 +87,11 @@ public class DiscussionPostsList extends SimpleComponent implements Constants {
|
||||||
* @param threadMessagesPanel
|
* @param threadMessagesPanel
|
||||||
*/
|
*/
|
||||||
public DiscussionPostsList(ACSObjectSelectionModel post,
|
public DiscussionPostsList(ACSObjectSelectionModel post,
|
||||||
DiscussionThreadSimpleView threadMessagesPanel) {
|
DiscussionThreadSimpleView threadMessagesPanel) {
|
||||||
m_threadMessagesPanel = threadMessagesPanel;
|
m_threadMessagesPanel = threadMessagesPanel;
|
||||||
m_post = post;
|
m_post = post;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @param p
|
* @param p
|
||||||
|
|
@ -112,56 +108,66 @@ public class DiscussionPostsList extends SimpleComponent implements Constants {
|
||||||
* @throws ServletException
|
* @throws ServletException
|
||||||
*/
|
*/
|
||||||
public void respond(PageState state)
|
public void respond(PageState state)
|
||||||
throws ServletException {
|
throws ServletException {
|
||||||
super.respond(state);
|
super.respond(state);
|
||||||
|
|
||||||
String key = state.getControlEventName();
|
String key = state.getControlEventName();
|
||||||
String value = state.getControlEventValue();
|
String value = state.getControlEventValue();
|
||||||
|
|
||||||
OID oid = new OID(Post.BASE_DATA_OBJECT_TYPE,
|
OID oid = new OID(Post.BASE_DATA_OBJECT_TYPE,
|
||||||
new BigDecimal(value));
|
new BigDecimal(value));
|
||||||
|
|
||||||
ForumContext ctx = ForumContext.getContext(state);
|
ForumContext ctx = ForumContext.getContext(state);
|
||||||
Post post = (Post)DomainObjectFactory.newInstance(oid);
|
Post post = (Post) DomainObjectFactory.newInstance(oid);
|
||||||
|
|
||||||
if (ACTION_EDIT.equals(key)) {
|
if (ACTION_EDIT.equals(key)) {
|
||||||
m_post.setSelectedObject(state, post);
|
m_post.setSelectedObject(state, post);
|
||||||
m_threadMessagesPanel.makeEditFormVisible(state);
|
m_threadMessagesPanel.makeEditFormVisible(state);
|
||||||
} else if (ACTION_DELETE.equals(key)) {
|
} else if (ACTION_DELETE.equals(key)) {
|
||||||
Assert.isTrue(ctx.canAdminister(), "can administer forums");
|
// Assert.isTrue(ctx.canDelete(post), "can administer forums");
|
||||||
|
|
||||||
MessageThread thread = ctx.getMessageThread();
|
MessageThread thread = ctx.getMessageThread();
|
||||||
ThreadedMessage root = thread.getRootMessage();
|
ThreadedMessage root = thread.getRootMessage();
|
||||||
|
|
||||||
if ( s_log.isDebugEnabled() ) {
|
if (s_log.isDebugEnabled()) {
|
||||||
s_log.debug("message: " + post.getOID() +
|
s_log.debug("message: " + post.getOID()
|
||||||
" root: " + root.getOID() +
|
+ " root: " + root.getOID()
|
||||||
" thread: " + thread.getOID());
|
+ " thread: " + thread.getOID());
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( ctx.getForum().isModerated() ) {
|
if (ctx.getForum().isModerated()) {
|
||||||
if ( !ctx.canModerate() ) {
|
if (!ctx.canModerate()) {
|
||||||
|
Assert.isTrue(ctx.canAdminister(), "can administer forums");
|
||||||
|
|
||||||
post.setStatus(Post.SUPPRESSED);
|
post.setStatus(Post.SUPPRESSED);
|
||||||
post.save();
|
post.save();
|
||||||
} else if (post.equals(root)) {
|
} else if (post.equals(root)) {
|
||||||
|
Assert.isTrue(ctx.canDelete(post), "can delete posts");
|
||||||
|
|
||||||
s_log.debug("Deleting entire thread");
|
s_log.debug("Deleting entire thread");
|
||||||
post.delete();
|
post.delete();
|
||||||
|
|
||||||
Forum forum = ctx.getForum();
|
Forum forum = ctx.getForum();
|
||||||
URL url = URL.there(state.getRequest(), forum, null );
|
URL url = URL.there(state.getRequest(), forum, null);
|
||||||
throw new RedirectSignal( url, true );
|
throw new RedirectSignal(url, true);
|
||||||
} else {
|
} else {
|
||||||
|
Assert.isTrue(ctx.canDelete(post), "can delete posts");
|
||||||
|
|
||||||
s_log.debug("Deleting message");
|
s_log.debug("Deleting message");
|
||||||
post.delete();
|
post.delete();
|
||||||
}
|
}
|
||||||
} else if (post.equals(root)) {
|
} else if (post.equals(root)) {
|
||||||
|
Assert.isTrue(ctx.canDelete(post), "can delete posts");
|
||||||
|
|
||||||
s_log.debug("Deleting entire thread");
|
s_log.debug("Deleting entire thread");
|
||||||
post.delete();
|
post.delete();
|
||||||
|
|
||||||
Forum forum = ctx.getForum();
|
Forum forum = ctx.getForum();
|
||||||
URL url = URL.there(state.getRequest(), forum, null );
|
URL url = URL.there(state.getRequest(), forum, null);
|
||||||
throw new RedirectSignal( url, true );
|
throw new RedirectSignal(url, true);
|
||||||
} else {
|
} else {
|
||||||
|
Assert.isTrue(ctx.canDelete(post), "can delete posts");
|
||||||
|
|
||||||
s_log.debug("Deleting message");
|
s_log.debug("Deleting message");
|
||||||
post.delete();
|
post.delete();
|
||||||
}
|
}
|
||||||
|
|
@ -179,9 +185,9 @@ public class DiscussionPostsList extends SimpleComponent implements Constants {
|
||||||
|
|
||||||
state.clearControlEvent();
|
state.clearControlEvent();
|
||||||
try {
|
try {
|
||||||
throw new RedirectSignal( state.stateAsURL(), true );
|
throw new RedirectSignal(state.stateAsURL(), true);
|
||||||
} catch( IOException ex ) {
|
} catch (IOException ex) {
|
||||||
throw new UncheckedWrapperException( ex );
|
throw new UncheckedWrapperException(ex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -197,10 +203,9 @@ public class DiscussionPostsList extends SimpleComponent implements Constants {
|
||||||
Forum forum = context.getForum();
|
Forum forum = context.getForum();
|
||||||
|
|
||||||
BigDecimal rootID = context.getMessageThread().
|
BigDecimal rootID = context.getMessageThread().
|
||||||
getRootMessage().getID();
|
getRootMessage().getID();
|
||||||
|
|
||||||
DataCollection messages = SessionManager.getSession().retrieve
|
DataCollection messages = SessionManager.getSession().retrieve(Post.BASE_DATA_OBJECT_TYPE);
|
||||||
(Post.BASE_DATA_OBJECT_TYPE);
|
|
||||||
|
|
||||||
// Hide replies if we're in noticeboard mode
|
// Hide replies if we're in noticeboard mode
|
||||||
if (forum.isNoticeboard()) {
|
if (forum.isNoticeboard()) {
|
||||||
|
|
@ -210,21 +215,14 @@ public class DiscussionPostsList extends SimpleComponent implements Constants {
|
||||||
|
|
||||||
FilterFactory ff = messages.getFilterFactory();
|
FilterFactory ff = messages.getFilterFactory();
|
||||||
messages.addFilter(
|
messages.addFilter(
|
||||||
ff.or()
|
ff.or().addFilter(ff.and().addFilter(ff.equals("root", null)).addFilter(ff.equals("id", rootID))).addFilter(ff.equals("root", rootID)));
|
||||||
.addFilter(ff.and()
|
|
||||||
.addFilter(ff.equals("root", null))
|
|
||||||
.addFilter(ff.equals("id", rootID)))
|
|
||||||
.addFilter(ff.equals("root", rootID)));
|
|
||||||
|
|
||||||
messages.addOrderWithNull("sortKey", "---", true);
|
messages.addOrderWithNull("sortKey", "---", true);
|
||||||
|
|
||||||
// Add a filter to only show approved messages
|
// Add a filter to only show approved messages
|
||||||
if (forum.isModerated() && !forum.canModerate(party)) {
|
if (forum.isModerated() && !forum.canModerate(party)) {
|
||||||
messages.addFilter(ff.or()
|
messages.addFilter(ff.or().addFilter(ff.equals("status", Post.APPROVED)).addFilter(ff.equals("sender.id", party == null
|
||||||
.addFilter(ff.equals("status", Post.APPROVED))
|
? null : party.getID())));
|
||||||
.addFilter(ff.equals("sender.id", party == null ?
|
|
||||||
null : party.getID()))
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return new DomainCollection(messages);
|
return new DomainCollection(messages);
|
||||||
|
|
@ -237,22 +235,21 @@ public class DiscussionPostsList extends SimpleComponent implements Constants {
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void generateXML(PageState state,
|
public void generateXML(PageState state,
|
||||||
Element parent) {
|
Element parent) {
|
||||||
Element content = parent.newChildElement(FORUM_XML_PREFIX +
|
Element content = parent.newChildElement(FORUM_XML_PREFIX
|
||||||
":threadDisplay",
|
+ ":threadDisplay",
|
||||||
FORUM_XML_NS);
|
FORUM_XML_NS);
|
||||||
exportAttributes(content);
|
exportAttributes(content);
|
||||||
|
|
||||||
Forum forum = ForumContext.getContext(state).getForum();
|
Forum forum = ForumContext.getContext(state).getForum();
|
||||||
content.addAttribute("forumTitle", forum.getTitle());
|
content.addAttribute("forumTitle", forum.getTitle());
|
||||||
content.addAttribute("noticeboard", (new Boolean(forum.isNoticeboard())).
|
content.addAttribute("noticeboard", (new Boolean(forum.isNoticeboard())).toString());
|
||||||
toString());
|
|
||||||
DomainCollection messages = getMessages(state);
|
DomainCollection messages = getMessages(state);
|
||||||
|
|
||||||
Integer page = (Integer)state.getValue(m_pageNumber);
|
Integer page = (Integer) state.getValue(m_pageNumber);
|
||||||
int pageNumber = (page == null ? 1 : page.intValue());
|
int pageNumber = (page == null ? 1 : page.intValue());
|
||||||
long objectCount = messages.size();
|
long objectCount = messages.size();
|
||||||
int pageCount = (int)Math.ceil((double)objectCount / (double)m_pageSize);
|
int pageCount = (int) Math.ceil((double) objectCount / (double) m_pageSize);
|
||||||
|
|
||||||
if (pageNumber < 1) {
|
if (pageNumber < 1) {
|
||||||
pageNumber = 1;
|
pageNumber = 1;
|
||||||
|
|
@ -262,29 +259,30 @@ public class DiscussionPostsList extends SimpleComponent implements Constants {
|
||||||
pageNumber = (pageCount == 0 ? 1 : pageCount);
|
pageNumber = (pageCount == 0 ? 1 : pageCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
long begin = ((pageNumber-1) * m_pageSize);
|
long begin = ((pageNumber - 1) * m_pageSize);
|
||||||
int count = (int)Math.min(m_pageSize, (objectCount - begin));
|
int count = (int) Math.min(m_pageSize, (objectCount - begin));
|
||||||
long end = begin + count;
|
long end = begin + count;
|
||||||
|
|
||||||
generatePaginatorXML(content,
|
generatePaginatorXML(content,
|
||||||
pageNumber,
|
pageNumber,
|
||||||
pageCount,
|
pageCount,
|
||||||
m_pageSize,
|
m_pageSize,
|
||||||
begin,
|
begin,
|
||||||
end,
|
end,
|
||||||
objectCount);
|
objectCount);
|
||||||
|
|
||||||
if (begin != 0 || end != 0) {
|
if (begin != 0 || end != 0) {
|
||||||
messages.setRange(new Integer((int)begin+1),
|
messages.setRange(new Integer((int) begin + 1),
|
||||||
new Integer((int)end+1));
|
new Integer((int) end + 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
while (messages.next()) {
|
while (messages.next()) {
|
||||||
Post message = (Post)messages.getDomainObject();
|
Post message = (Post) messages.getDomainObject();
|
||||||
Element messageEl = content.newChildElement(FORUM_XML_PREFIX + ":message",
|
Element messageEl = content.newChildElement(FORUM_XML_PREFIX + ":message",
|
||||||
FORUM_XML_NS);
|
FORUM_XML_NS);
|
||||||
|
|
||||||
generateActionXML(state, messageEl, message);
|
generateActionXML(state, messageEl, message,
|
||||||
|
(messages.getPosition() == messages.size()) ? true : false );
|
||||||
|
|
||||||
DomainObjectXMLRenderer xr = new DomainObjectXMLRenderer(messageEl);
|
DomainObjectXMLRenderer xr = new DomainObjectXMLRenderer(messageEl);
|
||||||
xr.setWrapRoot(false);
|
xr.setWrapRoot(false);
|
||||||
|
|
@ -299,60 +297,62 @@ public class DiscussionPostsList extends SimpleComponent implements Constants {
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @param state
|
* @param state
|
||||||
* @param parent
|
* @param parent Parent XML element to add any additional elements
|
||||||
* @param post
|
* @param post Current post to generate action links for
|
||||||
|
* @param isLast Post is last in list
|
||||||
*/
|
*/
|
||||||
protected void generateActionXML(PageState state,
|
protected void generateActionXML(PageState state,
|
||||||
Element parent,
|
Element parent,
|
||||||
Post post) {
|
Post post,
|
||||||
|
boolean isLast) {
|
||||||
ForumContext ctx = ForumContext.getContext(state);
|
ForumContext ctx = ForumContext.getContext(state);
|
||||||
|
|
||||||
String status = post.getStatus();
|
|
||||||
if (ctx.canModerate()) {
|
|
||||||
if (!status.equals(Post.REJECTED) &&
|
|
||||||
!status.equals(Post.SUPPRESSED) ) {
|
|
||||||
parent.addAttribute("rejectURL",
|
|
||||||
makeURL(state, ACTION_REJECT, post));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ctx.canModerate() &&
|
|
||||||
!post.getStatus().equals(post.APPROVED)) {
|
|
||||||
parent.addAttribute("approveURL",
|
|
||||||
makeURL(state, ACTION_APPROVE, post));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ctx.canAdminister()) {
|
|
||||||
parent.addAttribute("deleteURL",
|
|
||||||
makeURL(state, ACTION_DELETE, post));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
Party party = Kernel.getContext().getParty();
|
Party party = Kernel.getContext().getParty();
|
||||||
if (party == null) {
|
if (party == null) {
|
||||||
party = Kernel.getPublicUser();
|
party = Kernel.getPublicUser();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
String status = post.getStatus();
|
||||||
|
if (ctx.canModerate()) {
|
||||||
|
if (!status.equals(Post.REJECTED)
|
||||||
|
&& !status.equals(Post.SUPPRESSED)) {
|
||||||
|
parent.addAttribute("rejectURL",
|
||||||
|
makeURL(state, ACTION_REJECT, post));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ctx.canModerate()
|
||||||
|
&& !post.getStatus().equals(post.APPROVED)) {
|
||||||
|
parent.addAttribute("approveURL",
|
||||||
|
makeURL(state, ACTION_APPROVE, post));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ctx.canAdminister() || (post.canDelete(party) && isLast)) {
|
||||||
|
parent.addAttribute("deleteURL",
|
||||||
|
makeURL(state, ACTION_DELETE, post));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
if (post.canEdit(party)) {
|
if (post.canEdit(party)) {
|
||||||
parent.addAttribute("editURL",
|
parent.addAttribute("editURL",
|
||||||
makeURL(state, ACTION_EDIT, post));
|
makeURL(state, ACTION_EDIT, post));
|
||||||
}
|
}
|
||||||
|
|
||||||
PermissionDescriptor canRespond = new PermissionDescriptor(
|
PermissionDescriptor canRespond = new PermissionDescriptor(
|
||||||
PrivilegeDescriptor.get(Forum.RESPOND_TO_THREAD_PRIVILEGE),
|
PrivilegeDescriptor.get(Forum.RESPOND_TO_THREAD_PRIVILEGE),
|
||||||
Kernel.getContext().getResource(), party);
|
Kernel.getContext().getResource(), party);
|
||||||
|
|
||||||
if (!ctx.getForum().isNoticeboard() && PermissionService.
|
if (!ctx.getForum().isNoticeboard() && PermissionService.checkPermission(canRespond)) {
|
||||||
checkPermission(canRespond)) {
|
|
||||||
parent.addAttribute("replyURL",
|
parent.addAttribute("replyURL",
|
||||||
makeURL(state, ACTION_REPLY, post));
|
makeURL(state, ACTION_REPLY, post));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected String makeURL(PageState state,
|
protected String makeURL(PageState state,
|
||||||
String action,
|
String action,
|
||||||
Post post) {
|
Post post) {
|
||||||
state.setControlEvent(this, action,post.getID().toString());
|
state.setControlEvent(this, action, post.getID().toString());
|
||||||
|
|
||||||
String url = null;
|
String url = null;
|
||||||
try {
|
try {
|
||||||
|
|
@ -365,35 +365,34 @@ public class DiscussionPostsList extends SimpleComponent implements Constants {
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void generatePaginatorXML(Element parent,
|
protected void generatePaginatorXML(Element parent,
|
||||||
int pageNumber,
|
int pageNumber,
|
||||||
int pageCount,
|
int pageCount,
|
||||||
int pageSize,
|
int pageSize,
|
||||||
long begin,
|
long begin,
|
||||||
long end,
|
long end,
|
||||||
long objectCount) {
|
long objectCount) {
|
||||||
Element paginator = parent.newChildElement(FORUM_XML_PREFIX +
|
Element paginator = parent.newChildElement(FORUM_XML_PREFIX
|
||||||
":paginator", FORUM_XML_NS);
|
+ ":paginator", FORUM_XML_NS);
|
||||||
|
|
||||||
URL here = Web.getContext().getRequestURL();
|
URL here = Web.getContext().getRequestURL();
|
||||||
ParameterMap params = new ParameterMap(here.getParameterMap());
|
ParameterMap params = new ParameterMap(here.getParameterMap());
|
||||||
params.clearParameter(PAGINATOR_PARAM);
|
params.clearParameter(PAGINATOR_PARAM);
|
||||||
|
|
||||||
URL url = new URL(here.getScheme(),
|
URL url = new URL(here.getScheme(),
|
||||||
here.getServerName(),
|
here.getServerName(),
|
||||||
here.getServerPort(),
|
here.getServerPort(),
|
||||||
here.getContextPath(),
|
here.getContextPath(),
|
||||||
here.getServletPath(),
|
here.getServletPath(),
|
||||||
here.getPathInfo(),
|
here.getPathInfo(),
|
||||||
params);
|
params);
|
||||||
|
|
||||||
paginator.addAttribute("param", PAGINATOR_PARAM);
|
paginator.addAttribute("param", PAGINATOR_PARAM);
|
||||||
paginator.addAttribute("baseURL", XML.format(url));
|
paginator.addAttribute("baseURL", XML.format(url));
|
||||||
paginator.addAttribute("pageNumber", XML.format(new Integer(pageNumber)));
|
paginator.addAttribute("pageNumber", XML.format(new Integer(pageNumber)));
|
||||||
paginator.addAttribute("pageCount", XML.format(new Integer(pageCount)));
|
paginator.addAttribute("pageCount", XML.format(new Integer(pageCount)));
|
||||||
paginator.addAttribute("pageSize", XML.format(new Integer(pageSize)));
|
paginator.addAttribute("pageSize", XML.format(new Integer(pageSize)));
|
||||||
paginator.addAttribute("objectBegin", XML.format(new Long(begin+1)));
|
paginator.addAttribute("objectBegin", XML.format(new Long(begin + 1)));
|
||||||
paginator.addAttribute("objectEnd", XML.format(new Long(end)));
|
paginator.addAttribute("objectEnd", XML.format(new Long(end)));
|
||||||
paginator.addAttribute("objectCount", XML.format(new Long(objectCount)));
|
paginator.addAttribute("objectCount", XML.format(new Long(objectCount)));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue