github.com/insionng/yougam@v0.0.0-20170714101924-2bc18d833463/models/node.go (about)

     1  package models
     2  
     3  import (
     4  	"errors"
     5  	"fmt"
     6  	"log"
     7  	"os"
     8  	"strconv"
     9  	"time"
    10  	"github.com/insionng/yougam/helper"
    11  )
    12  
    13  type Node struct {
    14  	Id              int64
    15  	Pid             int64 `xorm:"index"` //pid为0 代表节点本身是顶层节点, pid大于0 代表上级节点id , 编写逻辑的时候注意判断此pid不能等于自身id
    16  	Cid             int64 `xorm:"index"` //所属分类的id
    17  	Uid             int64 `xorm:"index"`
    18  	Sort            int64
    19  	Ctype           int64   `xorm:"index"`
    20  	Title           string  `xorm:"index"`
    21  	Content         string  `xorm:"text"`
    22  	Attachment      string  `xorm:"text"`
    23  	Created         int64   `xorm:"created index"`
    24  	Updated         int64   `xorm:"updated"`
    25  	Hotness         float64 `xorm:"index"`
    26  	Confidence      float64 `xorm:"index"` //信任度数值
    27  	Hotup           int64   `xorm:"index"`
    28  	Hotdown         int64   `xorm:"index"`
    29  	Hotscore        int64   `xorm:"index"` //Hotup  -	Hotdown
    30  	Hotvote         int64   `xorm:"index"` //Hotup  + 	Hotdown
    31  	Views           int64
    32  	Author          string `xorm:"index"` //节点的创建者
    33  	Parent          string `xorm:"index"` //父级节点名称
    34  	Category        string `xorm:"index"` //所属分类标题
    35  	Tid             int64  //最后一次发布的topic的Tid
    36  	Topic           int64  //最后一次发布的topic的标题
    37  	TopicTime       int64
    38  	TopicCount      int64
    39  	TopicLastUserId int64
    40  	FavoriteCount   int64  `xorm:"index"`
    41  	Template        string `xorm:"index"`
    42  }
    43  
    44  type NodeMark struct {
    45  	Id  int64
    46  	Uid int64 `xorm:"index"`
    47  	Nid int64 `xorm:"index"` //node id
    48  }
    49  
    50  type NodeBookmark struct {
    51  	Id     int64
    52  	Userid int64 `xorm:"index"`
    53  	Nodeid int64 `xorm:"index"`
    54  }
    55  
    56  func HasNode(title string) (int64, bool) {
    57  
    58  	nd := new(Node)
    59  	if has, err := Engine.Where("title = ?", title).Get(nd); err != nil {
    60  		return -1, false
    61  	} else {
    62  		if has {
    63  			return nd.Id, true
    64  		}
    65  		return -1, false
    66  	}
    67  }
    68  
    69  //返回所有存在的节点
    70  func AllExistingNodes(offset int, limit int, field string) (*[]*Node, error) {
    71  	nds := new([]*Node)
    72  	err := Engine.Where("cid>=?", -2).Limit(limit, offset).Desc(field).Find(nds)
    73  	return nds, err
    74  }
    75  
    76  func AvailableNodes(offset int, limit int, field string) (*[]*Node, error) {
    77  	nds := new([]*Node)
    78  	err := Engine.Where("cid>=?", -1).Limit(limit, offset).Desc(field).Find(nds)
    79  	return nds, err
    80  }
    81  
    82  func NodesOfNodes(offset int, limit int, field string) (*[]*Node, error) {
    83  	nds := new([]*Node)
    84  	err := Engine.Where("cid>?", 0).Limit(limit, offset).Desc(field).Find(nds)
    85  	return nds, err
    86  }
    87  
    88  func NodesOfNavor(offset int, limit int, field string) (*[]*Node, error) {
    89  	nds := new([]*Node)
    90  	err := Engine.Where("cid<=? and cid>=?", 0, -1).Limit(limit, offset).Desc(field).Find(nds)
    91  	return nds, err
    92  }
    93  
    94  func SetNodeMark(uid int64, nid int64) (int64, error) {
    95  	nm := new(NodeMark)
    96  	nm = &NodeMark{Uid: uid, Nid: nid}
    97  	rows, err := Engine.Insert(nm)
    98  	return rows, err
    99  }
   100  
   101  func IsNodeMark(uid int64, nid int64) bool {
   102  
   103  	nm := new(NodeMark)
   104  
   105  	if has, err := Engine.Where("uid=? and nid=?", uid, nid).Get(nm); err != nil {
   106  		return false
   107  	} else {
   108  		if has {
   109  			if nm.Uid == uid {
   110  				return true
   111  			} else {
   112  				return false
   113  			}
   114  
   115  		} else {
   116  			return false
   117  		}
   118  	}
   119  
   120  }
   121  
   122  func GetNodesViaPid(pid int64, offset int, limit int, ctype int64, field string) *[]*Node {
   123  	var objs = new([]*Node)
   124  	if pid <= 0 {
   125  		switch {
   126  		case field == "asc":
   127  			{
   128  				if ctype != 0 {
   129  					Engine.Where("pid <= ? and ctype = ?", 0, ctype).Limit(limit, offset).Asc("id").Find(objs)
   130  				} else {
   131  					Engine.Where("pid <= ?", 0).Limit(limit, offset).Asc("id").Find(objs)
   132  				}
   133  			}
   134  		default:
   135  			{
   136  				if ctype != 0 {
   137  					Engine.Where("pid <= ? and ctype = ?", 0, ctype).Limit(limit, offset).Desc(field).Find(objs)
   138  				} else {
   139  					Engine.Where("pid <= ?", 0).Limit(limit, offset).Desc(field).Find(objs)
   140  				}
   141  			}
   142  		}
   143  	} else {
   144  		switch {
   145  		case field == "asc":
   146  			{
   147  				if ctype != 0 {
   148  					Engine.Where("pid=? and ctype=?", pid, ctype).Limit(limit, offset).Asc("id").Find(objs)
   149  				} else {
   150  					Engine.Where("pid=?", pid).Limit(limit, offset).Asc("id").Find(objs)
   151  				}
   152  			}
   153  		default:
   154  			{
   155  				if ctype != 0 {
   156  					Engine.Where("pid=? and ctype=?", pid, ctype).Limit(limit, offset).Desc(field).Find(objs)
   157  				} else {
   158  					Engine.Where("pid=?", pid).Limit(limit, offset).Desc(field).Find(objs)
   159  				}
   160  			}
   161  		}
   162  	}
   163  	return objs
   164  }
   165  
   166  func GetNodesByCtypeWithNid(offset int, limit int, ctype int64, nid int64, field string) (*[]*Node, error) {
   167  	objs := new([]*Node)
   168  	err := Engine.Table("node").Where("ctype = ? and nid = ?", ctype, nid).Limit(limit, offset).Desc(field).Find(objs)
   169  	return objs, err
   170  }
   171  
   172  func GetNodesByCtype(offset int, limit int, ctype int64, field string) (*[]*Node, error) {
   173  	catz := new([]*Node)
   174  	err := Engine.Table("node").Where("ctype = ?", ctype).Limit(limit, offset).Desc(field).Find(catz)
   175  	return catz, err
   176  }
   177  
   178  /*
   179  func GetNodesByCid(cid int64, offset int, limit int, field string) (*[]*Node, error) {
   180  	nds := new([]*Node)
   181  	err := Engine.Where("cid=?", cid).Limit(limit, offset).Desc(field).Find(nds)
   182  	return nds, err
   183  }
   184  */
   185  func GetNodesByCid(cid int64, offset int, limit int, field string) (*[]*Node, error) {
   186  	nds := new([]*Node)
   187  	var err error
   188  	if cid != 0 {
   189  		/*
   190  			if cid == -2 { //cid为-2时节点对前端隐藏展示
   191  				err = Engine.Where("cid>?", cid).Limit(limit, offset).Desc(field).Find(nds)
   192  			} else {
   193  				err = Engine.Where("cid=?", cid).Limit(limit, offset).Desc(field).Find(nds)
   194  			}
   195  		*/
   196  		err = Engine.Where("cid=?", cid).Limit(limit, offset).Desc(field).Find(nds)
   197  
   198  	} else {
   199  		err = Engine.Limit(limit, offset).Desc(field).Find(nds)
   200  	}
   201  	return nds, err
   202  }
   203  
   204  func GetNodesByCtypeWithPid(offset int, limit int, ctype int64, pid int64, field string) (*[]*Node, error) {
   205  	catz := new([]*Node)
   206  	err := Engine.Table("node").Where("ctype = ? and pid = ?", ctype, pid).Limit(limit, offset).Desc(field).Find(catz)
   207  	return catz, err
   208  }
   209  
   210  func AddNode(title string, content string, attachment string, nid int64, cid int64, uid int64) (int64, error) {
   211  
   212  	nd := &Node{Pid: nid, Cid: cid, Uid: uid, Title: title, Content: content, Attachment: attachment, Created: time.Now().Unix()}
   213  	if _, err := Engine.Insert(nd); err == nil {
   214  		return nd.Id, err
   215  	} else {
   216  		return -1, err
   217  	}
   218  
   219  }
   220  
   221  func SetNode(nid int64, nd *Node) (int64, error) {
   222  	nd.Id = nid
   223  	return Engine.Insert(nd)
   224  }
   225  
   226  func GetNode(id int64) (*Node, error) {
   227  
   228  	nd := &Node{}
   229  	has, err := Engine.Id(id).Get(nd)
   230  	if has {
   231  		return nd, err
   232  	} else {
   233  
   234  		return nil, err
   235  	}
   236  
   237  }
   238  
   239  func GetNodeByTitle(title string) (*Node, error) {
   240  	nd := &Node{}
   241  	nd.Title = title
   242  	has, err := Engine.Get(nd)
   243  	if has {
   244  		return nd, err
   245  	} else {
   246  
   247  		return nil, err
   248  	}
   249  }
   250  
   251  func GetNodesByCtypeWithCid(offset int, limit int, ctype int64, cid int64, field string) (*[]*Node, error) {
   252  	catz := new([]*Node)
   253  	err := Engine.Table("node").Where("ctype = ? and cid = ?", ctype, cid).Limit(limit, offset).Desc(field).Find(catz)
   254  	return catz, err
   255  }
   256  
   257  func GetNodesByPid(pid int64, offset int, limit int, ctype int64, field string) *[]*Node {
   258  
   259  	nds := new([]*Node)
   260  
   261  	switch {
   262  	case field == "asc":
   263  		{
   264  			if ctype != 0 {
   265  				Engine.Where("(pid=? or id=?) and ctype=?", pid, pid, ctype).Limit(limit, offset).Asc("id").Find(nds)
   266  			} else {
   267  				Engine.Where("pid=? or id=?", pid, pid).Limit(limit, offset).Asc("id").Find(nds)
   268  			}
   269  		}
   270  	default:
   271  		{
   272  			if ctype != 0 {
   273  				Engine.Where("(pid=? or id=?) and ctype=?", pid, pid, ctype).Limit(limit, offset).Desc(field).Find(nds)
   274  			} else {
   275  				Engine.Where("pid=? or id=?", pid, pid).Limit(limit, offset).Desc(field).Find(nds)
   276  			}
   277  		}
   278  	}
   279  	return nds
   280  }
   281  
   282  func GetNodes(offset int, limit int, field string) (*[]*Node, error) {
   283  	nds := new([]*Node)
   284  	err := Engine.Limit(limit, offset).Desc(field).Find(nds)
   285  	return nds, err
   286  }
   287  
   288  func PutNode(nid int64, nd *Node) (int64, error) {
   289  	//覆盖式更新
   290  	sess := Engine.NewSession()
   291  	defer sess.Close()
   292  	// 启动事务
   293  	if err := sess.Begin(); err != nil {
   294  		return -1, err
   295  	}
   296  
   297  	//执行事务
   298  	nodeid := int64(0)
   299  	if row, err := sess.Update(nd, &Node{Id: nid}); err != nil || row <= 0 {
   300  		sess.Rollback()
   301  		return -1, err
   302  	} else {
   303  		if nd.Uid > 0 {
   304  			n, _ := sess.Where("uid=?", nd.Uid).Count(&Node{})
   305  			_u := map[string]interface{}{"node_time": time.Now().Unix(), "node_count": n, "node_last_tid": nd.Tid, "node_last_topic": nd.Topic}
   306  			if row, err := sess.Table(&User{}).Where("id=?", nd.Uid).Update(&_u); err != nil || row <= 0 {
   307  				sess.Rollback()
   308  				return -1, errors.New(fmt.Sprint("PutNode更新user表话题相关信息时,执行:", row, "行变更,出现错误:", err))
   309  			}
   310  		}
   311  
   312  		nodeid = nd.Id
   313  	}
   314  
   315  	// 提交事务
   316  	return nodeid, sess.Commit()
   317  }
   318  
   319  //map[string]interface{}{"ctype": ctype}
   320  func UpdateNode(nid int64, nodemap *map[string]interface{}) error {
   321  	nd := &Node{}
   322  	if row, err := Engine.Table(nd).Where("id=?", nid).Update(nodemap); err != nil || row == 0 {
   323  		log.Println("UpdateNode  row:::", row, "UpdateNode出现错误:", err)
   324  		return err
   325  	} else {
   326  		return nil
   327  	}
   328  
   329  }
   330  
   331  func DelNode(id int64, uid int64, role int64) error {
   332  	allow := false
   333  	if role < 0 {
   334  		allow = true
   335  	}
   336  
   337  	node := &Node{}
   338  
   339  	if has, err := Engine.Id(id).Get(node); has == true && err == nil {
   340  
   341  		if node.Uid == uid || allow {
   342  			//检查附件字段并尝试删除文件
   343  			if len(node.Attachment) > 0 {
   344  
   345  				if p := helper.URL2local(node.Attachment); helper.Exist(p) {
   346  					//验证是否管理员权限
   347  					if allow {
   348  						if err := os.Remove(p); err != nil {
   349  							//可以输出错误日志,但不要反回错误,以免陷入死循环无法删掉
   350  							fmt.Println("ROOT DEL NODE Attachment, NODE ID:", id, ",ERR:", err)
   351  						}
   352  					} else { //检查用户对本地文件的所有权
   353  						if helper.VerifyUserfile(p, strconv.FormatInt(uid, 10)) {
   354  							if err := os.Remove(p); err != nil {
   355  								fmt.Println("DEL NODE Attachment, NODE ID:", id, ",ERR:", err)
   356  							}
   357  						}
   358  					}
   359  
   360  				}
   361  			}
   362  
   363  			//检查内容字段并尝试删除文件
   364  			if len(node.Content) > 0 {
   365  				//若内容中存在图片则开始尝试删除图片
   366  				delfiles_local := []string{}
   367  
   368  				if m, n := helper.GetImages(node.Content); n > 0 {
   369  
   370  					for _, v := range m {
   371  						if helper.IsLocal(v) {
   372  							delfiles_local = append(delfiles_local, v)
   373  							//如果本地同时也存在banner缓存文件,则加入旧图集合中,等待后面一次性删除
   374  							if p := helper.URL2local(helper.SetSuffix(v, "_banner.jpg")); helper.Exist(p) {
   375  								delfiles_local = append(delfiles_local, p)
   376  							}
   377  							if p := helper.URL2local(helper.SetSuffix(v, "_large.jpg")); helper.Exist(p) {
   378  								delfiles_local = append(delfiles_local, p)
   379  							}
   380  							if p := helper.URL2local(helper.SetSuffix(v, "_medium.jpg")); helper.Exist(p) {
   381  								delfiles_local = append(delfiles_local, p)
   382  							}
   383  							if p := helper.URL2local(helper.SetSuffix(v, "_small.jpg")); helper.Exist(p) {
   384  								delfiles_local = append(delfiles_local, p)
   385  							}
   386  						}
   387  					}
   388  					for k, v := range delfiles_local {
   389  						if p := helper.URL2local(v); helper.Exist(p) { //如若文件存在,则处理,否则忽略
   390  							//先行判断是否缩略图  如果不是则执行删除image表记录的操作 因为缩略图是没有存到image表记录里面的
   391  							//isThumbnails := bool(true) //false代表不是缩略图 true代表是缩略图
   392  							/*
   393  								if (!strings.HasSuffix(v, "_large.jpg")) &&
   394  									(!strings.HasSuffix(v, "_medium.jpg")) &&
   395  									(!strings.HasSuffix(v, "_small.jpg")) {
   396  									isThumbnails = false
   397  
   398  								}
   399  							*/
   400  							//验证是否管理员权限
   401  							if allow {
   402  								if err := os.Remove(p); err != nil {
   403  									log.Println("#", k, ",ROOT DEL FILE ERROR:", err)
   404  								}
   405  
   406  							} else { //检查用户对文件的所有权
   407  								if helper.VerifyUserfile(p, strconv.FormatInt(uid, 10)) {
   408  									if err := os.Remove(p); err != nil {
   409  										log.Println("#", k, ",DEL FILE ERROR:", err)
   410  									}
   411  
   412  								}
   413  							}
   414  
   415  						}
   416  					}
   417  				}
   418  
   419  			}
   420  			//不管实际路径中是否存在文件均删除该数据库记录,以免数据库记录陷入死循环无法删掉
   421  			if node.Id == id {
   422  
   423  				if row, err := Engine.Id(id).Delete(new(Node)); err != nil || row == 0 {
   424  					return errors.New(fmt.Sprint("删除话题错误!", row, err)) //错误还要我自己构造?!
   425  				} else {
   426  					return nil
   427  				}
   428  
   429  			}
   430  		}
   431  		return errors.New("你无权删除此话题:" + strconv.FormatInt(id, 10))
   432  	}
   433  	return errors.New("无法删除不存在的NODE ID:" + strconv.FormatInt(id, 10))
   434  }
   435  
   436  func GetNodesCount(offset int, limit int) (int64, error) {
   437  	total, err := Engine.Limit(limit, offset).Count(&Node{})
   438  	return total, err
   439  }
   440  
   441  func PostNode(node *Node) (int64, error) {
   442  	return Engine.Insert(node)
   443  }