package fetdata import ( "math" "sort" "strings" "golang-fave/engine/utils" "golang-fave/engine/wrapper" ) type BlogPagination struct { Num string Link string Current bool Dots bool } type Blog struct { wrap *wrapper.Wrapper category *BlogCategory post *BlogPost posts []*BlogPost postsCount int postsPerPage int postsMaxPage int postsCurrPage int pagination []*BlogPagination paginationPrev *BlogPagination paginationNext *BlogPagination bufferCats map[int]*utils.MySql_blog_category } func (this *Blog) load() *Blog { if this == nil { return this } if (*this.wrap.Config).Modules.Enabled.Blog == 0 { return this } sql_nums := ` SELECT COUNT(*) FROM fave_blog_posts WHERE active = 1 ; ` sql_rows := ` SELECT fave_blog_posts.id, fave_blog_posts.user, fave_blog_posts.name, fave_blog_posts.alias, fave_blog_posts.category, fave_blog_posts.briefly, fave_blog_posts.content, UNIX_TIMESTAMP(fave_blog_posts.datetime) as datetime, fave_blog_posts.active, fave_users.id, fave_users.first_name, fave_users.last_name, fave_users.email, fave_users.admin, fave_users.active, cats.id, cats.user, cats.name, cats.alias, cats.lft, cats.rgt, cats.depth, cats.parent_id FROM fave_blog_posts LEFT JOIN fave_users ON fave_users.id = fave_blog_posts.user LEFT JOIN ( SELECT main.id, main.user, main.name, main.alias, main.lft, main.rgt, main.depth, parent.id AS parent_id FROM ( SELECT node.id, node.user, node.name, node.alias, node.lft, node.rgt, (COUNT(parent.id) - 1) AS depth FROM fave_blog_cats AS node, fave_blog_cats AS parent WHERE node.lft BETWEEN parent.lft AND parent.rgt GROUP BY node.id ORDER BY node.lft ASC ) AS main LEFT JOIN ( SELECT node.id, node.user, node.name, node.alias, node.lft, node.rgt, (COUNT(parent.id) - 0) AS depth FROM fave_blog_cats AS node, fave_blog_cats AS parent WHERE node.lft BETWEEN parent.lft AND parent.rgt GROUP BY node.id ORDER BY node.lft ASC ) AS parent ON parent.depth = main.depth AND main.lft > parent.lft AND main.rgt < parent.rgt WHERE main.id > 1 ORDER BY main.lft ASC ) AS cats ON cats.id = fave_blog_posts.category WHERE fave_blog_posts.active = 1 ORDER BY fave_blog_posts.id DESC LIMIT ?, ?; ` // Category selected if this.category != nil { var cat_ids []string if rows, err := this.wrap.DB.Query( this.wrap.R.Context(), `SELECT node.id FROM fave_blog_cats AS node, fave_blog_cats AS parent WHERE node.lft BETWEEN parent.lft AND parent.rgt AND node.id > 1 AND parent.id = ? GROUP BY node.id ORDER BY node.lft ASC ;`, this.category.Id(), ); err == nil { defer rows.Close() for rows.Next() { var cat_id string if err := rows.Scan(&cat_id); *this.wrap.LogCpError(&err) == nil { cat_ids = append(cat_ids, cat_id) } } } sql_nums = ` SELECT COUNT(*) FROM ( SELECT COUNT(*) FROM fave_blog_posts LEFT JOIN fave_blog_cat_post_rel ON fave_blog_cat_post_rel.post_id = fave_blog_posts.id WHERE fave_blog_posts.active = 1 AND fave_blog_cat_post_rel.category_id IN (` + strings.Join(cat_ids, ", ") + `) GROUP BY fave_blog_posts.id ) AS tbl ; ` sql_rows = ` SELECT fave_blog_posts.id, fave_blog_posts.user, fave_blog_posts.name, fave_blog_posts.alias, fave_blog_posts.category, fave_blog_posts.briefly, fave_blog_posts.content, UNIX_TIMESTAMP(fave_blog_posts.datetime) AS datetime, fave_blog_posts.active, fave_users.id, fave_users.first_name, fave_users.last_name, fave_users.email, fave_users.admin, fave_users.active, cats.id, cats.user, cats.name, cats.alias, cats.lft, cats.rgt, cats.depth, cats.parent_id FROM fave_blog_posts LEFT JOIN fave_blog_cat_post_rel ON fave_blog_cat_post_rel.post_id = fave_blog_posts.id LEFT JOIN fave_users ON fave_users.id = fave_blog_posts.user LEFT JOIN ( SELECT main.id, main.user, main.name, main.alias, main.lft, main.rgt, main.depth, parent.id AS parent_id FROM ( SELECT node.id, node.user, node.name, node.alias, node.lft, node.rgt, (COUNT(parent.id) - 1) AS depth FROM fave_blog_cats AS node, fave_blog_cats AS parent WHERE node.lft BETWEEN parent.lft AND parent.rgt GROUP BY node.id ORDER BY node.lft ASC ) AS main LEFT JOIN ( SELECT node.id, node.user, node.name, node.alias, node.lft, node.rgt, (COUNT(parent.id) - 0) AS depth FROM fave_blog_cats AS node, fave_blog_cats AS parent WHERE node.lft BETWEEN parent.lft AND parent.rgt GROUP BY node.id ORDER BY node.lft ASC ) AS parent ON parent.depth = main.depth AND main.lft > parent.lft AND main.rgt < parent.rgt WHERE main.id > 1 ORDER BY main.lft ASC ) AS cats ON cats.id = fave_blog_posts.category WHERE fave_blog_posts.active = 1 AND fave_blog_cat_post_rel.category_id IN (` + strings.Join(cat_ids, ", ") + `) GROUP BY fave_blog_posts.id, cats.parent_id ORDER BY fave_blog_posts.id DESC LIMIT ?, ?; ` } if err := this.wrap.DB.QueryRow(this.wrap.R.Context(), sql_nums).Scan(&this.postsCount); *this.wrap.LogCpError(&err) == nil { if this.category == nil { this.postsPerPage = (*this.wrap.Config).Blog.Pagination.Index } else { this.postsPerPage = (*this.wrap.Config).Blog.Pagination.Category } this.postsMaxPage = int(math.Ceil(float64(this.postsCount) / float64(this.postsPerPage))) this.postsCurrPage = this.wrap.GetCurrentPage(this.postsMaxPage) offset := this.postsCurrPage*this.postsPerPage - this.postsPerPage if rows, err := this.wrap.DB.Query(this.wrap.R.Context(), sql_rows, offset, this.postsPerPage); err == nil { defer rows.Close() for rows.Next() { rp := utils.MySql_blog_post{} ru := utils.MySql_user{} ro := utils.MySql_blog_category{} if err := rows.Scan( &rp.A_id, &rp.A_user, &rp.A_name, &rp.A_alias, &rp.A_category, &rp.A_briefly, &rp.A_content, &rp.A_datetime, &rp.A_active, &ru.A_id, &ru.A_first_name, &ru.A_last_name, &ru.A_email, &ru.A_admin, &ru.A_active, &ro.A_id, &ro.A_user, &ro.A_name, &ro.A_alias, &ro.A_lft, &ro.A_rgt, &ro.A_depth, &ro.A_parent, ); *this.wrap.LogCpError(&err) == nil { this.posts = append(this.posts, &BlogPost{ wrap: this.wrap, object: &rp, user: &User{wrap: this.wrap, object: &ru}, category: &BlogCategory{wrap: this.wrap, object: &ro}, }) } } } } // Build pagination if true { for i := 1; i < this.postsCurrPage; i++ { if this.postsCurrPage >= 5 && i > 1 && i < this.postsCurrPage-1 { continue } if this.postsCurrPage >= 5 && i > 1 && i < this.postsCurrPage { this.pagination = append(this.pagination, &BlogPagination{ Dots: true, }) } link := this.wrap.R.URL.Path if i > 1 { link = link + "?p=" + utils.IntToStr(i) } this.pagination = append(this.pagination, &BlogPagination{ Num: utils.IntToStr(i), Link: link, Current: false, }) } // Current page link := this.wrap.R.URL.Path if this.postsCurrPage > 1 { link = link + "?p=" + utils.IntToStr(this.postsCurrPage) } this.pagination = append(this.pagination, &BlogPagination{ Num: utils.IntToStr(this.postsCurrPage), Link: link, Current: true, }) for i := this.postsCurrPage + 1; i <= this.postsMaxPage; i++ { if this.postsCurrPage < this.postsMaxPage-3 && i == this.postsCurrPage+3 { this.pagination = append(this.pagination, &BlogPagination{ Dots: true, }) } if this.postsCurrPage < this.postsMaxPage-3 && i > this.postsCurrPage+1 && i <= this.postsMaxPage-1 { continue } link := this.wrap.R.URL.Path if i > 1 { link = link + "?p=" + utils.IntToStr(i) } this.pagination = append(this.pagination, &BlogPagination{ Num: utils.IntToStr(i), Link: link, Current: false, }) } } else { for i := 1; i <= this.postsMaxPage; i++ { link := this.wrap.R.URL.Path if i > 1 { link = link + "?p=" + utils.IntToStr(i) } this.pagination = append(this.pagination, &BlogPagination{ Num: utils.IntToStr(i), Link: link, Current: i == this.postsCurrPage, }) } } // Pagination prev/next if this.postsMaxPage > 1 { link := this.wrap.R.URL.Path if this.postsCurrPage-1 > 1 { link = this.wrap.R.URL.Path + "?p=" + utils.IntToStr(this.postsCurrPage-1) } this.paginationPrev = &BlogPagination{ Num: utils.IntToStr(this.postsCurrPage - 1), Link: link, Current: this.postsCurrPage <= 1, } if this.postsCurrPage >= 1 && this.postsCurrPage < this.postsMaxPage { link = this.wrap.R.URL.Path + "?p=" + utils.IntToStr(this.postsCurrPage+1) } else { link = this.wrap.R.URL.Path + "?p=" + utils.IntToStr(this.postsMaxPage) } this.paginationNext = &BlogPagination{ Num: utils.IntToStr(this.postsCurrPage + 1), Link: link, Current: this.postsCurrPage >= this.postsMaxPage, } } return this } func (this *Blog) preload_cats() { if (*this.wrap.Config).Modules.Enabled.Blog == 0 { return } if this.bufferCats == nil { this.bufferCats = map[int]*utils.MySql_blog_category{} if rows, err := this.wrap.DB.Query( this.wrap.R.Context(), `SELECT main.id, main.user, main.name, main.alias, main.lft, main.rgt, main.depth, parent.id AS parent_id FROM ( SELECT node.id, node.user, node.name, node.alias, node.lft, node.rgt, (COUNT(parent.id) - 1) AS depth FROM fave_blog_cats AS node, fave_blog_cats AS parent WHERE node.lft BETWEEN parent.lft AND parent.rgt GROUP BY node.id ORDER BY node.lft ASC ) AS main LEFT JOIN ( SELECT node.id, node.user, node.name, node.alias, node.lft, node.rgt, (COUNT(parent.id) - 0) AS depth FROM fave_blog_cats AS node, fave_blog_cats AS parent WHERE node.lft BETWEEN parent.lft AND parent.rgt GROUP BY node.id ORDER BY node.lft ASC ) AS parent ON parent.depth = main.depth AND main.lft > parent.lft AND main.rgt < parent.rgt WHERE main.id > 1 ORDER BY main.lft ASC ; `); err == nil { defer rows.Close() for rows.Next() { row := utils.MySql_blog_category{} if err := rows.Scan( &row.A_id, &row.A_user, &row.A_name, &row.A_alias, &row.A_lft, &row.A_rgt, &row.A_depth, &row.A_parent, ); *this.wrap.LogCpError(&err) == nil { this.bufferCats[row.A_id] = &row if _, ok := this.bufferCats[row.A_parent]; ok { this.bufferCats[row.A_parent].A_childs = true } } } } } } func (this *Blog) Category() *BlogCategory { if this == nil { return nil } return this.category } func (this *Blog) Post() *BlogPost { if this == nil { return nil } return this.post } func (this *Blog) HavePosts() bool { if this == nil { return false } if len(this.posts) <= 0 { return false } return true } func (this *Blog) Posts() []*BlogPost { if this == nil { return []*BlogPost{} } return this.posts } func (this *Blog) PostsCount() int { if this == nil { return 0 } return this.postsCount } func (this *Blog) PostsPerPage() int { if this == nil { return 0 } return this.postsPerPage } func (this *Blog) PostsMaxPage() int { if this == nil { return 0 } return this.postsMaxPage } func (this *Blog) PostsCurrPage() int { if this == nil { return 0 } return this.postsCurrPage } func (this *Blog) Pagination() []*BlogPagination { if this == nil { return []*BlogPagination{} } return this.pagination } func (this *Blog) PaginationPrev() *BlogPagination { if this == nil { return nil } return this.paginationPrev } func (this *Blog) PaginationNext() *BlogPagination { if this == nil { return nil } return this.paginationNext } func (this *Blog) Categories(parent, depth int) []*BlogCategory { this.preload_cats() depth_tmp := 0 result := []*BlogCategory{} if (*this.wrap.Config).Modules.Enabled.Blog != 0 { for _, cat := range this.bufferCats { if parent <= 1 { if depth <= 0 { result = append(result, (&BlogCategory{wrap: this.wrap, object: cat}).load(&this.bufferCats)) } else { if cat.A_depth <= depth { result = append(result, (&BlogCategory{wrap: this.wrap, object: cat}).load(&this.bufferCats)) } } } else { if cat.A_parent == parent { if depth_tmp == 0 { depth_tmp = cat.A_depth } if depth <= 0 { result = append(result, (&BlogCategory{wrap: this.wrap, object: cat}).load(&this.bufferCats)) } else { if (cat.A_depth - depth_tmp + 1) <= depth { result = append(result, (&BlogCategory{wrap: this.wrap, object: cat}).load(&this.bufferCats)) } } } } } sort.Slice(result, func(i, j int) bool { return result[i].Left() < result[j].Left() }) } return result }