Example #1
0
		/// <summary>
		/// Updates the user/forum/thread statistics after a message insert. Also makes sure if the thread isn't in a queue and the forum has a default support
		/// queue that the thread is added to that queue
		/// </summary>
		/// <param name="threadID">The thread ID.</param>
		/// <param name="userID">The user ID.</param>
		/// <param name="transactionToUse">The transaction to use.</param>
		/// <param name="postingDate">The posting date.</param>
		/// <param name="addToQueueIfRequired">if set to true, the thread will be added to the default queue of the forum the thread is in, if the forum
		/// has a default support queue and the thread isn't already in a queue.</param>
		/// <remarks>Leaves the passed in transaction open, so it doesn't commit/rollback, it just performs a set of actions inside the
		/// passed in transaction.</remarks>
		internal static void UpdateStatisticsAfterMessageInsert(int threadID, int userID, Transaction transactionToUse, DateTime postingDate, bool addToQueueIfRequired, bool subscribeToThread)
		{
			// user statistics
			UserEntity userUpdater = new UserEntity();
			// set the amountofpostings field to an expression so it will be increased with 1. 
			userUpdater.Fields[(int)UserFieldIndex.AmountOfPostings].ExpressionToApply = (UserFields.AmountOfPostings + 1);
			UserCollection users = new UserCollection();
			transactionToUse.Add(users);
			users.UpdateMulti(userUpdater, (UserFields.UserID == userID));	// update directly on the DB. 

			// thread statistics
			ThreadEntity threadUpdater = new ThreadEntity();
			threadUpdater.ThreadLastPostingDate = postingDate;
			threadUpdater.MarkedAsDone = false;
			ThreadCollection threads = new ThreadCollection();
			transactionToUse.Add(threads);
			threads.UpdateMulti(threadUpdater, (ThreadFields.ThreadID == threadID));

			// forum statistics. Load the forum from the DB, as we need it later on. Use a fieldcompareset predicate to fetch the forum as we don't know the 
			// forumID as we haven't fetched the thread
			ForumCollection forums = new ForumCollection();
			transactionToUse.Add(forums);
			// use a fieldcompare set predicate to select the forumid based on the thread. This filter is equal to
			// WHERE ForumID == (SELECT ForumID FROM Thread WHERE ThreadID=@ThreadID)
			var forumFilter = new FieldCompareSetPredicate(
								ForumFields.ForumID, ThreadFields.ForumID, SetOperator.Equal, (ThreadFields.ThreadID == threadID));
			forums.GetMulti(forumFilter);
			ForumEntity containingForum = null;
			if(forums.Count>0)
			{
				// forum found. There's just one.
				containingForum = forums[0];
				containingForum.ForumLastPostingDate = postingDate;
				// save the forum. Just save the collection
				forums.SaveMulti();
			}

			if(addToQueueIfRequired)
			{
				// If the thread involved isn't in a queue, place it in the default queue of the forum (if applicable)
				SupportQueueEntity containingQueue = SupportQueueGuiHelper.GetQueueOfThread(threadID, transactionToUse);
				if((containingQueue == null) && (containingForum != null) && (containingForum.DefaultSupportQueueID.HasValue))
				{
					// not in a queue, and the forum has a default queue. Add the thread to the queue of the forum
					SupportQueueManager.AddThreadToQueue(threadID, containingForum.DefaultSupportQueueID.Value, userID, transactionToUse);
				}
			}

            //subscribe to thread if indicated
            if(subscribeToThread)
            {
				UserManager.AddThreadToSubscriptions(threadID, userID, transactionToUse);
            }
		}
Example #2
0
        /// <summary>
        /// Marks the thread as done.
        /// </summary>
        /// <param name="threadID">Thread ID.</param>
        /// <returns></returns>
        public static bool MarkThreadAsDone(int threadID)
        {
            // load the entity from the database
            ThreadEntity thread = ThreadGuiHelper.GetThread(threadID);

            if (thread == null)
            {
                // not found
                return(false);
            }

            // get the support queue the thread is in (if any)
            SupportQueueEntity containingSupportQueue = SupportQueueGuiHelper.GetQueueOfThread(threadID);

            thread.MarkedAsDone = true;

            // if the thread is in a support queue, the thread has to be removed from that queue. This is a multi-entity action and therefore we've to start a
            // transaction if that's the case. If not, we can use the easy route and simply save the thread and be done with it.
            if (containingSupportQueue == null)
            {
                // not in a queue, simply save the thread.
                return(thread.Save());
            }

            // in a queue, so remove from the queue and save the entity.
            Transaction trans = new Transaction(IsolationLevel.ReadCommitted, "MarkThreadDone");

            trans.Add(thread);
            try
            {
                // save the thread
                bool result = thread.Save();
                if (result)
                {
                    // save succeeded, so remove from queue, pass the current transaction to the method so the action takes place inside this transaction.
                    SupportQueueManager.RemoveThreadFromQueue(threadID, trans);
                }

                trans.Commit();
                return(true);
            }
            catch
            {
                // rollback transaction
                trans.Rollback();
                throw;
            }
            finally
            {
                trans.Dispose();
            }
        }
Example #3
0
        /// <summary>
        /// Marks the thread as done.
        /// </summary>
        /// <param name="threadId">Thread ID.</param>
        /// <returns></returns>
        public static async Task <bool> MarkThreadAsDoneAsync(int threadId)
        {
            var thread = await ThreadGuiHelper.GetThreadAsync(threadId);

            if (thread == null)
            {
                // not found
                return(false);
            }

            var containingSupportQueue = await SupportQueueGuiHelper.GetQueueOfThreadAsync(threadId);

            thread.MarkedAsDone = true;
            using (var adapter = new DataAccessAdapter())
            {
                // if the thread is in a support queue, the thread has to be removed from that queue. This is a multi-entity action and therefore we've to start a
                // transaction if that's the case. If not, we can use the easy route and simply save the thread and be done with it.
                if (containingSupportQueue == null)
                {
                    // not in a queue, simply save the thread.
                    return(await adapter.SaveEntityAsync(thread).ConfigureAwait(false));
                }

                // in a queue, so remove from the queue and save the entity.
                await adapter.StartTransactionAsync(IsolationLevel.ReadCommitted, "MarkThreadDone").ConfigureAwait(false);

                try
                {
                    // save the thread
                    var result = await adapter.SaveEntityAsync(thread).ConfigureAwait(false);

                    if (result)
                    {
                        // save succeeded, so remove from queue, pass the current adapter to the method so the action takes place inside this transaction.
                        await SupportQueueManager.RemoveThreadFromQueueAsync(threadId, adapter);
                    }

                    adapter.Commit();
                    return(true);
                }
                catch
                {
                    // rollback transaction
                    adapter.Rollback();
                    throw;
                }
            }
        }
Example #4
0
        /// <summary>
        /// Creates a new message in the given thread and closes the thread right after the addition of the message,
        /// which makes the just added message the 'close' message of the thread. Close messages are handy when the
        /// closure of a thread is not obvious.
        /// Caller should validate input parameters.
        /// </summary>
        /// <param name="threadID">Thread wherein the new message will be placed</param>
        /// <param name="userID">User who posted this message</param>
        /// <param name="messageText">Message text</param>
        /// <param name="messageAsHTML">Message text as HTML</param>
        /// <param name="userIDIPAddress">IP address of user calling this method</param>
        /// <param name="messageAsXML">Message text as XML, which is the result of the parse action on MessageText.</param>
        /// <param name="threadUpdatedNotificationTemplate">The thread updated notification template.</param>
        /// <param name="emailData">The email data.</param>
        /// <param name="sendReplyNotifications">Flag to signal to send reply notifications. If set to false no notifications are mailed,
        /// otherwise a notification is mailed to all subscribers to the thread the new message is posted in</param>
        /// <returns>MessageID if succeeded, 0 if not.</returns>
        public static int CreateNewMessageInThreadAndCloseThread(int threadID, int userID, string messageText, string messageAsHTML,
                                                                 string userIDIPAddress, string messageAsXML, string threadUpdatedNotificationTemplate, Dictionary <string, string> emailData,
                                                                 bool sendReplyNotifications)
        {
            Transaction trans     = new Transaction(IsolationLevel.ReadCommitted, "InsertNewMessage");
            int         messageID = 0;

            try
            {
                DateTime postingDate = DateTime.Now;
                messageID = InsertNewMessage(threadID, userID, messageText, messageAsHTML, userIDIPAddress, messageAsXML, trans, postingDate);

                MessageManager.UpdateStatisticsAfterMessageInsert(threadID, userID, trans, postingDate, false, false);

                ThreadEntity thread = new ThreadEntity();
                trans.Add(thread);
                thread.FetchUsingPK(threadID);
                thread.IsClosed     = true;
                thread.IsSticky     = false;
                thread.MarkedAsDone = true;
                bool result = thread.Save();
                if (result)
                {
                    // save succeeded, so remove from queue, pass the current transaction to the method so the action takes place inside this transaction.
                    SupportQueueManager.RemoveThreadFromQueue(threadID, trans);
                }

                trans.Commit();
            }
            catch (Exception)
            {
                trans.Rollback();
                throw;
            }
            finally
            {
                trans.Dispose();
            }

            if (sendReplyNotifications)
            {
                // send notification email to all subscribers. Do this outside the transaction so a failed email send action doesn't terminate the save process
                // of the message.
                ThreadManager.SendThreadReplyNotifications(threadID, userID, threadUpdatedNotificationTemplate, emailData);
            }
            return(messageID);
        }
Example #5
0
        /// <summary>
        /// Marks the thread as un-done, and add it to the default queue of the forum.
        /// </summary>
        /// <param name="threadID">Thread ID</param>
        /// <returns></returns>
        public static bool UnMarkThreadAsDone(int threadID, int userID)
        {
            // load the entity from the database
            ThreadEntity thread = ThreadGuiHelper.GetThread(threadID);

            if (thread == null)
            {
                // not found
                return(false);
            }

            thread.MarkedAsDone = false;

            ForumEntity forum = new ForumEntity(thread.ForumID);

            // Save the thread and add it to the default queue of the forum.
            Transaction trans = new Transaction(IsolationLevel.ReadCommitted, "MarkThreadUnDone");

            trans.Add(thread);
            try
            {
                thread.Save();

                if ((forum.Fields.State == EntityState.Fetched) && (forum.DefaultSupportQueueID.HasValue))
                {
                    // not in a queue, and the forum has a default queue. Add the thread to the queue of the forum
                    SupportQueueManager.AddThreadToQueue(threadID, forum.DefaultSupportQueueID.Value, userID, trans);
                }

                trans.Commit();
                return(true);
            }
            catch
            {
                // rollback transaction
                trans.Rollback();
                throw;
            }
            finally
            {
                trans.Dispose();
            }
        }
Example #6
0
        /// <summary>
        /// Marks the thread as un-done, and add it to the default queue of the forum.
        /// </summary>
        /// <param name="threadId">Thread ID</param>
        /// <param name="userId">the user adding the thread to a queue by unmarking it as done </param>
        /// <returns></returns>
        public static async Task <bool> UnMarkThreadAsDoneAsync(int threadId, int userId)
        {
            var thread = await ThreadGuiHelper.GetThreadAsync(threadId);

            if (thread == null)
            {
                // not found
                return(false);
            }

            thread.MarkedAsDone = false;
            using (var adapter = new DataAccessAdapter())
            {
                // Save the thread and add it to the default queue of the forum.
                await adapter.StartTransactionAsync(IsolationLevel.ReadCommitted, "MarkThreadUnDone").ConfigureAwait(false);

                try
                {
                    await adapter.SaveEntityAsync(thread, true).ConfigureAwait(false);

                    var q     = new QueryFactory().Forum.Where(ForumFields.ForumID.Equal(thread.ForumID));
                    var forum = await adapter.FetchFirstAsync(q).ConfigureAwait(false);

                    if (forum?.DefaultSupportQueueID != null)
                    {
                        // not in a queue, and the forum has a default queue. Add the thread to the queue of the forum
                        await SupportQueueManager.AddThreadToQueueAsync(threadId, forum.DefaultSupportQueueID.Value, userId, adapter);
                    }

                    adapter.Commit();
                    return(true);
                }
                catch
                {
                    // rollback transaction
                    adapter.Rollback();
                    throw;
                }
            }
        }
Example #7
0
        /// <summary>
        /// Modifies the given properties of the given thread.
        /// </summary>
        /// <param name="threadId">The threadID of the thread which properties should be changed</param>
        /// <param name="subject">The new subject for this thread</param>
        /// <param name="isSticky">The new value for IsSticky</param>
        /// <param name="isClosed">The new value for IsClosed</param>
        public static async Task ModifyThreadPropertiesAsync(int threadId, string subject, bool isSticky, bool isClosed)
        {
            var thread = await ThreadGuiHelper.GetThreadAsync(threadId);

            if (thread == null)
            {
                // not found
                return;
            }

            // update the fields with new values
            thread.Subject  = subject;
            thread.IsSticky = isSticky;
            thread.IsClosed = isClosed;
            using (var adapter = new DataAccessAdapter())
            {
                await adapter.StartTransactionAsync(IsolationLevel.ReadCommitted, "ModifyThreadProperties");

                try
                {
                    var result = await adapter.SaveEntityAsync(thread).ConfigureAwait(false);

                    if (result)
                    {
                        // save succeeded, so remove from queue, pass the current transaction to the method so the action takes place inside this transaction.
                        await SupportQueueManager.RemoveThreadFromQueueAsync(threadId, adapter);
                    }

                    adapter.Commit();
                }
                catch
                {
                    adapter.Rollback();
                    throw;
                }
            }
        }
Example #8
0
        /// <summary>
        /// Updates the user/forum/thread statistics after a message insert. Also makes sure if the thread isn't in a queue and the forum has a default support
        /// queue that the thread is added to that queue
        /// </summary>
        /// <param name="threadId">The thread ID.</param>
        /// <param name="userId">The user ID.</param>
        /// <param name="newMessageId">The message id of the new message posted in the thread with threadid. If 0 or lower it's ignored and threadstatistics
        /// aren't updated. This is the case for when a new thread: the first message insert already inserted a correct threadstatistics object. </param>
        /// <param name="adapter">The adapter to use, which is assumed to have a live transaction active</param>
        /// <param name="postingDate">The posting date.</param>
        /// <param name="addToQueueIfRequired">if set to true, the thread will be added to the default queue of the forum the thread is in, if the forum
        /// has a default support queue and the thread isn't already in a queue.</param>
        /// <param name="subscribeToThread">if set to <c>true</c> [subscribe to thread].</param>
        /// <remarks>
        /// Leaves the passed in transaction open, so it doesn't commit/rollback, it just performs a set of actions inside the
        /// passed in transaction.
        /// </remarks>
        internal static async Task UpdateStatisticsAfterMessageInsert(int threadId, int userId, int newMessageId, IDataAccessAdapter adapter, DateTime postingDate,
                                                                      bool addToQueueIfRequired, bool subscribeToThread)
        {
            // user statistics
            var userUpdater = new UserEntity();

            // set the amountofpostings field to an expression so it will be increased with 1. Update the entity directly in the DB
            userUpdater.Fields[(int)UserFieldIndex.AmountOfPostings].ExpressionToApply = (UserFields.AmountOfPostings + 1);
            await adapter.UpdateEntitiesDirectlyAsync(userUpdater, new RelationPredicateBucket(UserFields.UserID.Equal(userId)))
            .ConfigureAwait(false);

            if (newMessageId > 0)
            {
                // thread statistics. Create a single Update query which updates the messageid and increases the number of messages value with 1
                var threadStatisticsUpdater = new ThreadStatisticsEntity {
                    LastMessageID = newMessageId
                };
                threadStatisticsUpdater.Fields[(int)ThreadStatisticsFieldIndex.NumberOfMessages].ExpressionToApply = (ThreadStatisticsFields.NumberOfMessages + 1);
                await adapter.UpdateEntitiesDirectlyAsync(threadStatisticsUpdater, new RelationPredicateBucket(ThreadStatisticsFields.ThreadID.Equal(threadId)))
                .ConfigureAwait(false);
            }

            // unmark the thread as done if it's done
            var threadUpdater = new ThreadEntity()
            {
                MarkedAsDone = false
            };
            await adapter.UpdateEntitiesDirectlyAsync(threadUpdater, new RelationPredicateBucket(ThreadFields.ThreadID.Equal(threadId)))
            .ConfigureAwait(false);

            // forum statistics. Load the forum from the DB, as we need it later on. Use a nested query to fetch the forum as we don't know the
            // forumID as we haven't fetched the thread
            var qf = new QueryFactory();
            var q  = qf.Forum
                     .Where(ForumFields.ForumID.In(qf.Create()
                                                   .Select(ThreadFields.ForumID)
                                                   .Where(ThreadFields.ThreadID.Equal(threadId))));
            var containingForum = await adapter.FetchFirstAsync(q).ConfigureAwait(false);

            if (containingForum != null)
            {
                containingForum.ForumLastPostingDate = postingDate;

                // save the forum.
                await adapter.SaveEntityAsync(containingForum, true).ConfigureAwait(false);

                if (addToQueueIfRequired && containingForum.DefaultSupportQueueID.HasValue)
                {
                    // If the thread involved isn't in a queue, place it in the default queue of the forum (if applicable)
                    var containingQueue = await SupportQueueGuiHelper.GetQueueOfThreadAsync(threadId, adapter);

                    if (containingQueue == null)
                    {
                        // not in a queue, and the forum has a default queue. Add the thread to the queue of the forum
                        await SupportQueueManager.AddThreadToQueueAsync(threadId, containingForum.DefaultSupportQueueID.Value, userId, adapter);
                    }
                }
            }

            //subscribe to thread if indicated
            if (subscribeToThread)
            {
                await UserManager.AddThreadToSubscriptionsAsync(threadId, userId, adapter);
            }
        }