db = new PDO; $this->config = Config::get(); $this->table = new Table; $this->opt = new \stdClass(); $this->opt->sort = "DESC"; $this->opt->logic = "AND"; $this->CategoryTable = $this->table->arc_category; $this->fld_left = "lft"; $this->fld_right = "rgt"; $this->fld_tid = "tid"; $this->DeepTitle = "ROOTDEEP"; $this->DataNewsCode = "datanews"; $Listener = new Listener(); $this->getEventManager()->attachAggregate($Listener); } public function setEventManager(EventManagerInterface $events) { $events->setIdentifiers(array( __CLASS__, get_called_class(), )); $this->events = $events; return $this; } public function getEventManager() { if (NULL === $this->events) { $this->setEventManager(new EventManager()); } return $this->events; } public function GetFullCategory() { return $this->GetCategory(0,''); } public function GetCategory($tid=0,$ptype='news'){ $left = $this->fld_left; $right = $this->fld_right; $categoryTable = $this->CategoryTable; $tidField = $this->fld_tid; $whereSql = array(); if(!empty($tid)) { $sql = "SELECT $left,$right FROM $categoryTable WHERE id=$tid"; $sth = $this->db->query($sql); $row = $sth->fetch(); $whereSql[] = " $left BETWEEN {$row[$left]} AND {$row[$right]} "; } if(count($whereSql)>0) { $whereSql = " WHERE ".join(" AND ",$whereSql); }elseif ($ptype<>''){ $whereSql = " where ptype='$ptype' "; } else $whereSql=''; $sql = "SELECT * FROM $categoryTable $whereSql ORDER BY ptype ASC,$left ASC "; $sth = $this->db->query($sql); $rows = $sth->fetchAll(); $stack = array(); $categorys = array(); foreach($rows as $k=>$v) { /* 如果它是一个顶级栏目,则为它重置深度 */ if(empty($v[$tidField])) { $stack = array(); }else{ if(count($stack) > 1) { /* 在这个循环中必须追溯直至与其平级的分类 while循环无法重写条件中已经改变的变量 第一次max(array_keys($stack))赋值为当前深度 循环中的第一个if里max(array_keys($stack))是重新统计,而非使用一定义的 因为第二次循环到此时可能max(array_keys($stack))已经发生改变 第三处max(array_keys($stack))表示第一个if中没有break掉的深度值,所以也不能使用赋过值的变量代替。 加入brake 可使程序追溯至平级栏目即进行下一步操作 必须是倒序循环,多个平级栏目时,如果是正序列循环会到第一个平级的栏目后停止循环 */ for($i=max(array_keys($stack));$i>=0;$i--) if($v[$right]>$stack[max(array_keys($stack))]) { if(count($stack)<1) { break; } if($v[$right]>$stack[max(array_keys($stack))]) { array_pop($stack); }else{ break; } }//end if }//end if } //放入输出数组 $rows[$k][$this->DeepTitle] = count($stack); //将此节点加入栈中 $stack[] = $v[$right]; }// end foreach return $rows; } public function fetchAll() { $wheresql = array(); if(isset($this->opt->where) && !empty($this->opt->where)) $wheresql = array_merge($wheresql,$this->opt->where); if(count($wheresql)>0) { $wheresql = " WHERE ".join($wheresql," ".$this->opt->logic." "); }else{ $wheresql = ''; } if(!empty($this->opt->order)) { $order = $this->opt->order; }else{ $order = "id"; } $sql = "select * from {$this->table->arc_article} $wheresql ORDER BY $order {$this->opt->sort} "; if(!empty($this->opt->start)) { $sql .= " START {$this->opt->start} "; } if(!empty($this->opt->limit)){ $sql .= " LIMIT {$this->opt->limit} "; } $rs = $this->db->query($sql); return $rs->fetchAll(); } public function fetch($id) { if(is_numeric($id)) { $sql = "SELECT * FROM {$this->table->arc_category} WHERE id=$id"; }else{ if(preg_match("/^[A-Za-z]+$/",$id)) { $sql = "SELECT * FROM {$this->table->arc_category} WHERE code='$id'"; }else{ return false; } } $rs = $this->db->query($sql); return $rs->fetch(); } public $ptype = array( "新闻" => "news", "想法" => "idea", "帮助" => "help", "关于" => "about" ); public function getParam() { $request = new Request; $data = array( 'title' => $request->getPost('title'), 'ptype' => $request->getPost('ptype'), 'tid' => (int)$request->getPost('fid'), 'code' => $request->getPost('code'), ); return $data; } //添加 public function add($data,$id = 0) { $params = compact('data'); $results = $this->getEventManager()->trigger('submit.checkParam', $this, $params); $cache_data = $results->last(); if($cache_data !== true) { return $cache_data; } $results = $this->getEventManager()->trigger('submit.processData', $this, $params); $data = $results->last(); $dbh = new dbh(); if(empty($id)) { $id = $dbh->insert($this->table->arc_category,$data,true); if(!empty($id) && is_numeric($id)) { $this->getEventManager()->trigger('submit.recordPosted', $this, compact('params','data','id')); return true; }else{ if($id === false) { return '服务器开小差了,请稍后再试'; }else{ return '服务器处理中遇到错误,请联系管理员'; } } }//add else{ if(!$dbh->update($this->table->arc_category,$data," id=$id ",true)) { return "修改失败!请重试"; }else{ $this->getEventManager()->trigger('submit.recordChanged', $this, compact('params','data','id')); return true; } }//edit }// add() /** * Insert() 插入一个栏目 * 返回数组 left=>左值 right=>右值 * * * @param int $tid * * @return array */ function Insert($tid){ $left = $this->fld_left; $right = $this->fld_right; $categoryTable = $this->CategoryTable; //分别处理有上级栏目和没上级栏目的 if(!empty($tid)) { $sql = "SELECT $right FROM $categoryTable WHERE id=$tid"; $sth = $this->db->query($sql); $row = $sth->fetch(); $right_start = $row[$right]-1; //更新所有右值 $sql = "UPDATE $categoryTable SET $right=$right+2 WHERE $right>$right_start"; $this->db->exec($sql); //更新所有左值 $sql = "UPDATE $categoryTable SET $left=$left+2 WHERE $left>$right_start"; $this->db->exec($sql); //返回应该插入的左右值 $lft = $right_start + 1; $rgt = $lft + 1; return array( 'left'=>$lft, 'right'=>$rgt ); }else{ //取最大的右值 $sql = "SELECT $right FROM $categoryTable WHERE tid=0 ORDER BY $left DESC LIMIT 1"; $sth = $this->db->query($sql); $row = $sth->fetch(); $right_start = $row[$right]-1; if($right_start<1) { return array( 'left'=>1, 'right'=>2 ); } $lft = $right_start + 2; $rgt = $lft + 1; return array( 'left'=>$lft, 'right'=>$rgt ); } }//Insert //移动栏目 public function move($action,$id){ if($action == 'up') { return $this->moveup($id); } if($action == "down") { return $this->movedown($id); } } //栏目上移 public function moveup($id){ $info = $this->fetch($id); $tid = $info[$this->fld_tid]; $left = $info[$this->fld_left]; $right = $info[$this->fld_right]; $prev = $this->prevnode($tid,$left,$right); if($prev === NULL ) { return "此栏目已位于平级栏目的顶端"; } if(is_array($prev)) { $this_fd = $right-$left; $this_ft = $left - $prev[$this->fld_left]; $prve_fd = $prev[$this->fld_right] - $prev[$this->fld_left]; $new_right = $prev[$this->fld_left] + $this_fd; $new_left = $right - $prve_fd; $prev_ft = $new_left - $prev[$this->fld_left]; $exec = array( 'success' => array(), 'error' => array() ); $sql_1 = "UPDATE ".$this->CategoryTable." SET ".$this->fld_left."=".$prev[$this->fld_left].",".$this->fld_right."=".$new_right. " WHERE id=$id"; $sql_2 = "UPDATE ".$this->CategoryTable." SET ".$this->fld_left."=".$new_left.",".$this->fld_right."=".$right. " WHERE id=".$prev['id']; if($this->db->exec($sql_1)) { $exec['success'][] = $info['title']."[$id] :移动成功!"; }else{ $exec['error'][] = $info['title']."[$id] :移动失败! 请手动在数据库中修改,目标左右值 ".$prev[$this->fld_left].":".$new_right; } if($this->db->exec($sql_2)) { $exec['success'][] = $prev['title']."[".$prev['id']."] :移动成功!"; }else{ $exec['error'][] = $prev['title']."[".$prev['id']."] :移动失败! 请手动在数据库中修改,目标左右值 ".$new_left.":".$right; } $thisnode = $this->getSubNode($left,$right); $prevnode = $this->getSubNode($prev[$this->fld_left],$prev[$this->fld_right]); /* $a = array(); echo $prev[$this->fld_left].':'.$prev[$this->fld_right]." - ".$left.":".$right; echo "
"; echo $prev[$this->fld_left].':'.$new_right." - ".$new_left.":".$right; echo "
"; */ if(!empty($thisnode)) { foreach($thisnode as $k=>$v) { $node_new_left = ($v[$this->fld_left]-$this_ft); $fd = $v[$this->fld_right] - $v[$this->fld_left]; $node_new_right = $node_new_left + $fd; /* echo ($v['lft']) .":". ($v['rgt'])."
"; echo $node_new_left .":". $node_new_right."
"; echo "
"; */ $sql = "UPDATE ".$this->CategoryTable." SET ".$this->fld_left."=".$node_new_left.",".$this->fld_right."=".$node_new_right. " WHERE id=".$v['id']; if($this->db->exec($sql)) { $exec['success'][] = $info['title']."的子栏目".$v['title']."[".$v['id']."] :移动成功!"; }else{ $exec['error'][] = $info['title']."的子栏目".$v['title']."[".$v['id']."] :移动失败! 请手动在数据库中修改,目标左右值 ".$node_new_left.":".$node_new_right; } } } if(!empty($prevnode)) { foreach($prevnode as $k=>$v) { $node_new_left = ($v[$this->fld_left]+$prev_ft); $fd = $v[$this->fld_right] - $v[$this->fld_left]; $node_new_right = $node_new_left + $fd; /* echo ($v['lft']) .":". ($v['rgt'])."
"; echo $node_new_left .":". $node_new_right."
"; echo "
"; */ $sql = "UPDATE ".$this->CategoryTable." SET ".$this->fld_left."=".$node_new_left.",".$this->fld_right."=".$node_new_right. " WHERE id=".$v['id']; if($this->db->exec($sql)) { $exec['success'][] = $prev['title']."的子栏目".$v['title']."[".$v['id']."] :移动成功!"; }else{ $exec['error'][] = $prev['title']."的子栏目".$v['title']."[".$v['id']."] :移动失败! 请手动在数据库中修改,目标左右值 ".$node_new_left.":".$node_new_right; } } } return $exec; } if(is_string($prev)) { return $prev; } }//栏目上移 //栏目下移 public function movedown($id){ $info = $this->fetch($id); $tid = $info[$this->fld_tid]; $left = $info[$this->fld_left]; $right = $info[$this->fld_right]; $next = $this->nextnode($tid,$left,$right); if($next === NULL ) { return "此栏目已位于平级栏目的末端"; } if(is_array($next)) { $this_fd = $right-$left; $next_fd = $next[$this->fld_right] - $next[$this->fld_left]; $new_right = $left + $next_fd; $new_left = $next[$this->fld_right] - $this_fd; $this_ft = $new_left - $left; $next_ft = $next[$this->fld_left] - $left; //echo $id."[".$left .":".$right ."]-".$next['id']."[".$next[$this->fld_left].":".$next[$this->fld_right] . "]
"; //echo $next['id']."[".$left .":".$new_right ."]-".$id."[".$new_left.":".$next[$this->fld_right]."]

"; $exec = array( 'success' => array(), 'error' => array() ); $sql_1 = "UPDATE ".$this->CategoryTable." SET ".$this->fld_left."=".$new_left.",".$this->fld_right."=".$next[$this->fld_right]. " WHERE id=$id"; $sql_2 = "UPDATE ".$this->CategoryTable." SET ".$this->fld_left."=".$left.",".$this->fld_right."=".$new_right. " WHERE id=".$next['id']; if($this->db->exec($sql_1)) { $exec['success'][] = $info['title']."[$id] :移动成功!"; }else{ $exec['error'][] = $info['title']."[$id] :移动失败! 请手动在数据库中修改,目标左右值 ".$new_left.":".$next[$this->fld_right]; } if($this->db->exec($sql_2)) { $exec['success'][] = $next['title']."[".$next['id']."] :移动成功!"; }else{ $exec['error'][] = $next['title']."[".$next['id']."] :移动失败! 请手动在数据库中修改,目标左右值 ".$left.":".$this->fld_right; } $thisnode = $this->getSubNode($left,$right); $nextnode = $this->getSubNode($next[$this->fld_left],$next[$this->fld_right]); if(!empty($thisnode)) { foreach($thisnode as $k=>$v) { $node_new_left = ($v[$this->fld_left]+$this_ft); $fd = $v[$this->fld_right] - $v[$this->fld_left]; $node_new_right = $node_new_left + $fd; /*echo ($v['lft']) .":". ($v['rgt'])."
"; echo $node_new_left .":". $node_new_right."
"; echo "
";*/ $sql = "UPDATE ".$this->CategoryTable." SET ".$this->fld_left."=".$node_new_left.",".$this->fld_right."=".$node_new_right. " WHERE id=".$v['id']; if($this->db->exec($sql)) { $exec['success'][] = $info['title']."的子栏目".$v['title']."[".$v['id']."] :移动成功!"; }else{ $exec['error'][] = $info['title']."的子栏目".$v['title']."[".$v['id']."] :移动失败! 请手动在数据库中修改,目标左右值 ".$node_new_left.":".$node_new_right; } } } if(!empty($nextnode)) { foreach($nextnode as $k=>$v) { $node_new_left = ($v[$this->fld_left] - $next_ft); $fd = $v[$this->fld_right] - $v[$this->fld_left]; $node_new_right = $node_new_left + $fd; /*echo ($v['lft']) .":". ($v['rgt'])."
"; echo $node_new_left .":". $node_new_right."
"; echo "
";*/ $sql = "UPDATE ".$this->CategoryTable." SET ".$this->fld_left."=".$node_new_left.",".$this->fld_right."=".$node_new_right. " WHERE id=".$v['id']; if($this->db->exec($sql)) { $exec['success'][] = $info['title']."的子栏目".$v['title']."[".$v['id']."] :移动成功!"; }else{ $exec['error'][] = $info['title']."的子栏目".$v['title']."[".$v['id']."] :移动失败! 请手动在数据库中修改,目标左右值 ".$node_new_left.":".$node_new_right; } } } return $exec; } if(is_string($next)) { return $next; } }//栏目下移 //获得子栏目 public function getSubNode($left,$right,$data = NULL) { if(empty($data)) { $sql = "SELECT * FROM ".$this->CategoryTable." WHERE ".$this->fld_left.">$left AND ".$this->fld_right."<$right ORDER BY ".$this->fld_left." ASC"; $rs = $this->db->query($sql); $SN = $rs->fetchAll(); }else{ $SN = array(); foreach($data as $k=>$v) { if($left < $v[$this->fld_left] && $v[$this->fld_right] < $right) $SN[] = $data[$k]; } } return $SN; } //获取子栏目中的最大右值 public function getMaxSubRight($left,$right){ $sql = "SELECT max(".$this->fld_right.") as mx FROM ".$this->CategoryTable." WHERE ".$this->fld_left.">".$left." AND ".$this->fld_right."<".$right; $rs = $this->db->query($sql); $row = $rs->fetch(); return $row['mx']; } //获取平级栏目中的上一个栏目 public function prevnode($tid,$left,$right) { $sql = "SELECT * FROM ".$this->CategoryTable." WHERE ".$this->fld_tid."=$tid AND ".$this->fld_left."<$left AND ".$this->fld_right."<$right ORDER BY ".$this->fld_left." DESC LIMIT 1 "; $rs = $this->db->query($sql); $row = $rs->fetch(); if(empty($row)) { return NULL; } return $row; } //获取平级栏目中的下一个栏目 public function nextnode($tid,$left,$right) { $sql = "SELECT * FROM ".$this->CategoryTable." WHERE ".$this->fld_tid."=$tid AND ".$this->fld_left.">$left AND ".$this->fld_right.">$right ORDER BY ".$this->fld_left." ASC LIMIT 1 "; $rs = $this->db->query($sql); $row = $rs->fetch(); if(empty($row)) { return NULL; } return $row; } //删除某个栏目 public function del($id) { if(empty($id) || !is_numeric($id)) { return "参数错误"; } $cate = $this->fetch($id); if($cate[$this->fld_right] - $cate[$this->fld_left] > 1) { return "此栏目包含子栏目,不能直接删除,需要先删除子栏目"; } $sql = "DELETE FROM ".$this->CategoryTable." WHERE id=$id"; if($this->db->exec($sql)) { $sql = "UPDATE ".$this->CategoryTable. " SET ".$this->fld_right."=".$this->fld_right."-2". " WHERE ".$this->fld_right.">".$cate[$this->fld_right]; $sql2 = "UPDATE ".$this->CategoryTable. " SET ".$this->fld_left."=".$this->fld_left."-2". " WHERE ".$this->fld_left.">".$cate[$this->fld_left]; if($this->db->exec($sql) || $this->db->exec($sql2)) return true; else return false; } } }