public List <CommentDTO> Get(CommentFilter filter)
 {
     using (var unitOfWork = UnitOfWorkProvider.Create())
     {
         return(CreateQuery(filter).Execute().ToList());
     }
 }
Example #2
0
        protected void lkbPost_Click(object sender, EventArgs e)
        {
            try
            {
                var entry = new Trackback(EntryId, txbTitle.Text, txbUrl.Text.EnsureUrl(), string.Empty,
                                          txbBody.Text.Trim().Length > 0 ? txbBody.Text.Trim() : txbTitle.Text);
                var commentService = new CommentService(SubtextContext, null);

                if (commentService.Create(entry, true /*runFilters*/) > 0)
                {
                    ICommentSpamService feedbackService = null;
                    if (Config.CurrentBlog.FeedbackSpamServiceEnabled)
                    {
                        feedbackService = new AkismetSpamService(Config.CurrentBlog.FeedbackSpamServiceKey,
                                                                 Config.CurrentBlog, null, Url);
                    }
                    var filter = new CommentFilter(SubtextContext, feedbackService);
                    filter.FilterAfterPersist(entry);
                    Messages.ShowMessage(Constants.RES_SUCCESSNEW);
                    Edit.Visible    = false;
                    Results.Visible = true;
                }
                else
                {
                    Messages.ShowError(Constants.RES_FAILUREEDIT
                                       + " There was a baseline problem posting your Trackback.");
                }
            }
            catch (Exception ex)
            {
                Log.Error(ex.Message, ex);
                Messages.ShowError(String.Format(Constants.RES_EXCEPTION,
                                                 Constants.RES_FAILUREEDIT, ex.Message));
            }
        }
Example #3
0
        public async Task <IEnumerable <CommentAggregate> > GetAggregatesAsync(CommentFilter commentFilter)
        {
            using (IDbConnection connection = Connection) {
                string sql =
                    $@"SELECT TOP {commentFilter.Limit} Q.* FROM (
	                    SELECT T.*, ROW_NUMBER() OVER ({BuildAggregateOrderBy(commentFilter.DisplayOrderType)}) AS RN FROM (
		                    SELECT
			                    c.Id,
			                    c.CountdownId,
			                    c.Text,
			                    c.CreatedByAccountId,
			                    c.CreatedOn,
			                    a.DisplayName AS CreatedByDisplayName,
			                    a.Email AS CreatedByEmail,
			                    ISNULL((SELECT SUM(Value) FROM Votes WHERE CommentId = c.Id), 0) AS VoteScore,
			                    (SELECT VALUE FROM Votes WHERE CommentId = c.Id AND CastedByAccountId = @CurrentUserAccountId) AS CurrentUserVote,
                                (CASE WHEN CreatedByAccountId = @currentUserAccountId THEN 1 ELSE 0 END) AS IsCreatedByCurrentUser
		                    FROM Comments c
		                    INNER JOIN Accounts a ON c.CreatedByAccountId = a.Id
                            WHERE c.CountdownId = @CountdownId
	                    ) AS T
                    ) AS Q
                    WHERE Q.RN > {(commentFilter.Page - 1)*commentFilter.Limit} ORDER BY Q.RN";
                return(await connection.QueryAsync <CommentAggregate>(sql, commentFilter));
            }
        }
Example #4
0
        private string XlatStmts(string pyStmt)
        {
            var rdr = new StringReader(pyStmt);
            var lex = new Lexer("foo.py", rdr);
            var flt = new CommentFilter(lex);
            var par = new Parser("foo.py", flt);
            var stm = par.stmt();
            var gen = new CodeGenerator(new CodeCompileUnit(), "", "module");

            gen.SetCurrentMethod(new CodeMemberMethod());
            var types = new TypeReferenceTranslator(new Dictionary <Node, DataType>());
            var xlt   = new StatementTranslator(types, gen, new SymbolGenerator(), new HashSet <string>());

            stm[0].Accept(xlt);
            var pvd    = new CSharpCodeProvider();
            var writer = new StringWriter();

            foreach (CodeStatement csStmt in gen.Scope)
            {
                pvd.GenerateCodeFromStatement(
                    csStmt,
                    writer,
                    new CodeGeneratorOptions
                {
                });
            }
            return(writer.ToString());
        }
Example #5
0
        private string XlatModule(string pyModule)
        {
            var rdr   = new StringReader(pyModule);
            var lex   = new Lexer("foo.py", rdr);
            var flt   = new CommentFilter(lex);
            var par   = new Parser("foo.py", flt);
            var stm   = par.stmt();
            var unt   = new CodeCompileUnit();
            var gen   = new CodeGenerator(unt, "test", "testModule");
            var types = new TypeReferenceTranslator(new Dictionary <Node, DataType>());
            var xlt   = new StatementTranslator(types, gen, new SymbolGenerator(), new HashSet <string>());

            stm[0].Accept(xlt);
            var pvd    = new CSharpCodeProvider();
            var writer = new StringWriter();

            foreach (CodeNamespace ns in unt.Namespaces)
            {
                foreach (CodeNamespaceImport imp in ns.Imports)
                {
                    writer.WriteLine("using {0};", SanitizeNamespace(imp.Namespace, gen));
                }
                foreach (CodeTypeDeclaration type in ns.Types)
                {
                    pvd.GenerateCodeFromType(
                        type,
                        writer,
                        new CodeGeneratorOptions
                    {
                    });
                }
            }
            return(writer.ToString());
        }
Example #6
0
        public void FilterAfterPersistWithCommentModerationEnabledCausesNewCommentsToNeedApproval()
        {
            //arrange
            var subtextContext = new Mock <ISubtextContext>();
            var cache          = new TestCache();

            subtextContext.Setup(c => c.Cache).Returns(cache);
            subtextContext.Setup(c => c.User.IsInRole("Admins")).Returns(false);
            subtextContext.Setup(c => c.Blog).Returns(new Blog {
                ModerationEnabled = true
            });
            FeedbackItem savedFeedback = null;

            subtextContext.Setup(c => c.Repository.UpdateInternal(It.IsAny <FeedbackItem>())).Callback <FeedbackItem>(
                f => savedFeedback = f);

            var commentSpamFilter = new Mock <ICommentSpamService>();
            var commentFilter     = new CommentFilter(subtextContext.Object, commentSpamFilter.Object);
            var feedback          = new FeedbackItem(FeedbackType.Comment);

            Assert.IsFalse(feedback.NeedsModeratorApproval);

            //act
            commentFilter.FilterAfterPersist(feedback);

            //assert
            Assert.IsTrue(savedFeedback.NeedsModeratorApproval);
        }
        protected IQuery <CommentDTO> CreateQuery(CommentFilter filter = null)
        {
            var query = CommentListQuery;

            query.Filter = filter;
            return(query);
        }
Example #8
0
        /// <summary>
        /// Gets all the comments for the specified Community.
        /// </summary>
        /// <param name="filter">Filter which comments to be fetched</param>
        /// <param name="pageDetails">Details about the pagination</param>
        /// <returns>List of all comments of the Community</returns>
        public async Task <IEnumerable <CommentDetails> > GetCommunityComments(CommentFilter filter, PageDetails pageDetails)
        {
            this.CheckNotNull(() => new { filter, pageDetails });

            Func <CommunityComments, object>             orderBy   = (communityComments) => communityComments.CommentedDatetime;
            Expression <Func <CommunityComments, bool> > condition = (communityComments) => communityComments.CommunityID == filter.EntityId && communityComments.IsDeleted == false;

            // Gets the total items satisfying the
            var totalItemsForCondition = _communityCommentRepository.GetItemsCount(condition);

            pageDetails.TotalPages = (totalItemsForCondition / pageDetails.ItemsPerPage) + ((totalItemsForCondition % pageDetails.ItemsPerPage == 0) ? 0 : 1);

            IEnumerable <CommunityComments> comments = _communityCommentRepository
                                                       .GetItems(condition, orderBy, filter.OrderType == OrderType.NewestFirst, (pageDetails.CurrentPage - 1) * pageDetails.ItemsPerPage, pageDetails.ItemsPerPage);

            var commentDetails = new List <CommentDetails>();

            if (comments != null)
            {
                foreach (var item in comments)
                {
                    var comment = new CommentDetails();
                    Mapper.Map(item, comment);
                    commentDetails.Add(comment);
                }
            }

            return(commentDetails);
        }
Example #9
0
        public void FilterBeforePersistDoesNotAllowDuplicateComments()
        {
            //arrange
            var recentCommentChecksums = new Queue <string>();

            recentCommentChecksums.Enqueue("TestChecksum");
            var subtextContext = new Mock <ISubtextContext>();
            var cache          = new TestCache();

            cache["COMMENT FILTER:.RECENT_COMMENTS"] = recentCommentChecksums;
            subtextContext.Setup(c => c.Cache).Returns(cache);
            subtextContext.Setup(c => c.User.IsInRole("Admins")).Returns(false);
            subtextContext.Setup(c => c.Blog).Returns(new Blog {
                CommentDelayInMinutes = 0, DuplicateCommentsEnabled = false
            });
            var commentSpamFilter = new Mock <ICommentSpamService>();
            var commentFilter     = new CommentFilter(subtextContext.Object, commentSpamFilter.Object);

            //act, assert
            UnitTestHelper.AssertThrows <CommentDuplicateException>(() =>
                                                                    commentFilter.FilterBeforePersist(
                                                                        new FeedbackItem(FeedbackType.Comment)
            {
                ChecksumHash = "TestChecksum"
            })
                                                                    );
        }
Example #10
0
        // GET: api/Comment
        public IActionResult Get(CommentFilter filter)
        {
            var list = CommentService.List(filter);

            var result = Mapper.Map <IEnumerable <CommentDTO> >(list.Items);

            return(Ok(new PagedList <CommentDTO>(result, list)));
        }
        public void ShouldRejectModificationsWithNullComments()
        {
            Modification  modification = new Modification();
            CommentFilter filter       = new CommentFilter();

            filter.Pattern = ".*";
            Assert.IsFalse(filter.Accept(modification), "Should not have matched but did.");
        }
Example #12
0
 public DataTable GetCommentByCommentId(CommentFilter commentFilter)
 {
     IDataParameter[] parameter = new SqlParameter[]
     {
         new SqlParameter("@CommentId", commentFilter.CommentId),
     };
     return(ExecuteQuery("usp_GetCommentByCommentId", parameter));
 }
Example #13
0
        /// <summary>
        /// Gets the total number of content comments for the given filter.
        /// </summary>
        /// <param name="filter">Filter which comments to be fetched</param>
        /// <returns>total number of content comments.</returns>
        public int GetTotalContentComments(CommentFilter filter)
        {
            this.CheckNotNull(() => new { filter });

            Expression <Func <ContentComments, bool> > condition = (contentComments) => contentComments.ContentID == filter.EntityId && contentComments.IsDeleted == false;

            return(_contentCommentsRepository.GetItemsCount(condition));
        }
        // GET: /Comments
        public virtual ActionResult CommentList(int taskId)
        {
            var commentFilter = new CommentFilter().ByTask(taskId);
            var comments = CommentService.GetAll(Query.ForComment(commentFilter).Include(x => x.Employee()));

            var model = new CommentListViewModel { Comments = comments, TaskId = taskId };
            return PartialView(MVC.Comments.Views._ListComment, model);
        }
        BaseResponse <Comment> IComments.GetAllComments(CommentFilter filters)
        {
            var apiParams = filters.GetQueryParams();
            var url       = $"{_baseApiUrl}/comments?key={_apiKey}&{apiParams}";
            var response  = _httpClient.GetAsync(url).Result.Content.ReadAsStringAsync().Result;
            var apiResult = response.DeserializeJson <Data <Comment> >().ValidateApiResponse();

            return(apiResult);
        }
Example #16
0
        public static TNode RemoveComments <TNode>(TNode node, CommentFilter comments) where TNode : SyntaxNode
        {
            if (node == null)
            {
                throw new ArgumentNullException(nameof(node));
            }

            return(RemoveComments(node, node.FullSpan, comments));
        }
 internal CommentRestrictionData(StoreSession storeSession, CommentFilter filter)
 {
     base.ParseQueryFilter(storeSession, filter.Filter);
     this.PropValues = new PropValueData[filter.Values.Length];
     for (int i = 0; i < filter.Values.Length; i++)
     {
         this.PropValues[i] = new PropValueData((PropTag)base.GetPropTagFromDefinition(storeSession, filter.Properties[i]), filter.Values[i]);
     }
 }
Example #18
0
 public async Task <Comment[]> GetCommentsAsync(CommentFilter filter)
 {
     return(await Task.Factory.FromAsync
            (
                WordPressService.BeginGetComments(WordPressSiteConfig.BlogId, WordPressSiteConfig.Username,
                                                  WordPressSiteConfig.Password, filter),
                WordPressService.EndGetComments
            ));
 }
        BaseResponse <Comment> IComments.GetAllComments(CommentFilter filters)
        {
            var url = ApiUrlBuilder.Initialize(_apiKey)
                      .ForClient(ClientType.Comments)
                      .WithFilter(filters)
                      .GetApiUrl();
            var response = _httpClient.GetAsync(url).Result.ReadAsJsonAsync <Data <Comment> >().ValidateApiResponse();

            return(response);
        }
        public void ShouldRejectModificationsWithMatchingComments()
        {
            Modification modification = new Modification();

            modification.Comment = "This is a comment.";
            CommentFilter filter = new CommentFilter();

            filter.Pattern = ".* is not a .*";
            Assert.IsFalse(filter.Accept(modification), "Should not have matched but did.");
        }
Example #21
0
        public void Translate(string filename, TextReader input, TextWriter output)
        {
            Debug.Print("Translating module {0} in namespace {1}", moduleName, nmspace);
            var lex = new Lexer(filename, input);
            var flt = new CommentFilter(lex);
            var par = new Parser(filename, flt);
            var stm = par.Parse();

            TranslateModuleStatements(stm, null, output);
        }
Example #22
0
        internal CommentRemover(SyntaxNode node, CommentFilter comments, TextSpan span)
            : base(visitIntoStructuredTrivia: true)
        {
            Node = node;
            Span = span;

            ShouldRemoveSingleLineComment = (comments & CommentFilter.SingleLine) != 0;
            ShouldRemoveMultiLineComment  = (comments & CommentFilter.MultiLine) != 0;
            ShouldRemoveSingleLineDocumentationComment = (comments & CommentFilter.SingleLineDocumentation) != 0;
            ShouldRemoveMultiLineDocumentationComment  = (comments & CommentFilter.MultiLineDocumentation) != 0;
        }
Example #23
0
        public void FilterInputNotNull()
        {
            var filter = new CommentFilter(
                new WordDetector(
                    new WordDetectorSettings("Match")));

            // Testing this in line so that I am confident that the piece I want
            // to test is the piece throwing the exception.
            Assert.ThrowsException <ArgumentNullException>(() =>
                                                           filter.Filter(null), "Passed in comment data should not be allowed to be null.");
        }
        public void Translate(string filename, TextReader input, TextWriter output)
        {
            Debug.Print("Translating module {0} in namespace {1}", moduleName, nmspace);
            var lex   = new Lexer(filename, input);
            var flt   = new CommentFilter(lex);
            var par   = new Parser(filename, flt, true, logger);
            var stm   = par.Parse();
            var types = new TypeReferenceTranslator(new Dictionary <Node, DataType>());

            TranslateModuleStatements(stm, types, output);
        }
Example #25
0
        public static TNode RemoveComments <TNode>(TNode node, TextSpan span, CommentFilter comments) where TNode : SyntaxNode
        {
            if (node == null)
            {
                throw new ArgumentNullException(nameof(node));
            }

            var remover = new CommentRemover(node, comments, span);

            return((TNode)remover.Visit(node));
        }
        BaseResponse <Comment> IComments.GetCommentsByIds(List <string> commentIds, CommentFilter filters)
        {
            var apiParams   = filters.GetQueryParams();
            var url         = $"{_baseApiUrl}/comments/";
            var idsToEncode = string.Join(";", commentIds.ToArray());

            url = url + $"{HttpUtility.UrlEncode(idsToEncode)}" + $"?key={_apiKey}&{apiParams}";
            var response  = _httpClient.GetAsync(url).Result.Content.ReadAsStringAsync().Result;
            var apiResult = response.DeserializeJson <Data <Comment> >().ValidateApiResponse();

            return(apiResult);
        }
Example #27
0
        public static IList<CommentBE> RetrieveCommentsForPage(PageBE page, CommentFilter filter, bool includePageDescendants, uint? postedByUserId, SortDirection sortDir, uint offset, uint limit, out uint totalComments) {
            IList<CommentBE> commentsForPage = DbUtils.CurrentSession.Comments_GetByPage(page, filter, includePageDescendants, postedByUserId, sortDir, offset, limit, out totalComments);

            if(includePageDescendants) {

                //Filter out comments from pages with no user permissions
                //NOTE: this will mess up limits/offsets without a way to apply permissions at the db layer.
                commentsForPage = ApplyPermissionFilter(commentsForPage);
            }

            return commentsForPage;
        }
Example #28
0
 public async Task <List <Comment> > GetCommentsByBookId(int bookId)
 {
     try
     {
         var entityList = _commentRepository.GetAll();
         var comments   = CommentFilter.FilterByBookId(entityList, bookId);
         return(comments.ToList());
     }
     catch
     {
         return(null);
     }
 }
Example #29
0
        public static IList <CommentBE> RetrieveCommentsForPage(PageBE page, CommentFilter filter, bool includePageDescendants, uint?postedByUserId, SortDirection sortDir, uint offset, uint limit, out uint totalComments)
        {
            IList <CommentBE> commentsForPage = DbUtils.CurrentSession.Comments_GetByPage(page, filter, includePageDescendants, postedByUserId, sortDir, offset, limit, out totalComments);

            if (includePageDescendants)
            {
                //Filter out comments from pages with no user permissions
                //NOTE: this will mess up limits/offsets without a way to apply permissions at the db layer.
                commentsForPage = ApplyPermissionFilter(commentsForPage);
            }

            return(commentsForPage);
        }
        public async Task <IActionResult> GetComment([FromQuery] CommentFilter filter, [FromQuery] Pagination pagination)
        {
            var comment = await _context.Comments.ToListAsync();

            if (filter.BookId != 0)
            {
                comment = comment.Where(c => c.BookId == filter.BookId).ToList();
            }

            var result = PaginatedList <Comment> .Create(comment, pagination.current, pagination.pageSize);

            return(Ok(new { success = true, data = comment, filter = filter }));
        }
Example #31
0
        /// <summary>
        /// Comments list
        /// </summary>
        /// <param name="filter">Filter</param>
        /// <returns>The filtered and sorted list of records</returns>
        public PagedList <Comment> List(CommentFilter filter)
        {
            var query = base.GetAll();

            if (!string.IsNullOrWhiteSpace(filter.Content))
            {
                query = query.Where(i => i.Content.Contains(filter.Content));
            }

            var result = query.ToPaged(filter);

            return(result);
        }
Example #32
0
        public Comment GetCommentByCommentId(CommentFilter commentFilter)
        {
            Comment comment = null;

            try
            {
                comment = repository.GetCommentByCommentId(commentFilter).To <Comment>().FirstOrDefault();
            }
            catch (Exception ex)
            {
                CoreLogger.Instance.Error(this.CreateMessageLog(ex.Message));
            }
            return(comment);
        }
Example #33
0
		/// <summary>
		/// Gets a set of comments for a given post. Note that this only works for WordPress version 2.6.1 or higher.
		/// </summary>
		/// <param name="post_id"></param>
		/// <param name="status"></param>
		/// <param name="number"></param>
		/// <param name="offset"></param>
		/// <returns></returns>
		public IList<Comment> GetComments(string post_id, string status, int number, int offset)
		{
			//var statusList = GetCommentStatusList(post_id);
			//todo: add some validation to make sure supplied status is available.

			var filter = new CommentFilter
			{
				post_id = post_id,
				number = number,
				offset = offset,
				status = status
			};

			return wrapper.GetComments(this.BlogID, this.Username, this.Password, filter);
		}
Example #34
0
 public IList<CommentBE> Comments_GetByPage(PageBE page, CommentFilter searchStatus, bool includePageDescendants, uint? postedByUserId, SortDirection datePostedSortDir, uint? offset, uint? limit, out uint totalComments) {
     Stopwatch sw = Stopwatch.StartNew();
     var ret = _next.Comments_GetByPage(page, searchStatus, includePageDescendants, postedByUserId, datePostedSortDir, offset, limit, out totalComments);
     LogQuery(CATEGORY_COMMENTS, "Comments_GetByPage", sw, "page", page, "searchStatus", searchStatus, "includePageDescendants", includePageDescendants, "postedByUserId", postedByUserId, "datePostedSortDir", datePostedSortDir, "offset", offset, "limit", limit);
     return ret;
 }
Example #35
0
 //--- Methods ---
 public IList<CommentBE> RetrieveCommentsForPage(PageBE page, CommentFilter filter, bool includePageDescendants, uint? postedByUserId, SortDirection sortDir, uint offset, uint limit, out uint totalComments) {
     return CommentBL.RetrieveCommentsForPage(page, filter, includePageDescendants, postedByUserId, sortDir, offset, limit, out totalComments);
 }
Example #36
0
        /// <summary>
        /// Creates a feedback item in the database.
        /// </summary>
        /// <param name="feedback">The feedback.</param>
        /// <param name="filter">Spam filter.</param>
        /// <returns></returns>
        public static int Create(FeedbackItem feedback, CommentFilter filter)
        {
            if (HttpContext.Current != null && HttpContext.Current.Request != null)
            {
                feedback.UserAgent = HttpContext.Current.Request.UserAgent;
                feedback.IpAddress = HttpHelper.GetUserIpAddress(HttpContext.Current);
            }

            feedback.FlaggedAsSpam = true; //We're going to start with this assumption.
            feedback.Author = HtmlHelper.SafeFormat(feedback.Author);
            feedback.Body = HtmlHelper.ConvertUrlsToHyperLinks(HtmlHelper.ConvertToAllowedHtml(feedback.Body));
            feedback.Title = HtmlHelper.SafeFormat(feedback.Title);

            // If we are creating this feedback item as part of an import, we want to
            // be sure to use the item's datetime, and not set it to the current time.
            if (NullValue.NullDateTime.Equals(feedback.DateCreated))
            {
                feedback.DateCreated = Config.CurrentBlog.TimeZone.Now;
                feedback.DateModified = feedback.DateCreated;
            }
            else if (NullValue.NullDateTime.Equals(feedback.DateModified))
            {
                feedback.DateModified = feedback.DateCreated;
            }

            if(filter != null)
                filter.FilterBeforePersist(feedback);

            feedback.Id = ObjectProvider.Instance().Create(feedback);

            if(filter != null)
                filter.FilterAfterPersist(feedback);

            // if it's not the administrator commenting and it's not a trackback.
            if (!SecurityHelper.IsAdmin && !String.IsNullOrEmpty(Config.CurrentBlog.Email) && feedback.FeedbackType != Extensibility.FeedbackType.PingTrack)
            {
                //In order to make this async, we need to pass the HttpContext.Current
                //several layers deep. Instead, we should create our own context.
                EmailCommentToAdmin(feedback, Config.CurrentBlog);
            }

            return feedback.Id;
        }
Example #37
0
        public void can_map_from_commentFilter_to_xmlRpcCommentFilter()
        {
            var original = new CommentFilter
            {
                Number = 12,
                Offset = 4,
                PostID = 1234,
                Status = "aaa"
            };

            var result = Map.From.CommentFilter(original);

            Assert.AreEqual(original.Number, result.number);
            Assert.AreEqual(original.Offset, result.offset);
            Assert.AreEqual(original.PostID, result.post_id);
            Assert.AreEqual(original.Status, result.status);
        }
Example #38
0
        public IList<CommentBE> Comments_GetByPage(PageBE page, CommentFilter searchStatus, bool includePageDescendants, uint? postedByUserId, SortDirection datePostedSortDir, uint? offset, uint? limit, out uint totalComments) {
            List<CommentBE> comments = new List<CommentBE>();
            uint totalCommentsTemp = 0;

            string joins = string.Empty;
            if(includePageDescendants) {
                joins = "JOIN pages \n\tON comments.cmnt_page_id = pages.page_id";
            }

            string whereClauses = "\n 1=1";
            switch(searchStatus) {
                case CommentFilter.DELETED:
                    whereClauses += "\n AND cmnt_delete_date is not null";
                    break;
                case CommentFilter.NONDELETED:
                    whereClauses += "\n AND cmnt_delete_date is null";
                    break;
            }

            if(includePageDescendants) {
                whereClauses += @"
AND( 
(   ((  ?TITLE = '' AND pages.page_title != '') OR (LEFT(pages.page_title, CHAR_LENGTH(?TITLE) + 1) = CONCAT(?TITLE, '/') AND SUBSTRING(pages.page_title, CHAR_LENGTH(?TITLE) + 2, 1) != '/'))
        AND	pages.page_namespace = ?NS
	    AND	pages.page_is_redirect = 0 
    )
OR 	pages.page_id = ?PAGEID)";

            } else {
                whereClauses += "\n AND cmnt_page_id = ?PAGEID";
            }

            if(postedByUserId != null) {
                whereClauses += "\n AND cmnt_poster_user_id = ?POSTERID";
            }

            string orderby = string.Empty;
            if(datePostedSortDir != SortDirection.UNDEFINED) {
                orderby = string.Format("ORDER BY cmnt_create_date {0}, cmnt_id {0}", datePostedSortDir.ToString());
            }

            List<uint> userids = new List<uint>();
            string query = string.Format(@" /* Comments_GetByPage */
SELECT SQL_CALC_FOUND_ROWS comments.*
FROM comments
{0}
WHERE
{1}
{2}
LIMIT ?COUNT OFFSET ?OFFSET;

select found_rows() as totalcomments;"
                , joins, whereClauses, orderby);

            Catalog.NewQuery(query)
            .With("PAGEID", page.ID)
            .With("TITLE", page.Title.AsUnprefixedDbPath())
            .With("NS", (int)page.Title.Namespace)
            .With("POSTERID", postedByUserId)
            .With("COUNT", limit ?? UInt32.MaxValue)
            .With("OFFSET", offset ?? 0)
            .Execute(delegate(IDataReader dr) {
                while(dr.Read()) {
                    CommentBE c = Comments_Populate(dr);
                    if(c.DeleterUserId != null) {
                        userids.Add(c.DeleterUserId ?? 0);
                    }
                    if(c.LastEditUserId != null) {
                        userids.Add(c.LastEditUserId ?? 0);
                    }
                    userids.Add(c.PosterUserId);
                    comments.Add(c);
                }

                if(dr.NextResult() && dr.Read()) {
                    totalCommentsTemp = DbUtils.Convert.To<uint>(dr["totalcomments"]) ?? 0;
                }
            });

            totalComments = totalCommentsTemp;
            return comments;
        }