Exemple #1
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;
                }
            }
        }
Exemple #2
0
        /// <summary>
        /// Moves the given thread to the given forum.
        /// </summary>
        /// <param name="threadId">ID of thread to move</param>
        /// <param name="newForumId">ID of forum to move the thread to</param>
        /// <returns></returns>
        public static async Task <bool> MoveThreadAsync(int threadId, int newForumId)
        {
            var thread = await ThreadGuiHelper.GetThreadAsync(threadId);

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

            thread.ForumID = newForumId;
            using (var adapter = new DataAccessAdapter())
            {
                return(await adapter.SaveEntityAsync(thread).ConfigureAwait(false));
            }
        }
Exemple #3
0
        /// <summary>
        /// Updates the memo field for the given thread
        /// </summary>
        /// <param name="threadId">Thread ID.</param>
        /// <param name="memo">Memo.</param>
        /// <returns></returns>
        public static async Task <bool> UpdateMemoAsync(int threadId, string memo)
        {
            // load the entity from the database
            var thread = await ThreadGuiHelper.GetThreadAsync(threadId);

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

            using (var adapter = new DataAccessAdapter())
            {
                thread.Memo = memo;
                return(await adapter.SaveEntityAsync(thread).ConfigureAwait(false));
            }
        }
Exemple #4
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;
                }
            }
        }
Exemple #5
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;
                }
            }
        }
Exemple #6
0
        /// <summary>
        /// Sends email to all users subscribed to a specified thread, except the user who initiated the thread update.
        /// </summary>
        /// <param name="threadId">The thread that was updated.</param>
        /// <param name="initiatedByUserId">The user who initiated the update (who will not receive notification).</param>
        /// <param name="emailData">The email data.</param>
        private static async Task SendThreadReplyNotifications(int threadId, int initiatedByUserId, Dictionary <string, string> emailData)
        {
            // get list of subscribers to thread, minus the initiator. Do this by fetching the subscriptions plus the related user entity entity instances.
            // The related user entities are loaded using a prefetch path.
            var q = new QueryFactory().ThreadSubscription
                    .Where((ThreadSubscriptionFields.ThreadID.Equal(threadId)).And(ThreadSubscriptionFields.UserID.NotEqual(initiatedByUserId)))
                    .WithPath(ThreadSubscriptionEntity.PrefetchPathUser);
            var subscriptions = new EntityCollection <ThreadSubscriptionEntity>();

            using (var adapter = new DataAccessAdapter())
            {
                await adapter.FetchQueryAsync(q, subscriptions).ConfigureAwait(false);

                if (subscriptions.Count <= 0)
                {
                    // no subscriptions, nothing to do
                    return;
                }
            }

            // now collect all email addresses into an array so we can pass that to the email routine.
            var toAddresses = new string[subscriptions.Count];

            for (var i = 0; i < subscriptions.Count; i++)
            {
                toAddresses[i] = subscriptions[i].User.EmailAddress;
            }

            // use template to construct message to send.
            var emailTemplate = emailData.GetValue("emailTemplate") ?? string.Empty;
            var mailBody      = SD.HnD.Utility.StringBuilderCache.Acquire(emailTemplate.Length + 256);

            mailBody.Append(emailTemplate);
            var applicationURL = emailData.GetValue("applicationURL") ?? string.Empty;

            if (!string.IsNullOrEmpty(emailTemplate))
            {
                // Use the existing template to format the body
                var siteName = emailData.GetValue("siteName") ?? string.Empty;
                var thread   = await ThreadGuiHelper.GetThreadAsync(threadId);

                if (thread == null)
                {
                    // thread doesn't exist, exit
                    return;
                }

                var threadSubject = thread.Subject;
                var threadUrl     = string.Format("{0}Thread/{1}", applicationURL, thread.ThreadID);
                mailBody.Replace("[SiteURL]", applicationURL);
                mailBody.Replace("[SiteName]", siteName);
                mailBody.Replace("[ThreadSubject]", threadSubject);
                mailBody.Replace("[ThreadURL]", threadUrl);
            }

            // format the subject
            var subject     = (emailData.GetValue("emailThreadNotificationSubject") ?? string.Empty);
            var fromAddress = emailData.GetValue("defaultFromEmailAddress") ?? string.Empty;

            try
            {
                //send message
                await HnDGeneralUtils.SendEmail(subject, SD.HnD.Utility.StringBuilderCache.GetStringAndRelease(mailBody), fromAddress, toAddresses, emailData)
                .ConfigureAwait(false);
            }
            catch (SmtpFailedRecipientsException)
            {
                // swallow as it shouldn't have any effect on further operations
            }
            catch (SmtpException)
            {
                // swallow, as there's nothing we can do
            }
            catch (SmtpCommandException)
            {
                // recipient didn't exist, forget it.
            }

            // rest: problematic, so bubble upwards.
        }