You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

574 lines
20 KiB

7 years ago
  1. <?php
  2. /**
  3. * Class Board_model
  4. * ----------------------------------------------------------
  5. * 게시판 관련 모델
  6. */
  7. class Board_model extends WB_Model
  8. {
  9. function __construct()
  10. {
  11. parent::__construct();
  12. $this->load->driver('cache', array('adapter' => 'apc', 'backup' => 'file', 'key_prefix' => PROJECT));
  13. }
  14. /**
  15. * 게시글 목록을 가져온다.
  16. * @param $board
  17. * @param array $param
  18. * @return mixed
  19. */
  20. function post_list($board, $param=array())
  21. {
  22. // 공지사항 목록 가져오기
  23. $param['select'] = "P.*, PC.bca_name, M.mem_photo";
  24. $param['where']['P.brd_key'] = $board['brd_key'];
  25. $param['where_in']['post_status'] = array('Y','B');
  26. $param['order_by'] = "post_num DESC, post_reply ASC, post_idx ASC";
  27. $param['from'] = "board_post AS P";
  28. $param['where']['post_notice'] = "Y";
  29. $param['join'][] = array("board_category AS PC","PC.bca_idx=P.bca_idx","left");
  30. $param['join'][] = array("member AS M", "M.mem_userid=P.mem_userid","left");
  31. $param['limit'] = FALSE;
  32. $notice_list = array();
  33. $notice_list = $this->get_list($param);
  34. // 일반 글 목록 가져오기
  35. $param['where']['post_notice'] = "N";
  36. $param['page_rows'] = $board['brd_page_rows'];
  37. $param['page'] = element('page', $param, 1);
  38. $param['limit'] = ($board['brd_page_limit'] == 'Y');
  39. if( element('category', $param) ) {
  40. $category_filter = array( $param['category'] );
  41. // 해당 카테고리의 하위 아이템도 같이 불러오기 위함
  42. $sub_cate_list = $this->db->where('bca_parent', $param['category'])->where('brd_key', $board['brd_key'])->get('board_category')->result_array();
  43. foreach($sub_cate_list as $c) $category_filter[] = $c['bca_idx'];
  44. $param['where_in']['P.bca_idx'] = $category_filter;
  45. }
  46. if( element('scol', $param) && element('stxt', $param) )
  47. {
  48. if( $param['scol'] == 'title' ) {
  49. $param['sc'] = "post_title";
  50. $param['st'] = $param['stxt'];
  51. }
  52. else if ( $param['scol'] == 'nickname' )
  53. {
  54. $param['where']['M.mem_nickname'] = $param['stxt'];
  55. }
  56. }
  57. // 게시판에 관리자 승인기능이 있는경우 승인된 게시물만 가져온다.
  58. if ( $board['brd_use_assign'] == 'Y' && ! PAGE_ADMIN )
  59. {
  60. $param['where']['post_assign'] = 'Y';
  61. }
  62. $list = $this->get_list($param);
  63. $list['list'] = array_merge($notice_list['list'], $list['list']);
  64. $param = $this->get_param();
  65. foreach($list['list'] as &$row)
  66. {
  67. $row = $this->post_process($board, $row, $param, $board['brd_use_list_file'] == 'Y', $board['brd_use_list_thumbnail'] == 'Y');
  68. }
  69. return $list;
  70. }
  71. /**
  72. * 내용중 외부서버의 이미지를 내부서버로 복제한다.
  73. * @param $content
  74. */
  75. function copy_external_image($content, $user_agent)
  76. {
  77. // 외부서버의 이미지를 내부 서버로 복제한다.
  78. preg_match_all('/<img(.*)src="([^ "]*)"([^>]*)>/',$content, $matches_img);
  79. if(isset($matches_img[2]) && count($matches_img[2]) > 0)
  80. {
  81. foreach($matches_img[2] as $img) {
  82. $img = preg_replace('/\?.*/', '', $img);
  83. $img_server = parse_url($img);
  84. $cdn_server = parse_url(base_url());
  85. // 만약 같은서버에 올려진 파일이라면 지나간다.
  86. if (isset($img_server['host']) && $img_server['host'] === $cdn_server['host']) {
  87. continue;
  88. }
  89. // 파일의 확장자를 구한다.
  90. $read_img = $img;
  91. $fileinfo = pathinfo($read_img);
  92. $ext = (isset($fileinfo['extension']) && $fileinfo['extension']) ? $fileinfo['extension'] : "";
  93. // curl로 파일을 복사해온다.
  94. $ch = curl_init();
  95. curl_setopt($ch, CURLOPT_URL, $read_img);
  96. curl_setopt($ch, CURLOPT_HEADER, 0);
  97. curl_setopt($ch, CURLOPT_REFERER, $read_img);
  98. curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
  99. curl_setopt($ch, CURLOPT_BINARYTRANSFER, true);
  100. curl_setopt($ch, CURLOPT_USERAGENT, $user_agent);
  101. curl_setopt($ch, CURLOPT_TIMEOUT, 10);
  102. $img_content = curl_exec ($ch);
  103. $curl_info = curl_getinfo($ch, CURLINFO_CONTENT_TYPE);
  104. make_dir(DIR_UPLOAD . DIRECTORY_SEPARATOR . "editor", TRUE);
  105. $file_path_add = "./";
  106. $new_file_src = DIR_UPLOAD . "/editor/" .date('Y/m') ."/" .md5(time().$img) . ($ext?".".$ext:"");
  107. $new_url = base_url($new_file_src);
  108. $fh = fopen($file_path_add.$new_file_src, 'w');
  109. fwrite($fh, $img_content);
  110. fclose($fh);
  111. curl_close($ch);
  112. $imagesize = getimagesize($file_path_add.$new_file_src);
  113. if( $imagesize) {
  114. // 기존 html의 경로 바꾸기
  115. $content = str_replace( $img, $new_url, $content );
  116. }
  117. }
  118. }
  119. return $content;
  120. }
  121. /**
  122. * 댓글 목록 가져오기
  123. * @param $brd_key
  124. * @param $post_idx
  125. */
  126. function comment_list($brd_key, $post_idx, $board_admin=FALSE, $mem_userid="")
  127. {
  128. $board = $this->get_board($brd_key, TRUE);
  129. $comment_table = $this->db->dbprefix('board_comment');
  130. $param['select']= "{$comment_table}.*,member.mem_photo";
  131. $param['from'] = "board_comment";
  132. $param['join'][] = array("member", "member.mem_userid=board_comment.mem_userid","left");
  133. $param['where']['brd_key'] = $brd_key;
  134. $param['where']['post_idx'] = $post_idx;
  135. $param['where_in']['cmt_status'] = array('Y','B');
  136. $param['order_by'] = "cmt_num DESC,cmt_reply ASC, cmt_idx ASC";
  137. $list = $this->get_list($param);
  138. foreach($list['list'] as &$row)
  139. {
  140. $row['cmt_datetime'] = display_datetime( $row['cmt_regtime'], $board['brd_display_time']);
  141. $row['link']['delete'] = base_url("board/{$brd_key}/comment/{$post_idx}/{$row['cmt_idx']}/delete");
  142. $row['link']['blind'] = base_url("board/{$brd_key}/comment/{$post_idx}/{$row['cmt_idx']}/blind");
  143. $row['auth'] = $board_admin || ( $row['mem_userid'] >0 && $mem_userid == $row['mem_userid'] ) || $row['mem_userid']==0;
  144. $row['ip'] = display_ipaddress(long2ip($row['cmt_ip']), '1001');
  145. }
  146. return $list;
  147. }
  148. /**
  149. * 패러미터 정보를 가져온다.
  150. * @return string
  151. */
  152. function get_param()
  153. {
  154. // 링크를 위한 자료정리
  155. $queryParam = array();
  156. if( $this->input->get('category', TRUE) ) $queryParam['category'] = $this->input->get('category', TRUE);
  157. if( $this->input->get('page', TRUE) ) $queryParam['page'] = $this->input->get('page', TRUE);
  158. if( $this->input->get('scol', TRUE) ) $queryParam['scol'] = $this->input->get('scol', TRUE);
  159. if( $this->input->get('stxt', TRUE) ) $queryParam['stxt'] = $this->input->get('stxt', TRUE);
  160. $param = "";
  161. if( $queryParam && is_array($queryParam) )
  162. {
  163. $param = http_build_query($queryParam);
  164. $param = "?". $param;
  165. }
  166. return $param;
  167. }
  168. /**
  169. * 게시글에 포함된 첨부파일 목록을 가져온다.
  170. * @param $brd_key
  171. * @param $post_idx
  172. * @return array
  173. */
  174. function get_attach_list($brd_key, $post_idx)
  175. {
  176. if(empty($brd_key) OR empty($post_idx)) return array();
  177. $file_list = $this->db->where('brd_key', $brd_key)->where('post_idx', $post_idx)->get('board_attach')->result_array();
  178. foreach($file_list as &$f)
  179. {
  180. $f['link'] = base_url("board/{$brd_key}/download/{$post_idx}/{$f['att_idx']}");
  181. }
  182. return $file_list;
  183. }
  184. /**
  185. * 게시글 하나를 가져온다.
  186. * @param $brd_key
  187. * @param $post_idx
  188. * @param bool $get_raw_data
  189. * @return mixed
  190. */
  191. function get_post($brd_key, $post_idx, $get_raw_data=FALSE)
  192. {
  193. $this->db->select('board_post.*, member.mem_photo');
  194. $this->db->from('board_post');
  195. $this->db->join("member", "member.mem_userid=board_post.mem_userid","left");
  196. $this->db->where('post_idx', $post_idx);
  197. $this->db->where_in('post_status', array('Y','N'));
  198. $this->db->where('brd_key', $brd_key);
  199. $result =$this->db->get();
  200. $post = $result->row_array();
  201. if( ! $get_raw_data ) {
  202. $board = $this->get_board($brd_key,FALSE);
  203. $post = $this->post_process($board, $post, '',TRUE, TRUE);
  204. $np = $this->get_np($brd_key, $post_idx, $post['post_num'], $post['post_reply']);
  205. $post['prev'] = ( isset($np['prev']) && isset($np['prev']['post_idx']) )? $np['prev'] : NULL;
  206. $post['next'] = ( isset($np['next']) && isset($np['next']['post_idx']) )? $np['next'] : NULL;
  207. }
  208. return $post;
  209. }
  210. /**
  211. * 게시글의 내용을 정리한다.
  212. * @param $board
  213. * @param $post
  214. * @param $param
  215. * @param bool $extra
  216. * @param bool $files
  217. * @return mixed
  218. */
  219. function post_process($board, $post, $param, $files=FALSE, $thumbnail=FALSE)
  220. {
  221. $post['post_notice'] = ($post['post_notice']=='Y');
  222. $post['link'] = base_url("board/{$board['brd_key']}/{$post['post_idx']}".$param);
  223. $post['link_modify'] = base_url("board/{$board['brd_key']}/write/{$post['post_idx']}");
  224. $post['link_delete'] = base_url("board/{$board['brd_key']}/delete/{$post['post_idx']}");
  225. $post['is_new'] = ((time() - strtotime($post['post_regtime']) ) <= ($board['brd_time_new'] * 60 * 60));
  226. $post['is_hot'] = ($post['post_hit'] >= $board['brd_hit_count']) ;
  227. $post['is_secret'] = ($post['post_secret'] == 'Y');
  228. $post['post_datetime'] = display_datetime($post['post_regtime'], $board['brd_display_time']);
  229. if( $files)
  230. {
  231. $post['file'] = $this->get_attach_list($board['brd_key'], $post['post_idx']);
  232. }
  233. $post['post_thumbnail'] = "";
  234. if( $thumbnail )
  235. {
  236. if(! isset($post['file']))
  237. {
  238. $post['file'] = $this->get_attach_list($board['brd_key'], $post['post_idx']);
  239. }
  240. $post['post_thumbnail'] = get_post_thumbnail($post, $board['brd_thumb_width'], $board['brd_thumb_height']);
  241. }
  242. return $post;
  243. }
  244. /**********************************************************
  245. * 첨부파일 삭제
  246. * @param $bfi_idx
  247. * @return mixed
  248. *********************************************************/
  249. function attach_remove($att_idx)
  250. {
  251. if(empty($att_idx)) return false;
  252. $this->db->where("att_idx", $att_idx);
  253. $result = $this->db->get('board_attach');
  254. $attach = $result->row_array();
  255. if(! $attach) return false;
  256. if( file_exists(FCPATH. $attach['att_filename']) )
  257. {
  258. @unlink(FCPATH.$attach['att_filename']);
  259. }
  260. $this->db->where("att_idx", $att_idx);
  261. $this->db->delete("board_attach");
  262. }
  263. /**
  264. * 해당 게시판에 관리자 권한이 있는지 확인한다.
  265. * @param $brd_key
  266. * @param $member_idx
  267. * @return bool
  268. */
  269. function is_admin($brd_key, $member_idx)
  270. {
  271. if( empty($member_idx) OR $member_idx == 0 )
  272. {
  273. return FALSE;
  274. }
  275. $result = (int)$this->db->select('COUNT(*) AS cnt')->where('ath_type','BOARD')->where('ath_key', $brd_key)->where('mem_idx', $member_idx)->get('member_auth')->row(0)->cnt;
  276. return ( $result > 0 );
  277. }
  278. /**
  279. * 해당 게시글의 이전글과 다음글을 가져온다.
  280. * @param $brd_key
  281. * @param $post_idx
  282. * @param $post_num
  283. * @param $post_depth
  284. * @return mixed
  285. */
  286. function get_np($brd_key, $post_idx,$post_num,$post_reply)
  287. {
  288. $param = $this->get_param();
  289. $this->db->group_start();
  290. $this->db->or_group_start();
  291. $this->db->where("post_num =", (int)$post_num);
  292. $this->db->where('post_reply >', $post_reply);
  293. $this->db->where('post_idx >', $post_idx);
  294. $this->db->group_end();
  295. $this->db->or_group_start();
  296. $this->db->where('post_num <', $post_num);
  297. $this->db->group_end();
  298. $this->db->group_end();
  299. // 이전글 가져오기
  300. $return['prev'] = $this->db->where_in("post_status", array("Y","B"))
  301. ->where('post_notice', "N")
  302. ->where("brd_key", $brd_key)
  303. ->where('post_idx !=', $post_idx)
  304. ->limit(1)
  305. ->order_by("post_num DESC, post_reply ASC, post_idx ASC")
  306. ->get("board_post")
  307. ->row_array();
  308. if(isset($return['prev']['post_idx']))
  309. {
  310. $return['prev']['link'] = base_url("board/{$brd_key}/{$return['prev']['post_idx']}".$param);
  311. }
  312. $this->db->group_start();
  313. $this->db->or_group_start();
  314. $this->db->where("post_num =", (int)$post_num);
  315. $this->db->where('post_reply <', $post_reply);
  316. $this->db->where('post_idx <', $post_idx);
  317. $this->db->group_end();
  318. $this->db->or_group_start();
  319. $this->db->where('post_num >', $post_num);
  320. $this->db->group_end();
  321. $this->db->group_end();
  322. // 다음글 가져오기
  323. $return['next'] =
  324. $this->db->where_in("post_status", array("Y","B"))
  325. ->where('post_notice', "N")
  326. ->where("brd_key", $brd_key)
  327. ->where('post_idx !=', $post_idx)
  328. ->limit(1)
  329. ->order_by("post_num ASC, post_reply DESC, post_idx DESC")
  330. ->get("board_post")->row_array();
  331. if(isset($return['next']['post_idx']))
  332. {
  333. $return['next']['link'] = base_url("board/{$brd_key}/{$return['next']['post_idx']}".$param);
  334. }
  335. return $return;
  336. }
  337. /**
  338. * 게시판과 관련된 링크를 가져온다.
  339. * @param $brd_key
  340. * @param string $post_idx
  341. * @return mixed
  342. */
  343. function get_link($brd_key, $post_idx="")
  344. {
  345. $queryParam = array();
  346. if( $this->input->get('category', TRUE) ) $queryParam['category'] = $this->input->get('category', TRUE);
  347. if( $this->input->get('page', TRUE) ) $queryParam['page'] = $this->input->get('page', TRUE);
  348. if( $this->input->get('scol', TRUE) ) $queryParam['scol'] = $this->input->get('scol', TRUE);
  349. if( $this->input->get('stxt', TRUE) ) $queryParam['stxt'] = $this->input->get('stxt', TRUE);
  350. $param = "";
  351. if( $queryParam && is_array($queryParam) )
  352. {
  353. $param = http_build_query($queryParam);
  354. $param = "?". $param;
  355. }
  356. $return['base_url'] = base_url("board/{$brd_key}");
  357. $return['list'] = base_url("board/{$brd_key}". $param);
  358. $return['write'] = base_url( "board/{$brd_key}/write". $param );
  359. $return['rss'] = base_url("rss/{$brd_key}");
  360. if(! empty($post_idx))
  361. {
  362. $return['modify'] = base_url( "board/{$brd_key}/write/{$post_idx}".$param );
  363. $return['delete'] = base_url( "board/{$brd_key}/delete/{$post_idx}".$param );
  364. $return['reply'] = base_url( "board/{$brd_key}/reply/{$post_idx}". $param );
  365. }
  366. return $return;
  367. }
  368. /**
  369. * 게시판 목록을 가져온다.
  370. */
  371. function board_list()
  372. {
  373. $param['from'] = "board";
  374. $param['order_by'] = "brd_sort ASC";
  375. $param['limit'] = FALSE;
  376. $result = $this->get_list($param);
  377. return $result;
  378. }
  379. /**
  380. * 게시판 하나의 정보를 가져온다.
  381. * @param $brd_key
  382. */
  383. function get_board($brd_key, $raw_data = FALSE)
  384. {
  385. return $raw_data ? $this->_get_board_raw($brd_key) : $this->_get_board_mixed($brd_key);
  386. }
  387. /**
  388. * 가공되지 않은 게시판 정보를 가져온다.
  389. * @param $brd_key
  390. */
  391. private function _get_board_raw($brd_key)
  392. {
  393. if(empty($brd_key)) return array();
  394. if( ! $board = $this->cache->get('board_raw_'.$brd_key) ) {
  395. $param['from'] = "board";
  396. $param['idx'] = $brd_key;
  397. $param['column'] = "brd_key";
  398. $board = $this->get_one($param);
  399. if(! IS_TEST) {
  400. $this->cache->save('board_raw_'.$brd_key, $board, 60*5);
  401. }
  402. }
  403. return $board;
  404. }
  405. /**
  406. * 가공한 게시판의 정보를 가져온다.
  407. * @param $brd_key
  408. */
  409. private function _get_board_mixed($brd_key)
  410. {
  411. if( empty($brd_key) ) return array();
  412. if( ! $board = $this->cache->get('board_'.$brd_key) ) {
  413. $board = $this->_get_board_raw($brd_key);
  414. $board['category'] = $this->get_all_category($brd_key);
  415. if(! IS_TEST)
  416. {
  417. $this->cache->save('board_'.$brd_key, $board, 60*5);
  418. }
  419. }
  420. return $board;
  421. }
  422. /**
  423. * 특정 게시판의 캐시를 삭제한다.
  424. * @param $brd_key
  425. */
  426. function delete_cache($brd_key)
  427. {
  428. $this->cache->delete('board_raw_'.$brd_key);
  429. $this->cache->delete('board_'.$brd_key);
  430. }
  431. /**
  432. * 해당게시판의 전체 카테고리 구조 출력
  433. */
  434. function get_all_category($brd_key)
  435. {
  436. if(empty($brd_key)) return NULL;
  437. $this->db->where('brd_key', $brd_key);
  438. $this->db->order_by('bca_parent ASC, bca_sort ASC', TRUE);
  439. $this->db->from('board_category');
  440. $result = $this->db->get();
  441. $list = $result->result_array();
  442. $return = array();
  443. foreach($list as &$row)
  444. {
  445. if( $row['bca_parent'] == 0 )
  446. {
  447. $row['link'] = base_url("board/{$brd_key}?category=".$row['bca_idx']);
  448. $return[$row['bca_idx']] = $row;
  449. $return[$row['bca_idx']]['items'] = array();
  450. }
  451. else if ( $row['bca_parent'] >= 1 )
  452. {
  453. $row['link'] = base_url("board/{$brd_key}?category=".$row['bca_idx']);
  454. $return[$row['bca_parent']]['items'][] = $row;
  455. }
  456. }
  457. return $return;
  458. }
  459. /**
  460. * 카테고리 한개의 정보를 가져온다.
  461. * @param $bca_idx
  462. * @return bool
  463. */
  464. function get_category($bca_idx)
  465. {
  466. $param['from'] = "board_category";
  467. $param['idx'] = $bca_idx;
  468. $param['column'] = "bca_idx";
  469. return $this->get_one($param);
  470. }
  471. /**
  472. * 해당 게시글의 코멘트가 몇개인지 확인한다.
  473. * @param $brd_key
  474. * @param $post_idx
  475. */
  476. function get_comment_count($brd_key, $post_idx)
  477. {
  478. $count = (int)$this->db->select('COUNT(*) AS cnt')->from('board_comment')->where_in('cmt_status', array('Y','B'))->where('brd_key',$brd_key)->where('post_idx',$post_idx)->get()->row(0)->cnt;
  479. return $count;
  480. }
  481. /**
  482. * 해당 게시물의 댓글수를 최신화 한다
  483. * @param $brd_key
  484. * @param $post_idx
  485. */
  486. function update_post_comment_count($brd_key, $post_idx)
  487. {
  488. $count = $this->get_comment_count($brd_key, $post_idx);
  489. $this->db->where('brd_key', $brd_key);
  490. $this->db->where('post_idx', $post_idx);
  491. $this->db->set('post_count_comment', (int)$count);
  492. return $this->db->update('board_post');
  493. }
  494. }