View Issue Details

IDProjectCategoryView StatusLast Update
0001485Composrcns_forumpublic2014-12-14 00:09
ReporterChris GrahamAssigned ToChris Graham 
SeverityFeature-request 
Status resolvedResolutionfixed 
Product Version 
Fixed in Version 
Summary0001485: Post editing time limit
DescriptionAdd a new forum option, "minutes before post editing locked". Allow it to be left blank.

Add a new privilege, "may edit posts after the time limit".
TagsNo tags attached.
Time estimation (hours)1
Sponsorship open


If users wish to sponsor this issue (optional, some issues are implemented without sponsorship)...
If users wish to sponsor this issue (optional, some issues are implemented without sponsorship)...

Activities

Chris Graham

2014-12-13 23:22

administrator   ~0002388

Thank you for the sponsorship OneRingRules. This has now been implemented. Salman will supply the change in one of his updates.

Chris Graham

2014-12-13 23:36

administrator   ~0002389

Ah, I forgot to mention -- we'll have the same feature for deleting too, separate timer, separate privilege.

Chris Graham

2014-12-14 00:05

administrator   ~0002390

Tuned this a bit more. Rather than working as a flat "deny, don't offer action", it is a bit smarter. As there is a specific reason why this is denied, I've coded the API to feed through this reason. The edit/delete buttons are set to show if there's a specific reason, and upon clicking them you are told that reason.

Chris Graham

2014-12-14 00:09

administrator  

post-edit-times.diff (14,373 bytes)
diff --git a/data_custom/execute_temp.php b/data_custom/execute_temp.php
index ca71f91..dacdca1 100644
--- a/data_custom/execute_temp.php
+++ b/data_custom/execute_temp.php
@@ -55,4 +55,8 @@ if (!headers_sent())
  */
 function execute_temp()
 {
+	add_config_option('EDIT_TIME_LIMIT','edit_time_limit','integer','return \'15\';','SECTION_FORUMS','GENERAL');
+	add_specific_permission('SECTION_FORUMS','exceed_post_edit_time_limit',false);
+	add_config_option('DELETE_TIME_LIMIT','delete_time_limit','integer','return \'15\';','SECTION_FORUMS','GENERAL');
+	add_specific_permission('SECTION_FORUMS','exceed_post_delete_time_limit',false);
 }
diff --git a/forum/pages/modules/topics.php b/forum/pages/modules/topics.php
index f5623bf..90d1b7c 100644
--- a/forum/pages/modules/topics.php
+++ b/forum/pages/modules/topics.php
@@ -2251,6 +2251,18 @@ END;
 		if (is_null($topic_id)) warn_exit(do_lang_tempcode('MISSING_RESOURCE'));
 		$topic_info=$GLOBALS['FORUM_DB']->query_select('f_topics',array('*'),array('id'=>$topic_id),'',1);
 		if (!array_key_exists(0,$topic_info)) warn_exit(do_lang_tempcode('MISSING_RESOURCE'));
+
+		$reason=NULL;
+		$may_delete=ocf_may_delete_post_by($post_id,NULL,NULL,NULL,get_member(),$reason);
+		if (!$may_delete)
+		{
+			if (!is_null($reason))
+			{
+				warn_exit($reason);
+			}
+			access_denied('I_ERROR');
+		}
+
 		$this->handle_topic_breadcrumbs($topic_info[0]['t_forum_id'],$topic_id,$topic_info[0]['t_cache_first_title'],do_lang_tempcode('DELETE_POST'));
 
 		if (has_specific_permission(get_member(),'mass_delete_from_ip'))
@@ -2589,8 +2601,16 @@ END;
 		if (!array_key_exists(0,$post_details)) warn_exit(do_lang_tempcode('MISSING_RESOURCE'));
 
 		$forum_id=$post_details[0]['p_cache_forum_id'];
-		if (!ocf_may_edit_post_by($post_details[0]['p_poster'],$forum_id))
+		$reason=NULL;
+		$may_edit=ocf_may_edit_post_by($post_id,$post_details[0]['p_time'],$post_details[0]['p_poster'],$forum_id,get_member(),$reason);
+		if (!$may_edit)
+		{
+			if (!is_null($reason))
+			{
+				warn_exit($reason);
+			}
 			access_denied('I_ERROR');
+		}
 
 		$topic_info=$GLOBALS['FORUM_DB']->query_select('f_topics',array('*'),array('id'=>$post_details[0]['p_topic_id']),'',1);
 		if (!array_key_exists(0,$topic_info)) warn_exit(do_lang_tempcode('MISSING_RESOURCE'));
@@ -2659,7 +2679,7 @@ END;
 		$options[]=array(do_lang_tempcode('MARK_UNREAD'),'mark_as_unread',false,do_lang_tempcode('DESCRIPTION_MARK_UNREAD'));
 		$options[]=array(do_lang_tempcode('SHOW_AS_EDITED'),'show_as_edited',((time()-$post_details[0]['p_time'])>60*3),do_lang_tempcode('DESCRIPTION_POST_SHOW_AS_EDITED'));
 		$specialisation2->attach(form_input_various_ticks($options,''));
-		if (ocf_may_delete_post_by($post_details[0]['p_poster'],$forum_id))
+		if (ocf_may_delete_post_by($post_id,$post_details[0]['p_time'],$post_details[0]['p_poster'],$forum_id))
 		{
 			$specialisation2->attach(form_input_tick(do_lang_tempcode('DELETE'),do_lang_tempcode('DESCRIPTION_DELETE'),'delete',false));
 		}
diff --git a/forum/pages/modules/topicview.php b/forum/pages/modules/topicview.php
index c28a5e4..6dcffa4 100644
--- a/forum/pages/modules/topicview.php
+++ b/forum/pages/modules/topicview.php
@@ -420,7 +420,7 @@ class Module_topicview
 					unset($topic_info['may_use_quick_reply']);
 				}
 			}
-			elseif (((is_null($topic_info['forum_id'])) || (has_specific_permission(get_member(),'submit_lowrange_content','topics',array('forums',$topic_info['forum_id'])))) && ($topic_info['last_poster']==get_member()) && (!is_guest()) && (ocf_may_edit_post_by(get_member(),$topic_info['forum_id'])))
+			elseif (((is_null($topic_info['forum_id'])) || (has_specific_permission(get_member(),'submit_lowrange_content','topics',array('forums',$topic_info['forum_id'])))) && ($topic_info['last_poster']==get_member()) && (!is_guest()) && (ocf_may_edit_post_by($topic_info['last_post_id'],$topic_info['last_time'],get_member(),$topic_info['forum_id'])))
 			{
 				$map=array('page'=>'topics','type'=>'edit_post','id'=>$topic_info['last_post_id']);
 				$test=get_param_integer('kfs'.strval($topic_info['forum_id']),-1);
diff --git a/lang/EN/ocf.ini b/lang/EN/ocf.ini
index e766d29..cb1a688 100755
--- a/lang/EN/ocf.ini
+++ b/lang/EN/ocf.ini
@@ -972,3 +972,4 @@ MEMBER_ADDED_TO_GROUP=Member added to usergroup
 MEMBER_REMOVED_FROM_GROUP=Member removed from usergroup
 MEMBER_PRIMARY_GROUP_CHANGED=Member primary usergroup changed
 LIFETIME_POINTS=Life-time point earnings; {1} {1|point|points} available to spend
+EXCEEDED_TIME_LIMIT=You can only perform this action within {1} of making the post.
diff --git a/lang/EN/ocf_config.ini b/lang/EN/ocf_config.ini
index 1a3402d..139e5f8 100644
--- a/lang/EN/ocf_config.ini
+++ b/lang/EN/ocf_config.ini
@@ -155,6 +155,12 @@ PT_multi_delete_topics=Can multi-delete topics
 PT_show_user_browsing=See where users currently are on the website, and their choice of web browser
 PT_see_hidden_groups=See hidden usergroups and their membership
 PT_pt_anyone=Whisper to anyone, regardless of their acceptance settings
+EDIT_TIME_LIMIT=Edit time limit
+CONFIG_OPTION_edit_time_limit=The number of minutes before post editing becomes locked (assuming the “May edit posts after the time limit” privilege has not been granted).
+PT_exceed_post_edit_time_limit=May edit posts after the time limit
+DELETE_TIME_LIMIT=Delete time limit
+CONFIG_OPTION_delete_time_limit=The number of minutes before post deleting becomes locked (assuming the “May delete posts after the time limit” privilege has not been granted).
+PT_exceed_post_delete_time_limit=May delete posts after the time limit
 SIGNUP_FULLNAME=Sign-up with full-name
 CONFIG_OPTION_signup_fullname=Members sign-up with their full-name, and are then assigned a username automatically based on this. If someone else is already registered with the name, a numbering suffix is added.
 INTRO_FORUM_ID=Intro forum ID
diff --git a/sources/ocf_posts.php b/sources/ocf_posts.php
index a5445a3..12e4f3b 100644
--- a/sources/ocf_posts.php
+++ b/sources/ocf_posts.php
@@ -56,59 +56,134 @@ function ocf_may_post_in_topic($forum_id,$topic_id,$last_member_id=NULL,$member_
 /**
  * Find whether a member may edit the detailed post.
  *
- * @param  MEMBER			The owner of the post.
- * @param  ?AUTO_LINK 	The forum the post is in (NULL: is a Private Topic).
+ * @param  AUTO_LINK		The post ID.
+ * @param  ?TIME			The time of the post (NULL: lookup).
+ * @param  ?MEMBER		The owner of the post (NULL: lookup).
+ * @param  ?AUTO_LINK 	The forum the post is in (NULL: is a Private Topic, unless $post_time is NULL in which case we look this up too).
  * @param  ?MEMBER		The member (NULL: current member).
+ * @param  ?tempcode		Save the reason into here (NULL: do not save; NULL final value means just generic access denied).
  * @return boolean		The answer.
  */
-function ocf_may_edit_post_by($resource_owner,$forum_id,$member_id=NULL)
+function ocf_may_edit_post_by($post_id,$post_time=NULL,$resource_owner=NULL,$forum_id=NULL,$member_id=NULL,&$reason=NULL)
 {
 	if (is_null($member_id)) $member_id=get_member();
 
+	$reason=NULL;
+
+	if (is_null($post_time))
+	{
+		$posts=$GLOBALS['FORUM_DB']->query_select('f_posts',array('p_time','p_poster','p_cache_forum_id'),array('id'=>$post_id),'',1);
+		if (!array_key_exists(0,$posts))
+		{
+			$reason=do_lang_tempcode('INTERNAL_ERROR');
+			return false;
+		}
+		$post_time=$posts[0]['p_time'];
+		$resource_owner=$posts[0]['p_poster'];
+		$forum_id=$posts[0]['p_cache_forum_id'];
+		// TODO v10: $topic_is_closed
+	}
+
+	if (((time()-$post_time)>intval(get_option('edit_time_limit'))*60) && (!has_specific_permission($member_id,'exceed_edit_time_limit')))
+	{
+		$reason=do_lang_tempcode('EXCEEDED_TIME_LIMIT',escape_html(display_time_period(intval(get_option('edit_time_limit'))*60)));
+		return false;
+	}
+
 	if (is_null($forum_id))
 	{
-		if (has_specific_permission($member_id,'moderate_personal_topic')) return true;
-		if (($resource_owner!=$member_id) || (!has_specific_permission($member_id,'delete_personal_topic_posts'))) return false;
+		if (has_specific_permission($member_id,'moderate_personal_topic'))
+		{
+			return true;
+		}
+		if (($resource_owner!=$member_id) || (!has_specific_permission($member_id,'edit_personal_topic_posts')))
+		{
+			return false;
+		}
 	} else
 	{
 		$ticket_forum=get_option('ticket_forum_name',true);
 		$comments_forum=get_option('comments_forum_name',true);
 		if ((is_null($ticket_forum)) || (($forum_id!=$GLOBALS['FORUM_DRIVER']->forum_id_from_name($ticket_forum)) && ($forum_id!=$GLOBALS['FORUM_DRIVER']->forum_id_from_name($comments_forum))))
 		{
-			if (!has_category_access($member_id,'forums',strval($forum_id))) return false;
+			if (!has_category_access($member_id,'forums',strval($forum_id)))
+			{
+				return false;
+			}
 		}
 	}
 
-	return has_edit_permission('low',$member_id,$resource_owner,'topics',array('forums',$forum_id));
+	if (!has_edit_permission('low',$member_id,$resource_owner,'topics',array('forums',$forum_id)))
+	{
+		return false;
+	}
+	return true;
 }
 
 /**
  * Find whether a member may delete the detailed post.
  *
- * @param  MEMBER			The owner of the post.
- * @param  ?AUTO_LINK 	The forum the post is in (NULL: is a Private Topic).
+ * @param  AUTO_LINK		The post ID.
+ * @param  ?TIME			The time of the post (NULL: lookup).
+ * @param  ?MEMBER		The owner of the post (NULL: lookup).
+ * @param  ?AUTO_LINK 	The forum the post is in (NULL: is a Private Topic, unless $post_time is NULL in which case we look this up too).
  * @param  ?MEMBER		The member (NULL: current member).
+ * @param  ?tempcode		Save the reason into here (NULL: do not save; NULL final value means just generic access denied).
  * @return boolean		The answer.
  */
-function ocf_may_delete_post_by($resource_owner,$forum_id,$member_id=NULL)
+function ocf_may_delete_post_by($post_id,$post_time=NULL,$resource_owner=NULL,$forum_id=NULL,$member_id=NULL,&$reason=NULL)
 {
 	if (is_null($member_id)) $member_id=get_member();
 
+	$reason=NULL;
+
+	if (is_null($post_time))
+	{
+		$posts=$GLOBALS['FORUM_DB']->query_select('f_posts',array('p_time','p_poster','p_cache_forum_id'),array('id'=>$post_id),'',1);
+		if (!array_key_exists(0,$posts))
+		{
+			return false;
+		}
+		$post_time=$posts[0]['p_time'];
+		$resource_owner=$posts[0]['p_poster'];
+		$forum_id=$posts[0]['p_cache_forum_id'];
+		// TODO v10: $topic_is_closed
+	}
+
+	if (((time()-$post_time)>intval(get_option('delete_time_limit'))*60) && (!has_specific_permission($member_id,'exceed_delete_time_limit')))
+	{
+		$reason=do_lang_tempcode('EXCEEDED_TIME_LIMIT',escape_html(display_time_period(intval(get_option('delete_time_limit'))*60)));
+		return false;
+	}
+
 	if (is_null($forum_id))
 	{
-		if (has_specific_permission($member_id,'moderate_personal_topic')) return true;
-		if (($resource_owner!=$member_id) || (!has_specific_permission($member_id,'delete_personal_topic_posts'))) return false;
+		if (has_specific_permission($member_id,'moderate_personal_topic'))
+		{
+			return true;
+		}
+		if (($resource_owner!=$member_id) || (!has_specific_permission($member_id,'delete_personal_topic_posts')))
+		{
+			return false;
+		}
 	} else
 	{
 		$ticket_forum=get_option('ticket_forum_name',true);
 		$comments_forum=get_option('comments_forum_name',true);
 		if ((is_null($ticket_forum)) || (($forum_id!=$GLOBALS['FORUM_DRIVER']->forum_id_from_name($ticket_forum)) && ($forum_id!=$GLOBALS['FORUM_DRIVER']->forum_id_from_name($comments_forum))))
 		{
-			if (!has_category_access($member_id,'forums',strval($forum_id))) return false;
+			if (!has_category_access($member_id,'forums',strval($forum_id)))
+			{
+				return false;
+			}
 		}
 	}
 
-	return has_delete_permission('low',$member_id,$resource_owner,'topics',array('forums',$forum_id));
+	if (!has_delete_permission('low',$member_id,$resource_owner,'topics',array('forums',$forum_id)))
+	{
+		return false;
+	}
+	return true;
 }
 
 /**
diff --git a/sources/ocf_posts_action3.php b/sources/ocf_posts_action3.php
index 46b552b..ee49e9a 100644
--- a/sources/ocf_posts_action3.php
+++ b/sources/ocf_posts_action3.php
@@ -115,7 +115,7 @@ function ocf_edit_post($post_id,$validated,$title,$post,$skip_sig,$is_emphasised
 	ocf_check_post($post);
 
 	if ($check_perms)
-		if (!ocf_may_edit_post_by($post_owner,$forum_id)) access_denied('I_ERROR');
+		if (!ocf_may_edit_post_by($post_id,$post_info[0]['p_time'],$post_owner,$forum_id)) access_denied('I_ERROR');
 	if ((is_null($validated)) || ($validated==1))
 	{
 		if ((!is_null($forum_id)) && (!has_specific_permission(get_member(),'bypass_validation_lowrange_content','topics',array('forums',$forum_id)))) $validated=0; else $validated=1;
@@ -226,7 +226,7 @@ function ocf_delete_posts_topic($topic_id,$posts,$reason)
 	{
 		if ((is_null($post['p_intended_solely_for'])) && ($post['p_validated']==1)) $num_posts_counted++;
 		$post_owner=$post['p_poster'];
-		if (!ocf_may_delete_post_by($post_owner,$forum_id)) access_denied('I_ERROR');
+		if (!ocf_may_delete_post_by($post['id'],$post['p_time'],$post_owner,$forum_id)) access_denied('I_ERROR');
 	}
 
 	// Save in history
diff --git a/sources/ocf_topicview.php b/sources/ocf_topicview.php
index 86fea7a..01f57cf 100755
--- a/sources/ocf_topicview.php
+++ b/sources/ocf_topicview.php
@@ -207,8 +207,20 @@ function ocf_get_details_to_show_post($_postdetails,$only_post=false)
 
 	// Do we have any special controls over this post?
 	require_code('ocf_posts');
-	if (ocf_may_edit_post_by($_postdetails['p_poster'],$forum_id)) $post['may_edit']=true;
-	if ((ocf_may_delete_post_by($_postdetails['p_poster'],$forum_id)) && (!$only_post)) $post['may_delete']=true;
+	$reason=NULL;
+	$may_edit=ocf_may_edit_post_by($_postdetails['id'],$_postdetails['p_time'],$_postdetails['p_poster'],$forum_id,get_member(),$reason);
+	if ($may_edit || $reason!==NULL/*Interesting reason, let them find it out when they click*/)
+	{
+		$post['may_edit']=true;
+	}
+	if (!$only_post)
+	{
+		$may_delete=ocf_may_delete_post_by($_postdetails['id'],$_postdetails['p_time'],$_postdetails['p_poster'],$forum_id,get_member(),$reason);
+		if ($may_delete || $reason!==NULL/*Interesting reason, let them find it out when they click*/)
+		{
+			$post['may_delete']=true;
+		}
+	}
 
 	// More
 	if (has_specific_permission(get_member(),'see_ip')) $post['ip_address']=$_postdetails['p_ip_address'];
post-edit-times.diff (14,373 bytes)

Issue History

Date Modified Username Field Change