5 * 提供存取以 MySQL 資料庫構成的資料結構後端的物件
\r
7 * @package PMCLibrary
\r
8 * @version $Id: pio.mysql.php 671 2008-09-20 05:54:15Z scribe $
\r
9 * @date $Date: 2008-09-20 13:54:15 +0800 (星期六, 20 九月 2008) $
\r
13 var $ENV, $username, $password, $server, $dbname, $tablename; // Local Constant
\r
14 var $con, $prepared, $useTransaction; // Local Global
\r
16 function PIOmysql($connstr='', $ENV){
\r
18 $this->prepared = 0;
\r
19 if($connstr) $this->dbConnect($connstr);
\r
22 /* private 攔截SQL錯誤 */
\r
23 function _error_handler($errarray, $query=''){
\r
24 $err = 'Pixmicat! SQL Error: '.$errarray[0].' on line '.$errarray[1];
\r
25 error_log($err."\n".mysql_errno().': '.mysql_error()."\n".$query."\n\n", 3, 'error.log');
\r
26 trigger_error($err, E_USER_ERROR);
\r
30 /* private 使用SQL字串和MySQL伺服器要求 */
\r
31 function _mysql_call($query, $errarray=false){
\r
32 $resource = mysql_query($query);
\r
33 if(is_array($errarray) && $resource===false) $this->_error_handler($errarray, $query);
\r
34 else return $resource;
\r
37 /* private 由資源輸出陣列 */
\r
38 function _ArrangeArrayStructure($line){
\r
40 while($row = mysql_fetch_array($line, MYSQL_ASSOC)) $posts[] = $row;
\r
41 mysql_free_result($line);
\r
46 function pioVersion(){
\r
47 return '0.6 (v20100404)';
\r
51 function dbConnect($connStr){
\r
52 // 格式: mysql://帳號:密碼@伺服器位置:埠號(可省略)/資料庫/資料表/
\r
53 // 示例: mysql://yotsubanome:pass@localhost/yotsubanome/img_loog/
\r
54 if(preg_match('/^mysql:\/\/(.*)\:(.*)\@(.*(?:\:[0-9]+)?)\/(.*)\/(.*)\/$/i', $connStr, $linkinfos)){
\r
55 $this->username = $linkinfos[1]; // 登入帳號
\r
56 $this->password = $linkinfos[2]; // 登入密碼
\r
57 $this->server = $linkinfos[3]; // 登入伺服器 (含埠號)
\r
58 $this->dbname = $linkinfos[4]; // 資料庫名稱
\r
59 $this->tablename = $linkinfos[5]; // 資料表名稱
\r
64 function dbInit($isAddInitData=true){
\r
66 if(mysql_num_rows(mysql_query("SHOW TABLES LIKE '".$this->tablename."'"))!=1){ // 資料表不存在
\r
67 $result = "CREATE TABLE ".$this->tablename." (primary key(no),
\r
68 index (resto),index (root),index (time),
\r
69 no int(1) not null auto_increment,
\r
70 resto int(1) not null,
\r
71 root timestamp(14) null DEFAULT 0,
\r
72 time int(1) not null,
\r
73 md5chksum varchar(32) not null,
\r
74 category varchar(255) not null,
\r
75 tim bigint(1) not null,
\r
76 ext varchar(4) not null,
\r
77 imgw smallint(1) not null,
\r
78 imgh smallint(1) not null,
\r
79 imgsize varchar(10) not null,
80 filename varchar(255) not null,
\r
81 tw smallint(1) not null,
\r
82 th smallint(1) not null,
\r
83 pwd varchar(8) not null,
\r
84 now varchar(255) not null,
\r
85 name varchar(255) not null,
\r
86 email varchar(255) not null,
\r
87 sub varchar(255) not null,
\r
89 host varchar(255) not null,
\r
90 status varchar(255) not null)
\r
92 COMMENT = 'PIO Structure V4'";
93 $result2 = @mysql_query("SHOW CHARACTER SET like 'utf8'"); // 是否支援UTF-8 (MySQL 4.1.1開始支援)
\r
94 if($result2 && mysql_num_rows($result2)){
\r
95 $result .= ' CHARACTER SET utf8 COLLATE utf8_general_ci'; // 資料表追加UTF-8編碼
\r
96 mysql_free_result($result2);
\r
98 mysql_query($result); // 正式新增資料表
100 if($isAddInitData) $this->addPost(0, 0, '', '', 0, '', 0, 0, '', '', 0, 0, '', '08/11/08(土) 10:24:04', '【スパーキー(④ ^ヮ^)】', '', $this->ENV['NOTITLE'], $this->ENV['NOCOMMENT'], ''); // 追加一筆新資料料
\r
106 function dbPrepare($transaction=false){
\r
107 if($this->prepared) return true;
\r
109 if(@!$this->con = mysql_pconnect($this->server, $this->username, $this->password)) $this->_error_handler(array('Open database failed', __LINE__));
\r
110 @mysql_select_db($this->dbname, $this->con);
\r
111 @mysql_query("SET NAMES 'utf8'"); // MySQL資料以UTF-8模式傳送
\r
112 $this->useTransaction = $transaction;
\r
113 if($transaction) @mysql_query('START TRANSACTION'); // 啟動交易性能模式
\r
115 $this->prepared = 1;
\r
119 function dbCommit(){
\r
120 if(!$this->prepared) return false;
\r
121 if($this->useTransaction) @mysql_query('COMMIT'); // 交易性能模式提交
\r
125 function dbMaintanence($action, $doit=false){
\r
129 $this->dbPrepare(false);
\r
130 if($this->_mysql_call('OPTIMIZE TABLES '.$this->tablename)) return true;
\r
132 }else return true; // 支援最佳化資料表
\r
136 $this->dbPrepare(false);
\r
137 if($rs=$this->_mysql_call('CHECK TABLE '.$this->tablename)){
\r
138 mysql_data_seek($rs, mysql_num_rows($rs)-1);
\r
139 $row = mysql_fetch_assoc($rs);
\r
140 return 'Table '.$row['Table'].': '.$row['Msg_type'].' = '.$row['Msg_text'];
\r
143 }else return true; // 支援檢查資料表
\r
147 $this->dbPrepare(false);
\r
148 if($rs=$this->_mysql_call('REPAIR TABLE '.$this->tablename)){
\r
149 mysql_data_seek($rs, mysql_num_rows($rs)-1);
\r
150 $row = mysql_fetch_assoc($rs);
\r
151 return 'Table '.$row['Table'].': '.$row['Msg_type'].' = '.$row['Msg_text'];
\r
154 }else return true; // 支援修復資料表
\r
158 $this->dbPrepare(false);
\r
159 $gp = gzopen('piodata.log.gz', 'w9');
\r
160 gzwrite($gp, $this->dbExport());
\r
162 return '<a href="piodata.log.gz">下載 piodata.log.gz 中介檔案</a>';
\r
163 }else return true; // 支援匯出資料
\r
165 default: return false; // 不支援
\r
170 function dbImport($data){
\r
171 $this->dbInit(false); // 僅新增結構不新增資料
\r
172 $data = explode("\r\n", $data);
\r
173 $data_count = count($data) - 1;
\r
174 $replaceComma = create_function('$txt', 'return str_replace(",", ",", $txt);');
\r
175 for($i = 0; $i < $data_count; $i++){
\r
176 $line = array_map($replaceComma, explode(',', $data[$i])); // 取代 , 為 ,
\r
177 $SQL = 'INSERT INTO '.$this->tablename.' (no,resto,root,time,md5chksum,category,tim,ext,imgw,imgh,imgsize,filename,tw,th,pwd,now,name,email,sub,com,host,status) VALUES ('.
\r
181 substr($line[5], 0, 10).',\''.
\r
182 mysql_real_escape_string($line[3], $this->con).'\',\''.
\r
183 mysql_real_escape_string($line[4], $this->con).'\','.
\r
184 $line[5].',\''.mysql_real_escape_string($line[6], $this->con).'\','.
\r
185 $line[7].','.$line[8].',\''.mysql_real_escape_string($line[9], $this->con).','.mysql_real_escape_string($line[10], $this->con).'\','.$line[11].','.$line[12].',\''.
\r
186 mysql_real_escape_string($line[13], $this->con).'\',\''.
\r
187 mysql_real_escape_string($line[14], $this->con).'\',\''.
\r
188 mysql_real_escape_string($line[15], $this->con).'\',\''.
\r
189 mysql_real_escape_string($line[16], $this->con).'\',\''.
\r
190 mysql_real_escape_string($line[17], $this->con).'\',\''.
\r
191 mysql_real_escape_string($line[18], $this->con).'\',\''.
\r
192 mysql_real_escape_string($line[19], $this->con).'\',\''.
\r
193 mysql_real_escape_string($line[20], $this->con).'\')';
\r
194 $this->_mysql_call($SQL, array('Import a new post failed', __LINE__));
\r
196 $this->dbCommit(); // 送交
\r
201 function dbExport(){
\r
202 if(!$this->prepared) $this->dbPrepare();
\r
203 $line = $this->_mysql_call('SELECT no,resto,root,md5chksum,category,tim,ext,imgw,imgh,imgsize,filename,tw,th,pwd,now,name,email,sub,com,host,status FROM '.$this->tablename.' ORDER BY no DESC',
\r
204 array('Export posts failed', __LINE__));
\r
206 $replaceComma = create_function('$txt', 'return str_replace(",", ",", $txt);');
\r
207 while($row = mysql_fetch_array($line, MYSQL_ASSOC)){
\r
208 $row = array_map($replaceComma, $row); // 取代 , 為 ,
\r
209 if($row['root']=='0000-00-00 00:00:00') $row['root'] = '0'; // 初始值設為 0
\r
210 $data .= rtrim(implode(',', $row)).",\r\n";
\r
212 mysql_free_result($line);
\r
217 function postCount($resno=0){
\r
218 if(!$this->prepared) $this->dbPrepare();
\r
220 if($resno){ // 回傳討論串總文章數目
\r
221 $line = $this->_mysql_call('SELECT COUNT(no) FROM '.$this->tablename.' WHERE resto = '.intval($resno),
\r
222 array('Fetch count in thread failed', __LINE__));
\r
223 $countline = mysql_result($line, 0) + 1;
\r
225 $line = $this->_mysql_call('SELECT COUNT(no) FROM '.$this->tablename, array('Fetch count of posts failed', __LINE__));
\r
226 $countline = mysql_result($line, 0);
\r
228 mysql_free_result($line);
\r
233 function threadCount(){
\r
234 if(!$this->prepared) $this->dbPrepare();
\r
236 $tree = $this->_mysql_call('SELECT COUNT(no) FROM '.$this->tablename.' WHERE resto = 0',
\r
237 array('Fetch count of threads failed', __LINE__));
\r
238 $counttree = mysql_result($tree, 0); mysql_free_result($tree); // 計算討論串目前資料筆數
\r
243 function getLastPostNo($state){
\r
244 if(!$this->prepared) $this->dbPrepare();
\r
246 if($state=='afterCommit'){ // 送出後的最後文章編號
\r
247 $tree = $this->_mysql_call('SELECT MAX(no) FROM '.$this->tablename, array('Get the last No. failed', __LINE__));
\r
248 $lastno = mysql_result($tree, 0); mysql_free_result($tree);
\r
250 }else return 0; // 其他狀態沒用
\r
254 function fetchPostList($resno=0, $start=0, $amount=0){
\r
255 if(!$this->prepared) $this->dbPrepare();
\r
258 $resno = intval($resno);
\r
259 if($resno){ // 輸出討論串的結構 (含自己, EX : 1,2,3,4,5,6)
\r
260 $tmpSQL = 'SELECT no FROM '.$this->tablename.' WHERE no = '.$resno.' OR resto = '.$resno.' ORDER BY no';
\r
261 }else{ // 輸出所有文章編號,新的在前
\r
262 $tmpSQL = 'SELECT no FROM '.$this->tablename.' ORDER BY no DESC';
\r
263 $start = intval($start); $amount = intval($amount);
\r
264 if($amount) $tmpSQL .= " LIMIT {$start}, {$amount}"; // 有指定數量才用 LIMIT
\r
266 $tree = $this->_mysql_call($tmpSQL, array('Fetch post list failed', __LINE__));
\r
267 while($rows = mysql_fetch_row($tree)) $line[] = $rows[0]; // 迴圈
\r
268 mysql_free_result($tree);
\r
273 function fetchThreadList($start=0, $amount=0, $isDESC=false){
\r
274 if(!$this->prepared) $this->dbPrepare();
\r
276 $start = intval($start); $amount = intval($amount);
\r
277 $treeline = array();
\r
278 $tmpSQL = 'SELECT no FROM '.$this->tablename.' WHERE resto = 0 ORDER BY '.($isDESC ? 'no' : 'root').' DESC';
\r
279 if($amount) $tmpSQL .= " LIMIT {$start}, {$amount}"; // 有指定數量才用 LIMIT
\r
280 $tree = $this->_mysql_call($tmpSQL, array('Fetch thread list failed', __LINE__));
\r
281 while($rows = mysql_fetch_row($tree)) $treeline[] = $rows[0]; // 迴圈
\r
282 mysql_free_result($tree);
\r
287 function fetchPosts($postlist){
\r
288 if(!$this->prepared) $this->dbPrepare();
\r
290 if(is_array($postlist)){ // 取多串
\r
291 $pno = implode(', ', $postlist); // ID字串
\r
292 $tmpSQL = 'SELECT * FROM '.$this->tablename.' WHERE no IN ('.$pno.') ORDER BY no';
\r
293 if(count($postlist) > 1){ if($postlist[0] > $postlist[1]) $tmpSQL .= ' DESC'; } // 由大排到小
\r
294 }else $tmpSQL = 'SELECT * FROM '.$this->tablename.' WHERE no = '.intval($postlist); // 取單串
\r
295 $line = $this->_mysql_call($tmpSQL, array('Fetch the post content failed', __LINE__));
\r
296 return $this->_ArrangeArrayStructure($line); // 輸出陣列結構
\r
299 /* 刪除舊附件 (輸出附件清單) */
\r
300 function delOldAttachments($total_size, $storage_max, $warnOnly=true){
\r
302 if(!$this->prepared) $this->dbPrepare();
\r
304 $arr_warn = $arr_kill = array(); // 警告 / 即將被刪除標記陣列
\r
305 $result = $this->_mysql_call('SELECT no,ext,tim FROM '.$this->tablename.' WHERE ext <> \'\' ORDER BY no',
\r
306 array('Get old posts failed', __LINE__));
\r
307 while(list($dno, $dext, $dtim) = mysql_fetch_row($result)){ // 個別跑舊文迴圈
\r
308 $dfile = $dtim.$dext; // 附加檔案名稱
\r
309 $dthumb = $dtim.'s.jpg'; // 預覽檔案名稱
\r
310 if($FileIO->imageExists($dfile)){ $total_size -= $FileIO->getImageFilesize($dfile) / 1024; $arr_kill[] = $dno; $arr_warn[$dno] = 1; } // 標記刪除
\r
311 if($FileIO->imageExists($dthumb)) $total_size -= $FileIO->getImageFilesize($dthumb) / 1024;
\r
312 if($total_size < $storage_max) break;
\r
314 mysql_free_result($result);
\r
315 return $warnOnly ? $arr_warn : $this->removeAttachments($arr_kill);
\r
319 function removePosts($posts){
\r
320 if(!$this->prepared) $this->dbPrepare();
\r
321 if(count($posts)==0) return array();
\r
323 $files = $this->removeAttachments($posts, true); // 先遞迴取得刪除文章及其回應附件清單
\r
324 $pno = implode(', ', $posts); // ID字串
\r
325 $this->_mysql_call('DELETE FROM '.$this->tablename.' WHERE no IN ('.$pno.') OR resto IN('.$pno.')',
\r
326 array('Delete old posts and replies failed', __LINE__)); // 刪掉文章
\r
330 /* 刪除附件 (輸出附件清單) */
\r
331 function removeAttachments($posts, $recursion=false){
\r
333 if(!$this->prepared) $this->dbPrepare();
\r
334 if(count($posts)==0) return array();
\r
337 $pno = implode(', ', $posts); // ID字串
\r
338 if($recursion) $tmpSQL = 'SELECT ext,tim FROM '.$this->tablename.' WHERE (no IN ('.$pno.') OR resto IN('.$pno.")) AND ext <> ''"; // 遞迴取出 (含回應附件)
\r
339 else $tmpSQL = 'SELECT ext,tim FROM '.$this->tablename.' WHERE no IN ('.$pno.") AND ext <> ''"; // 只有指定的編號
\r
341 $result = $this->_mysql_call($tmpSQL, array('Get attachments of the post failed', __LINE__));
\r
342 while(list($dext, $dtim) = mysql_fetch_row($result)){ // 個別跑迴圈
\r
343 $dfile = $dtim.$dext; // 附加檔案名稱
\r
344 $dthumb = $dtim.'s.jpg'; // 預覽檔案名稱
\r
345 if($FileIO->imageExists($dfile)) $files[] = $dfile;
\r
346 if($FileIO->imageExists($dthumb)) $files[] = $dthumb;
\r
348 mysql_free_result($result);
\r
353 function addPost($no, $resto, $md5chksum, $category, $tim, $ext, $imgw, $imgh, $imgsize, $filename, $tw, $th, $pwd, $now, $name, $email, $sub, $com, $host, $age=false, $status='') {
\r
354 if(!$this->prepared) $this->dbPrepare();
\r\r
355 $time = (int)substr($tim, 0, -3); // 13位數的數字串是檔名,10位數的才是時間數值
\r
356 $updatetime = gmdate('Y-m-d H:i:s'); // 更動時間 (UTC)
\r
357 $resto = intval($resto);
\r
358 if($resto){ // 新增回應
\r
361 $this->_mysql_call('UPDATE '.$this->tablename.' SET root = "'.$updatetime.'" WHERE no = '.$resto,
\r
362 array('Push the post failed', __LINE__)); // 將被回應的文章往上移動
\r
363 }
\r }else $root = $updatetime; // 新增討論串, 討論串最後被更新時間
\r
365 if($no === 0){ // init post 0
366 $query = 'INSERT INTO '.$this->tablename.' (no,resto,root,time,md5chksum,category,tim,ext,imgw,imgh,imgsize,tw,th,pwd,now,name,email,sub,com,host,status) VALUES ('.
369 "'$root',". // 最後更新時間
371 "'$md5chksum',". // 附加檔案md5
372 "'".mysql_real_escape_string($category, $this->con)."',". // 分類標籤
373 "'$tim', '$ext',". // 附加檔名
374 (int)$imgw.','.(int)$imgh.",'".$imgsize."','".$filename."',".(int)$tw.','.(int)$th.','. // 圖檔長寬及檔案大小;預覽圖長寬
375 "'".mysql_real_escape_string($pwd, $this->con)."',".
\r
376 "'$now',". // 時間(含ID)字串
377 "'".mysql_real_escape_string($name, $this->con)."',".
\r
378 "'".mysql_real_escape_string($email, $this->con)."',".
\r
379 "'".mysql_real_escape_string($sub, $this->con)."',".
\r
380 "'".mysql_real_escape_string($com, $this->con)."',".
\r
381 "'".mysql_real_escape_string($host, $this->con)."', '".mysql_real_escape_string($status, $this->con)."')";
383 $query = 'INSERT INTO '.$this->tablename.' (resto,root,time,md5chksum,category,tim,ext,imgw,imgh,imgsize,tw,th,pwd,now,name,email,sub,com,host,status) VALUES ('.
\r
385 "'$root',". // 最後更新時間
387 "'$md5chksum',". // 附加檔案md5
388 "'".mysql_real_escape_string($category, $this->con)."',". // 分類標籤
389 "'$tim', '$ext',". // 附加檔名
390 (int)$imgw.','.(int)$imgh.",'".$imgsize."','".$filename."',".(int)$tw.','.(int)$th.','. // 圖檔長寬及檔案大小;預覽圖長寬
391 "'".mysql_real_escape_string($pwd, $this->con)."',".
\r
392 "'$now',". // 時間(含ID)字串
393 "'".mysql_real_escape_string($name, $this->con)."',".
\r
394 "'".mysql_real_escape_string($email, $this->con)."',".
\r
395 "'".mysql_real_escape_string($sub, $this->con)."',".
\r
396 "'".mysql_real_escape_string($com, $this->con)."',".
\r
397 "'".mysql_real_escape_string($host, $this->con)."', '".mysql_real_escape_string($status, $this->con)."')";
399 $this->_mysql_call($query, array('Insert a new post failed', __LINE__));
\r
403 function isSuccessivePost($lcount, $com, $timestamp, $pass, $passcookie, $host, $isupload){
\r
405 if(!$this->prepared) $this->dbPrepare();
\r
407 if(!$this->ENV['PERIOD.POST']) return false; // 關閉連續投稿檢查
\r
408 $timestamp = intval($timestamp);
\r
409 $tmpSQL = 'SELECT pwd,host FROM '.$this->tablename.' WHERE time > '.($timestamp - (int)$this->ENV['PERIOD.POST']); // 一般投稿時間檢查
\r
410 if($isupload) $tmpSQL .= ' OR time > '.($timestamp - (int)$this->ENV['PERIOD.IMAGEPOST']); // 附加圖檔的投稿時間檢查 (與下者兩者擇一)
\r
411 else $tmpSQL .= ' OR md5(com) = "'.md5($com).'"'; // 內文一樣的檢查 (與上者兩者擇一)
\r
413 $result = $this->_mysql_call($tmpSQL, array('Get the post to check the succession failed', __LINE__));
\r
414 while(list($lpwd, $lhost) = mysql_fetch_row($result)){
\r
415 // 判斷為同一人發文且符合連續投稿條件
\r
416 if($host==$lhost || $pass==$lpwd || $passcookie==$lpwd) return true;
\r
422 function isDuplicateAttachment($lcount, $md5hash){
\r
424 if(!$this->prepared) $this->dbPrepare();
\r
426 $result = $this->_mysql_call('SELECT tim,ext FROM '.$this->tablename." WHERE ext <> '' AND md5chksum = '$md5hash' ORDER BY no DESC",
\r
427 array('Get the post to check the duplicate attachment failed', __LINE__));
\r
428 while(list($ltim, $lext) = mysql_fetch_row($result)){
\r
429 if($FileIO->imageExists($ltim.$lext)) return true; // 有相同檔案
\r
435 function isThread($no){
\r
436 if(!$this->prepared) $this->dbPrepare();
\r
438 $result = $this->_mysql_call('SELECT no FROM '.$this->tablename.' WHERE no = '.intval($no).' AND resto = 0');
\r
439 return mysql_fetch_array($result) ? true : false;
\r
443 function searchPost($keyword, $field, $method){
\r
444 if(!$this->prepared) $this->dbPrepare();
\r
446 $keyword_cnt = count($keyword);
\r
447 $SearchQuery = 'SELECT * FROM '.$this->tablename." WHERE {$field} LIKE '%".mysql_real_escape_string($keyword[0], $this->con)."%'";
\r
448 if($keyword_cnt > 1){
\r
449 for($i = 1; $i < $keyword_cnt; $i++){
\r
450 $SearchQuery .= " {$method} {$field} LIKE '%".mysql_real_escape_string($keyword[$i], $this->con)."%'"; // 多重字串交集 / 聯集搜尋
\r
453 $SearchQuery .= ' ORDER BY no DESC'; // 按照號碼大小排序
\r
454 $line = $this->_mysql_call($SearchQuery, array('Search the post failed', __LINE__));
\r
455 return $this->_ArrangeArrayStructure($line); // 輸出陣列結構
\r
459 function searchCategory($category){
\r
460 if(!$this->prepared) $this->dbPrepare();
\r
462 $foundPosts = array();
\r
463 $SearchQuery = 'SELECT no FROM '.$this->tablename." WHERE lower(category) LIKE '%,".strtolower(mysql_real_escape_string($category, $this->con)).",%' ORDER BY no DESC";
\r
464 $line = $this->_mysql_call($SearchQuery, array('Search the category failed', __LINE__));
\r
465 while($rows = mysql_fetch_row($line)) $foundPosts[] = $rows[0];
\r
466 mysql_free_result($line);
\r
467 return $foundPosts;
\r
471 function getPostStatus($status){
\r
472 return new FlagHelper($status); // 回傳 FlagHelper 物件
\r
476 function updatePost($no, $newValues){
\r
477 if(!$this->prepared) $this->dbPrepare();
\r
480 $chk = array('resto', 'md5chksum', 'category', 'tim', 'ext', 'imgw', 'imgh', 'imgsize', 'filename', 'tw', 'th', 'pwd', 'now', 'name', 'email', 'sub', 'com', 'host', 'status');
\r
481 foreach($chk as $c){
\r
482 if(isset($newValues[$c])){
\r
483 $this->_mysql_call('UPDATE '.$this->tablename." SET $c = '".mysql_real_escape_string($newValues[$c], $this->con)."', root = root WHERE no = ".$no,
\r
484 array('Update the field of the post failed', __LINE__)); // 更新討論串屬性
\r
490 function setPostStatus($no, $newStatus){
\r
491 $this->updatePost($no, array('status' => $newStatus));
\r