PageRenderTime 59ms CodeModel.GetById 15ms RepoModel.GetById 0ms app.codeStats 1ms

/controller/api.class.php

https://github.com/no2key/TeamToy
PHP | 2564 lines | 1447 code | 557 blank | 560 comment | 407 complexity | 087630566edf2f065afffca89ccccc61 MD5 | raw file
Possible License(s): AGPL-1.0

Large files files are truncated, but you can click here to view the full file

  1. <?php
  2. if( !defined('IN') ) die('bad request');
  3. include_once( AROOT . 'controller'.DS.'app.class.php' );
  4. define( 'LR_API_TOKEN_ERROR' , 10001 );
  5. define( 'LR_API_USER_ERROR' , 10002 );
  6. define( 'LR_API_DB_ERROR' , 10004 );
  7. define( 'LR_API_NOT_IMPLEMENT_YET' , 10005 );
  8. define( 'LR_API_ARGS_ERROR' , 10006 );
  9. define( 'LR_API_DB_EMPTY_RESULT' , 10007 );
  10. define( 'LR_API_USER_CLOSED' , 10008 );
  11. define( 'LR_API_FORBIDDEN' , 10009 );
  12. define( 'LR_API_UPGRADE_ERROR' , 10010 );
  13. define( 'LR_API_UPGRADE_ABORT' , 10011 );
  14. /**
  15. * TeamToy Open Api
  16. *
  17. * @author easychen
  18. * @version $Id$
  19. * @package server
  20. *
  21. */
  22. /**
  23. * apiController class
  24. * TeamToy OpenAPI实现
  25. *
  26. * <code>
  27. * <?php
  28. * $api_url = 'http://api.teamtoy.net/index.php';
  29. * $info = json_decode(file_get_contents( $api_url . '?c=api&a=user_get_token&password=******&email=abc@qq.com' ) , 1);
  30. * $token = $info['data']['token'];
  31. *
  32. * $todos = json_decode(file_get_contents( $api_url . '?c=api&a=todo_list&token=' . $token ) , 1);
  33. * print_r( $todos );
  34. *
  35. *
  36. * ?>
  37. * </code>
  38. *
  39. *
  40. * @author easychen
  41. * @package server
  42. *
  43. */
  44. class apiController extends appController
  45. {
  46. function __construct()
  47. {
  48. parent :: __construct();
  49. apply_filter( 'API_' . g('a') .'_INPUT_FILTER' );
  50. $not_check = array( 'user_sign_up' , 'user_get_token' );
  51. $not_check = apply_filter('API_LOGIN_ACTION_FILTER' , $not_check );
  52. if( !in_array( g('a') , $not_check )) $this->check_token();
  53. }
  54. public function __call( $method , $args)
  55. {
  56. // 进入这里表示不存在当前调用的api(no public method)
  57. return do_action( 'API_' . $method , $args );
  58. }
  59. /**
  60. * 用户注册
  61. *
  62. * 只有以管理员的token才能注册用户,否则需要激活码
  63. *
  64. * @param string name
  65. * @param string email
  66. * @param string password
  67. * @return user array
  68. * @author EasyChen
  69. */
  70. public function user_sign_up()
  71. {
  72. if( !not_empty( v( 'name' ) )) return $this -> send_error( LR_API_ARGS_ERROR , 'name FIELD REQUIRED' );
  73. if( !is_email( v( 'email' ) ) ) return $this -> send_error( LR_API_ARGS_ERROR , 'email FORMAT ERROR' );
  74. if( strlen( v( 'password' ) ) < 1 ) return $this -> send_error( LR_API_ARGS_ERROR , 'password FIELD REQUIRED' );// actions
  75. // admin add user derictly
  76. $jump = false;
  77. $token = z( t( v( 'token' ) ) );
  78. if( strlen( $token ) > 2 )
  79. {
  80. session_id( $token );
  81. session_set_cookie_params( c('session_time') );
  82. @session_start();
  83. if($_SESSION['level'] == '9') $jump = true;
  84. }
  85. if( !$jump )
  86. {
  87. if( !not_empty( v( 'code' ) )) return $this -> send_error( LR_API_ARGS_ERROR , 'activecode REQUIRED' );
  88. $code = z(t(v('code')));
  89. if( get_var( "SELECT COUNT(*) FROM `activecode` WHERE `code` = '" . s($code) . "' AND `timeline` > '" . date( "Y-m-d H:i:s " , strtotime("-1day")) . "'" ) < 1 )
  90. return $this -> send_error( LR_API_ARGS_ERROR , 'activecode error or expired' );
  91. }
  92. if( get_var("SELECT COUNT(*) FROM `user` WHERE `email` = '" . s( t(v('email')) ) . "'") > 0 )
  93. return $this -> send_error( LR_API_ARGS_ERROR , 'email EXISTS' );
  94. $dsql = array();
  95. $dsql[] = "'" . s( v( 'name' ) ) . "'";
  96. $dsql[] = "'" . s( pinyin(v( 'name' )) ) . "'";
  97. $dsql[] = "'" . s( v( 'email' ) ) . "'";
  98. $dsql[] = "'" . s( md5( v( 'password' ) ) ) . "'";
  99. $dsql[] = "'" . s( date( "Y-m-d H:i:s" ) ) . "'";
  100. $sql = "INSERT INTO `user` ( `name` , `pinyin` , `email` , `password` , `timeline` ) VALUES ( " . join( ' , ' , $dsql ) . " )";
  101. run_sql( $sql );
  102. if( db_errno() != 0 )
  103. {
  104. return $this -> send_error( LR_API_DB_ERROR , 'DATABASE ERROR ' . db_error() );
  105. }
  106. $lid = last_id();
  107. if( $lid < 1 )
  108. {
  109. return $this -> send_error( LR_API_DB_ERROR , 'DATABASE ERROR ' . db_error() );
  110. }
  111. if( !$data = get_user_info_by_id( $lid ) )
  112. return $this -> send_error( LR_API_DB_ERROR , 'DATABASE ERROR ' . db_error() );
  113. else
  114. {
  115. // one code for multi-people
  116. /*
  117. $sql = "DELETE FROM `activecode` WHERE `code` = '" . s($code) . "' LIMIT 1";
  118. run_sql( $sql );
  119. */
  120. publish_feed( $data['name'] . '加入了TeamToy' , $data['uid'] , 3 );
  121. return $this -> send_result( $data );
  122. }
  123. }
  124. /**
  125. * 终止当前token
  126. *
  127. *
  128. * @param string token , 必填
  129. * @return user array
  130. * @author EasyChen
  131. */
  132. public function user_end_session()
  133. {
  134. $data = array();
  135. $data['token'] = $_SESSION['token'];
  136. $data['uid'] = $_SESSION['uid'];
  137. foreach( $_SESSION as $key=>$value )
  138. {
  139. unset( $_SESSION[$key] );
  140. }
  141. session_destroy();
  142. return $this -> send_result( $data );
  143. }
  144. /**
  145. * 检查是否存在新版本
  146. *
  147. *
  148. * @param string token , 必填
  149. * @return info array ( 'new' , 'version' , 'info' )
  150. * @author EasyChen
  151. */
  152. public function check_new_verison( $in = false )
  153. {
  154. $last = intval(kget('last_check'));
  155. if( $last > 0 && ( (time()-$last) < 60*60 ) && $in )
  156. {
  157. // checked in 1 hour
  158. // do nothing
  159. }
  160. else
  161. {
  162. // set timeout
  163. $ctx=stream_context_create(array('http'=>array( 'timeout' => 3 )));
  164. // send domain and uid to help teamtoy.net anti-cc attack
  165. $url = c('teamtoy_url') . '/?a=last_version&domain=' . c('site_domain') . '&uid=' . $user[ 'id' ];
  166. $new = false;
  167. if($info = @file_get_contents($url , 0 , $ctx))
  168. {
  169. $info_array = json_decode($info,true);
  170. if( $new_build = intval($info_array['version']) )
  171. {
  172. if( $new_build > local_version() )
  173. {
  174. $new = true;
  175. $last_noticed_version = intval(kget('last_notice'));
  176. if( $last_noticed_version > 0 )
  177. {
  178. if( $new_build > $last_noticed_version )
  179. $send = 1;
  180. else
  181. $send = 0;
  182. }
  183. else
  184. $send = 1;
  185. if( $send == 1 )
  186. {
  187. // send notice to current user
  188. $text = 'TeamToy'.$new_build.'版本已发布';
  189. if( !$in )
  190. {
  191. send_notice( uid() , $text , 10 , array( 'info' => $info_array['desp'] ) );
  192. kset('last_notice',$new_build);
  193. }
  194. }
  195. }
  196. kset('last_check',time());
  197. }
  198. }
  199. if( !$in )
  200. {
  201. if( $new )
  202. return $this->send_result( array('new'=>1 ,'info' => $info_array['desp'] , 'version' => $info_array['version'] ) );
  203. else
  204. return $this->send_result( array('new'=>0 ) );
  205. }
  206. }
  207. }
  208. /**
  209. * 通过email和密码获取token
  210. *
  211. * @param string email
  212. * @param string password
  213. * @return token array( 'token' , 'uid' , 'uname' , 'email' , 'level' )
  214. * @author EasyChen
  215. */
  216. public function user_get_token()
  217. {
  218. $email = z( t( v( 'email' ) ) );
  219. $password = z( t( v( 'password' ) ) );
  220. if( $user = get_full_info_by_email_password( $email , $password ) )
  221. {
  222. if( $user['is_closed'] == '1' )
  223. return $this->send_error( LR_API_USER_CLOSED , 'USER CLOSED BY ADMIN' );
  224. session_set_cookie_params( c('session_time') );
  225. @session_start();
  226. $token = session_id();
  227. $_SESSION[ 'token' ] = $token;
  228. $_SESSION[ 'uid' ] = $user[ 'id' ];
  229. $_SESSION[ 'uname' ] = $user['name'];
  230. $_SESSION[ 'email' ] = $user[ 'email' ];
  231. $_SESSION[ 'level' ] = $user['level'];
  232. if( c('api_check_new_verison') )
  233. $this->check_new_verison( true );
  234. return $this -> send_result( $_SESSION );
  235. }
  236. else
  237. {
  238. return $this -> send_error( LR_API_TOKEN_ERROR , 'BAD ACCOUNT OR PASSWORD' );
  239. }
  240. }
  241. /**
  242. * 在线升级
  243. *
  244. * 只有管理员token才能调用
  245. *
  246. * @param string token , 必填
  247. * @param string password
  248. * @return msg array( 'msg'=>ok )
  249. * @author EasyChen
  250. */
  251. function upgrade()
  252. {
  253. if( $_SESSION['level'] != '9' )
  254. return $this->send_error( LR_API_FORBIDDEN , 'ONLY ADMIN CAN DO THIS' );
  255. $info = json_decode( file_get_contents( c('teamtoy_url') . '/?a=last_version&domain=' . c('site_domain') . '&uid=' . uid() ) , true);
  256. if( !isset($info['url']) ) return $this -> send_error( LR_API_UPGRADE_ERROR , ' JSON DATA ERROR' );
  257. $url = t($info['url']);
  258. $vid = intval($info['version']);
  259. if( $vid < 1 ) return $this -> send_error( LR_API_UPGRADE_ERROR , ' JSON DATA ERROR' );
  260. if( $vid == local_version() )
  261. {
  262. return $this -> send_error( LR_API_UPGRADE_ABORT , ' ALREADY LATEST VERSION' );
  263. }
  264. $zip_tmp = SAE_TMP_PATH . DS . 'teamtoy2-' . intval($vid) . '.zip';
  265. if( @copy( $url , $zip_tmp ) )
  266. {
  267. include_once( AROOT.'lib'.DS.'dUnzip2.inc.php' );
  268. $zip = new dUnzip2( $zip_tmp );
  269. $zip->debug = false;
  270. $zip->unzipAll( AROOT );
  271. chmod( AROOT , 0755 );
  272. if( isset( $info['post_script'] ) ) $pscript = t($info['post_script']);
  273. else $pscript = false;
  274. if( local_version() == $vid )
  275. {
  276. if( $pscript )
  277. send_notice( uid() , 'TeamToy代码已经更新到' . $vid . ',<a href="'. c('site_url') . $pscript .'">请立即升级数据表</a>' , 0 );
  278. return $this->send_result( array('msg'=>'ok','post_script'=>$pscript) );
  279. }
  280. else
  281. return $this -> send_error( LR_API_UPGRADE_ERROR , ' FILE UNZIP ERROR' );
  282. }
  283. else
  284. {
  285. return $this -> send_error( LR_API_UPGRADE_ERROR , ' COPY REMOTE FILE ERROR' );
  286. }
  287. }
  288. /**
  289. * 读取用户个人资料
  290. *
  291. * 不包含密码
  292. *
  293. * @param string token , 必填
  294. * @param int uid
  295. * @return user array
  296. * @author EasyChen
  297. */
  298. function user_profile()
  299. {
  300. $uid = intval(v('uid'));
  301. if( $uid < 1 ) return $this->send_error( LR_API_ARGS_ERROR , 'UID CAN\'T BE EMPTY' );
  302. return $this->send_result( get_user_info_by_id($uid) );
  303. }
  304. /**
  305. * 更新用户个人资料
  306. *
  307. * 不包含密码
  308. *
  309. * @param string token , 必填
  310. * @param string mobile - 手机号 , 必填
  311. * @param string email - 电子邮件 , 必填
  312. * @param string tel - 分机号 , 选填
  313. * @param string eid - 工号, 选填
  314. * @param string weibo - 微博昵称, 选填
  315. * @param string desp - 备注, 选填
  316. * @return user array
  317. * @author EasyChen
  318. */
  319. function user_update_profile()
  320. {
  321. $mobile = z(t(v('mobile')));
  322. $tel = z(t(v('tel')));
  323. $eid = z(t(v('eid')));
  324. $weibo = z(t(v('weibo')));
  325. $desp = z(t(v('desp')));
  326. $email = z(t(v('email')));
  327. if( !not_empty($email) ) return $this -> send_error( LR_API_ARGS_ERROR , 'email FIELD REQUIRED' );
  328. if( !not_empty($mobile) ) return $this -> send_error( LR_API_ARGS_ERROR , 'mobile FIELD REQUIRED' );
  329. $sql = "UPDATE `user` SET "
  330. ." `mobile` = '" . s($mobile) . "' "
  331. ." , `tel` = '" . s($tel) . "' "
  332. ." , `eid` = '" . s($eid) . "' "
  333. ." , `weibo` = '" . s($weibo) . "' "
  334. ." , `email` = '" . s($email) . "' "
  335. ." , `desp` = '" . s($desp) . "' WHERE `id` = '" . uid() . "' LIMIT 1 ";
  336. run_sql( $sql );
  337. if( db_errno() != 0 )
  338. return $this -> send_error( LR_API_DB_ERROR , 'DATABASE ERROR ' . db_error() );
  339. else
  340. return $this->send_result( get_user_info_by_id(uid()) );
  341. }
  342. /**
  343. * 读取用户扩展设置
  344. *
  345. * @ignore
  346. */
  347. function user_settings()
  348. {
  349. if(!is_array( $settings = get_user_settings_by_id( $_SESSION['uid'] ) ))
  350. return $this->send_error( LR_API_DB_ERROR , 'CAN\'T FIND DATA' );
  351. else
  352. return $this->send_result( $settings );
  353. }
  354. /**
  355. * 更新用户密码
  356. *
  357. *
  358. * @param string token , 必填
  359. * @param string opassword - 原密码 , 必填
  360. * @param string password -新密码 , 必填
  361. * @return msg array( 'msg'=>ok )
  362. * @author EasyChen
  363. */
  364. function user_update_password()
  365. {
  366. $opassword = z(t(v('opassword')));
  367. if( !not_empty($opassword) ) return $this -> send_error( LR_API_ARGS_ERROR , 'old password FIELD REQUIRED' );
  368. $password = z(t(v('password')));
  369. if( !not_empty($password) ) return $this -> send_error( LR_API_ARGS_ERROR , 'password FIELD REQUIRED' );
  370. if( $opassword == $password ) return $this -> send_error( LR_API_ARGS_ERROR , 'password and old password are the same' );
  371. $sql = "SELECT COUNT(*) FROM `user` WHERE `id` = '" . intval( uid() ) . "' AND `password` = '" . md5( $opassword ) . "' ";
  372. if( get_var( $sql ) < 1 )
  373. return $this -> send_error( LR_API_ARGS_ERROR , 'Old password wrong' );
  374. $sql = "UPDATE `user` SET `password` = MD5('" . s($password) . "') WHERE `id` = '" . intval( uid() ) . "' AND `password` = '" . md5( $opassword ) . "' LIMIT 1";
  375. run_sql( $sql );
  376. if( db_errno() != 0 )
  377. return $this -> send_error( LR_API_DB_ERROR , 'DATABASE ERROR ' . db_error() );
  378. else
  379. return $this->send_result( array('msg'=>'ok') );
  380. }
  381. /**
  382. * 更新用户扩展设置
  383. *
  384. * @ignore
  385. */
  386. function user_update_settings()
  387. {
  388. $key = z(t(v('key')));
  389. if( !not_empty($key) ) return $this -> send_error( LR_API_ARGS_ERROR , 'key FIELD REQUIRED' );
  390. if(!$value = unserialize(v('value')))
  391. {
  392. $value = z(t(v('value')));
  393. if( !not_empty($value) ) return $this -> send_error( LR_API_ARGS_ERROR , 'value FIELD REQUIRED' );
  394. }
  395. else
  396. {
  397. if( !is_array($value) ) return $this -> send_error( LR_API_ARGS_ERROR , 'value FIELD REQUIRED' );
  398. }
  399. if(!is_array( $settings = get_user_settings_by_id( $_SESSION['uid'] ) ))
  400. return $this->send_error( LR_API_DB_ERROR , 'CAN\'T FIND DATA' );
  401. else
  402. {
  403. $settings[$key] = $value;
  404. update_user_settings_array( $settings );
  405. if( db_errno() != 0 )
  406. return $this -> send_error( LR_API_DB_ERROR , 'DATABASE ERROR ' . db_error() );
  407. else
  408. return $this->send_result( $settings );
  409. }
  410. }
  411. /**
  412. * 更新用户等级
  413. *
  414. * 必须是管理员的token,level9为管理员,不能修改自己的等级
  415. *
  416. * @param string token , 必填
  417. * @param string uid , 必填
  418. * @return user array
  419. * @author EasyChen
  420. */
  421. function user_level()
  422. {
  423. $uid = intval(v('uid'));
  424. if( $uid < 1 ) return $this->send_error( LR_API_ARGS_ERROR , 'UID CAN\'T BE EMPTY' );
  425. if( $uid == uid() ) return $this->send_error( LR_API_ARGS_ERROR , 'CANNOT CHANGE YOUR SELF' );
  426. if(!$user = get_user_info_by_id( $uid ))
  427. return $this->send_error( LR_API_ARGS_ERROR , 'UID NOT EXISTS' );
  428. $level = intval(v('level'));
  429. if( $_SESSION['level'] != '9' )
  430. return $this->send_error( LR_API_FORBIDDEN , 'ONLY ADMIN CAN DO THIS' );
  431. if( $level == 0 ) $more = " , `is_closed` = 1 ";
  432. else $more = "";
  433. $sql = "UPDATE `user` SET `level` = '" . intval( $level ) . "' " . $more . " WHERE `id` = '" . intval($uid) . "' LIMIT 1";
  434. run_sql( $sql );
  435. if( db_errno() != 0 )
  436. return $this -> send_error( LR_API_DB_ERROR , 'DATABASE ERROR ' . db_error() );
  437. else
  438. {
  439. if( $level == 0 )
  440. {
  441. publish_feed( uname().'关闭了账号【'. $user['name'] .'】' , uid() , 1 );
  442. $user['level'] = 0;
  443. return $this->send_result( $user );
  444. }
  445. else
  446. {
  447. publish_feed( uname().'修改了账号【'. $user['name'] .'】权限为'.$level , uid() , 1 );
  448. return $this->send_result( get_user_info_by_id($uid) );
  449. }
  450. }
  451. }
  452. /**
  453. * 关闭用户
  454. *
  455. * 必须是管理员的token
  456. *
  457. * @param string token , 必填
  458. * @param string uid , 必填
  459. * @return user array
  460. * @author EasyChen
  461. */
  462. function user_close()
  463. {
  464. $uid = intval(v('uid'));
  465. if( $uid < 1 ) return $this->send_error( LR_API_ARGS_ERROR , 'UID CAN\'T BE EMPTY' );
  466. if(!$user = get_user_info_by_id( $uid ))
  467. return $this->send_error( LR_API_ARGS_ERROR , 'UID NOT EXISTS' );
  468. if( $_SESSION['level'] != '9' )
  469. return $this->send_error( LR_API_FORBIDDEN , 'ONLY ADMIN CAN DO THIS' );
  470. if( $user['is_closed'] == '1' )
  471. return $this->send_error( LR_API_USER_CLOSED , 'USER CLOSED BY ADMIN' );
  472. if( $_SESSION['level'] == '9' && $uid == uid() )
  473. {
  474. $admin_num = get_var( "SELECT COUNT(*) FROM `user` WHERE `is_closed` = 0 AND `level` = 9 " );
  475. if( $admin_num < 2 ) return $this->send_error( LR_API_FORBIDDEN , 'CANNOT CLOSE THE ONLY ADMIN' );
  476. }
  477. close_user_by_id($uid);
  478. if( db_errno() != 0 )
  479. return $this -> send_error( LR_API_DB_ERROR , 'DATABASE ERROR ' . db_error() );
  480. else
  481. {
  482. publish_feed( uname().'关闭了账号【'. $user['name'] .'】' , uid() , 1 );
  483. return $this->send_result( $user );
  484. }
  485. }
  486. /**
  487. * 添加TODO
  488. *
  489. *
  490. * @param string token , 必填
  491. * @param string text - TODO内容 , 必填
  492. * @param string is_public - 是否公开 , 默认为1
  493. * @param string uid - 要给添加TODO的用户id , uid为0时添加给自己。私有TODO不能添加给其他人
  494. * @return todo array
  495. * @author EasyChen
  496. */
  497. public function todo_add()
  498. {
  499. $content = z(t(v('text')));
  500. if( !not_empty($content) ) return $this->send_error( LR_API_ARGS_ERROR , 'TEXT CAN\'T EMPTY' );
  501. $is_public = intval(v('is_public'));
  502. if( $is_public != 0 ) $is_public = 1;
  503. $uid = intval(v('uid'));
  504. // 检查是否已经存在
  505. $sql = "SELECT * FROM `todo` WHERE `content` = '" . s( $content ) . "' AND `owner_uid` = '" . intval(uid()) . "' LIMIT 1";
  506. if( $todo = get_line($sql) )
  507. {
  508. if( get_var( "SELECT COUNT(*) FROM `todo_user` WHERE `tid` = '" . intval( $todo['id'] ) . "' AND `uid` = '" . intval( uid() ) . "' AND `status` != 3 " ) > 0 )
  509. return $this-> send_error( LR_API_ARGS_ERROR , 'TODO EXISTS ' );
  510. }
  511. if( !$tid = add_todo( $content , $is_public ))
  512. {
  513. return $this-> send_error( LR_API_DB_ERROR , 'DATABASE ERROR ' . db_error() );
  514. }
  515. $tinfo = get_todo_info_by_id( $tid );
  516. if( $is_public == 1 )
  517. {
  518. if( $uid > 0 && $uid !=uid() )
  519. {
  520. $this->todo_assign( $tid , $uid , true );
  521. $tinfo['other'] = 1;
  522. }
  523. else
  524. publish_feed( uname().'添加了TODO【'. $content .'】' , uid() , 2 , $tid );
  525. }
  526. return $this->send_result( $tinfo );
  527. }
  528. /**
  529. * 删除TODO评论
  530. *
  531. *
  532. * @param string token , 必填
  533. * @param string hid - 评论id, 必填
  534. * @return comment array
  535. * @author EasyChen
  536. */
  537. public function todo_remove_comment()
  538. {
  539. $hid = intval(v('hid'));
  540. if( intval( $hid ) < 1 ) return $this->send_error( LR_API_ARGS_ERROR , 'HID NOT EXISTS' );
  541. $sql = "SELECT *,`id` as `hid` FROM `todo_history` WHERE `id` = '" . intval( $hid ) . "' LIMIT 1";
  542. if( !$hitem = get_line( $sql ) )
  543. {
  544. if( db_errno() != 0 )
  545. return $this->send_error( LR_API_DB_ERROR , 'DATABASE ERROR ' . mysql_error() );
  546. else
  547. return $this->send_error( LR_API_DB_EMPTY_RESULT , 'DATA NOT EXISTS' );
  548. }
  549. else
  550. {
  551. if( ($hitem['uid'] != $_SESSION['uid']) && $_SESSION['level'] < 9 )
  552. {
  553. return $this->send_error( LR_API_FORBIDDEN , 'CANNOT REMOVE OTHER\'S COMMENT' );
  554. }
  555. if( $hitem['type'] != 2 )
  556. {
  557. return $this->send_error( LR_API_ARGS_ERROR , 'HTYPE ERROR' );
  558. }
  559. $sql = "DELETE FROM `todo_history` WHERE `id` = '" . intval($hid) . "' LIMIT 1";
  560. run_sql( $sql );
  561. if( db_errno() != 0 )
  562. return $this->send_error( LR_API_DB_ERROR , 'DATABASE ERROR ' . mysql_error() );
  563. else
  564. return $this->send_result( $hitem );
  565. }
  566. }
  567. /**
  568. * 为TODO添加评论
  569. *
  570. *
  571. * @param string token , 必填
  572. * @param string tid - TODOid, 必填
  573. * @param string text - 评论内容, 必填
  574. * @return comment array
  575. * @author EasyChen
  576. */
  577. public function todo_add_comment()
  578. {
  579. $content = z(t(v('text')));
  580. if( !not_empty($content) ) return $this->send_error( LR_API_ARGS_ERROR , 'TEXT CAN\'T EMPTY' );
  581. $tid = intval(v('tid'));
  582. if( intval( $tid ) < 1 ) return $this->send_error( LR_API_ARGS_ERROR , 'TID NOT EXISTS' );
  583. $tinfo = get_line("SELECT * FROM `todo` WHERE `id` = '" . intval( $tid ) . "' LIMIT 1");
  584. if( is_mobile_request() ) $device = 'mobile';
  585. else $device = 'web';
  586. $sql = "INSERT INTO `todo_history` ( `tid` , `uid` , `content` , `type` , `timeline` , `device` )
  587. VALUES ( '" . intval($tid) . "' , '" . intval($_SESSION['uid']) . "' , '" . s( $content ) . "' , '2' , NOW() , '" . s($device) . "' ) ";
  588. run_sql( $sql );
  589. if( db_errno() != 0 )
  590. return $this->send_error( LR_API_DB_ERROR , 'DATABASE ERROR ' . mysql_error() );
  591. else
  592. {
  593. $lid = last_id();
  594. // 向订阅todo的同学发送通知
  595. $sql = "SELECT `uid` FROM `todo_user` WHERE `tid`= '" . intval($tid) . "' AND `is_follow` = 1 ";
  596. $follow_uids = array();
  597. if( $uitems = get_data( $sql ) )
  598. foreach( $uitems as $uitem )
  599. {
  600. if( $uitem['uid'] != uid() )
  601. {
  602. if( !in_array( $uitem['uid'] , $follow_uids ) )
  603. {
  604. send_notice( $uitem['uid'] , uname() .'评论了你关注的TODO【'. $tinfo['content'] .'】: '.$content , 1 , array('tid'=>intval($tid) ) );
  605. $follow_uids[] = $uitem['uid'];
  606. }
  607. }
  608. }
  609. // 向todo作者发通知
  610. if( $tinfo['owner_uid'] != uid() )
  611. {
  612. if( !in_array( $tinfo['owner_uid'] , $follow_uids ) )
  613. send_notice( $tinfo['owner_uid'] , uname() .'评论了你的TODO【'. $tinfo['content'] .'】: '.$content , 1 , array('tid'=>intval($tid) ) );
  614. }
  615. // 向被@的同学,发送通知
  616. if( $ats = find_at($content) )
  617. {
  618. $sql = "SELECT `id` FROM `user` WHERE ";
  619. foreach( $ats as $at )
  620. {
  621. $at =z(t($at));
  622. if( mb_strlen($at, 'UTF-8') < 2 ) continue;
  623. $wsql[] = " `name` = '" . s(t($at)) . "' ";
  624. if( c('at_short_name') )
  625. if( mb_strlen($at, 'UTF-8') == 2 )
  626. $wsql[] = " `name` LIKE '_" . s($at) . "' ";
  627. }
  628. if( isset( $wsql ) && is_array( $wsql ) )
  629. {
  630. $sql = $sql . join( ' OR ' , $wsql );
  631. if( $udata = get_data( $sql ) )
  632. foreach( $udata as $uitem )
  633. if( !in_array( $uitem['id'] , $follow_uids ) )
  634. $myuids[] = $uitem['id'];
  635. if( isset( $myuids ) && is_array($myuids) )
  636. {
  637. $myuids = array_unique($myuids);
  638. foreach( $myuids as $muid )
  639. {
  640. if( $muid != uid() && $muid != $tinfo['owner_uid'] )
  641. send_notice( $muid , uname().'在TODO【'.$tinfo['content'].'】的评论中@了你: '.$content , 1 , array('tid'=>intval($tid) ));
  642. }
  643. }
  644. }
  645. }
  646. if( $comment = get_line( "SELECT * FROM `todo_history` WHERE `id` = '" . intval($lid) . "' LIMIT 1" , db() ) )
  647. {
  648. $comment['user'] = get_user_info_by_id( $_SESSION['uid'] );
  649. if($tinfo['is_public'] == 1)
  650. publish_feed( uname().'评论了TODO【'. $tinfo['content'] .'】: '.$content , uid() , 2 , $tid );
  651. return $this->send_result( $comment );
  652. }
  653. else
  654. {
  655. if( db_errno() != 0 )
  656. return $this->send_error( LR_API_DB_ERROR , 'DATABASE ERROR ' . mysql_error() );
  657. else
  658. return $this->send_error( LR_API_DB_EMPTY_RESULT , 'DATA NOT EXISTS' );
  659. }
  660. }
  661. }
  662. /**
  663. * 读取TODO详细信息
  664. *
  665. * 其他人的私有TODO会无法读取
  666. *
  667. * @param string token , 必填
  668. * @param string tid - TODOid, 必填
  669. * @return todo array
  670. * @author EasyChen
  671. */
  672. public function todo_detail()
  673. {
  674. $tid = intval(v('tid'));
  675. if( intval( $tid ) < 1 ) return $this->send_error( LR_API_ARGS_ERROR , 'TID NOT EXISTS' );
  676. if( $tinfo = get_todo_info_by_id( $tid ) )
  677. {
  678. return $this->send_result( $tinfo );
  679. }
  680. else
  681. {
  682. if( db_errno() != 0 )
  683. return $this->send_error( LR_API_DB_ERROR , 'DATABASE ERROR ' . mysql_error() );
  684. else
  685. return $this->send_error( LR_API_DB_EMPTY_RESULT , 'DATA NOT EXISTS' );
  686. }
  687. }
  688. /**
  689. * 指派TODO给其他人
  690. *
  691. * 不可以分配给自己
  692. *
  693. * @param string token , 必填
  694. * @param string tid - TODOid, 必填
  695. * @param string uid - 要指派的用户id, 必填
  696. * @return todo array
  697. * @author EasyChen
  698. */
  699. public function todo_assign( $tid = false , $uid = false , $in = false )
  700. {
  701. if( !$tid ) $tid = intval(v('tid'));
  702. if( intval( $tid ) < 1 ) return $this->send_error( LR_API_ARGS_ERROR , 'TID NOT EXISTS' );
  703. if( !$uid ) $uid = intval(v('uid'));
  704. if( intval( $uid ) < 1 ) return $this->send_error( LR_API_ARGS_ERROR , 'UIDS ERROR' );
  705. if( $uid == $_SESSION['uid'] ) return $this->send_error( LR_API_ARGS_ERROR , 'ASSIGN TO SELF' );
  706. if( !$tinfo = get_line( "SELECT * FROM `todo_user` WHERE `tid` = '" . intval($tid) . "' AND `uid` = '" . uid() . "' LIMIT 1" ) )
  707. {
  708. if( db_errno() != 0 )
  709. return $this->send_error( LR_API_DB_ERROR , 'DATABASE ERROR ' . mysql_error() );
  710. else
  711. return $this->send_error( LR_API_DB_EMPTY_RESULT , 'DATA NOT EXISTS' );
  712. }
  713. else
  714. {
  715. if( $tinfo['uid'] != uid() ) return $this->send_error( LR_API_FORBIDDEN , 'CANNOT ASSING OTHER\'S TODO' );
  716. // 更新todo表
  717. $sql = "UPDATE `todo` SET `owner_uid` = '" . intval( $uid ) . "' WHERE `id` = '" . intval($tid) . "' LIMIT 1";
  718. run_sql( $sql );
  719. if( db_errno() != 0 )
  720. if( $in )
  721. return false;
  722. else
  723. return $this->send_error( LR_API_DB_ERROR , 'DATABASE ERROR ' . mysql_error() );
  724. // 将新的uid加入 todo_user 表
  725. $sql = "REPLACE INTO `todo_user` ( `uid` , `tid` , `status` , `last_action_at` ) VALUES ( '" . intval( $uid ) . "' , '" . intval( $tid ) . "' , 1 , NOW() ) ";
  726. run_sql( $sql );
  727. if( db_errno() != 0 )
  728. if( $in )
  729. return false;
  730. else
  731. return $this->send_error( LR_API_DB_ERROR , 'DATABASE ERROR ' . mysql_error() );
  732. // 将现有uid 变为follow状态
  733. $sql = "UPDATE `todo_user` SET `is_follow` = 1 WHERE `tid` = '" . intval($tid) . "' AND `uid` = '" . intval($_SESSION['uid']) . "' LIMIT 1";
  734. run_sql( $sql );
  735. if( db_errno() != 0 )
  736. if( $in )
  737. return false;
  738. else
  739. return $this->send_error( LR_API_DB_ERROR , 'DATABASE ERROR ' . mysql_error() );
  740. // 获取被转让人的信息
  741. $uinfo = get_user_info_by_id($uid);
  742. $todo_text = get_todo_text_by_id( $tid );
  743. // 向todo新主人发送通知
  744. send_notice( intval( $uid ) , uname() .'向你转让了TODO【'. $todo_text .'】' , 1 , array('tid'=>intval($tid)) );
  745. // 向todo关注者发送通知
  746. $sql = "SELECT `uid` FROM `todo_user` WHERE `tid`= '" . intval($tid) . "' AND `is_follow` = 1 ";
  747. if( $uitems = get_data( $sql ) )
  748. foreach( $uitems as $uitem )
  749. {
  750. // 避免向当前转让人发送通知
  751. if( $uitem['uid'] != uid() )
  752. send_notice( $uitem['uid'] , uname() .'将你关注的TODO【'. $todo_text .'】转让给了'.$uinfo['name'] , 1 , array('tid'=>intval($tid) ) );
  753. }
  754. add_history( $tid , '转让了TODO' );
  755. publish_feed( uname().'将TODO【'. $todo_text .'】转让给了'.$uinfo['name'] , uid() , 2 , $tid );
  756. if( $in )
  757. return get_todo_info_by_id( $tid ) ;
  758. else
  759. return $this->send_result( get_todo_info_by_id( $tid ) );
  760. }
  761. }
  762. /**
  763. * 获取TODO列表
  764. *
  765. *
  766. * @param string token , 必填
  767. * @param string since_id - 最小TODO id
  768. * @param string max_id - 最大TODO id
  769. * @param string count - 每页TODO条数
  770. * @param string ord - 排序 , asc 或者 desc
  771. * @param string by - 排序字段
  772. * @param string group - 按分组输出,默认为false
  773. * @return todo list array
  774. * @author EasyChen
  775. */
  776. public function todo_list()
  777. {
  778. $uid = intval(v('uid'));
  779. if( $uid < 1 ) $uid = $_SESSION['uid'];
  780. $since_id = intval( v( 'since_id' ) );
  781. $max_id = intval( v( 'max_id' ) );
  782. $count = intval( v( 'count' ) );
  783. $order = strtolower( z( t( v( 'ord' ) ) ) );
  784. $by = strtolower( z( t( v( 'by' ) ) ) );
  785. if( $order != 'desc' )
  786. $ord = ' ASC ';
  787. else
  788. $ord = ' DESC ';
  789. if( strlen( $by ) > 0 )
  790. {
  791. $osql = ' ORDER BY `' . s( $by ) . '` ' . $ord . ' ';
  792. }
  793. else
  794. $osql = '';
  795. if( $count < 1 ) $count = 10;
  796. if( $count > 100 ) $count = 100;
  797. if( $since_id > 0 )
  798. $wsql = " AND `id` > '" . intval( $since_id ) . "' ";
  799. elseif( $max_id > 0 )
  800. $wsql = " AND `id` < '" . intval( $max_id ) . "' ";
  801. else
  802. $wsql = '';
  803. if( $uid != uid() ) $wsql .= ' AND `is_public` = 1 ';
  804. $sql = "SELECT * FROM `todo_user` WHERE `uid` = '" . intval($uid) . "' ";
  805. $sql = $sql . $wsql . $osql . " LIMIT " . $count ;
  806. if( !$data = get_data( $sql ) ) return $this->send_error( LR_API_DB_EMPTY_RESULT , 'EMPTY RESULT' );
  807. if( db_errno() != 0 )
  808. return $this->send_error( LR_API_DB_ERROR , 'DATABASE ERROR ' );
  809. $tids = array();
  810. foreach( $data as $item )
  811. {
  812. $tids[] = $item['tid'];
  813. $todos[$item['tid']] = $item;
  814. }
  815. if( count( $tids ) > 0 )
  816. {
  817. $sql = "SELECT * FROM `todo` WHERE `id` IN ( " . join( ' , ' , $tids ) . ") ORDER BY FIELD( `id` , " . join( ' , ' , $tids ) . " )";
  818. $todo = get_data( $sql );
  819. foreach( $todo as $t )
  820. {
  821. $todos[$t['id']]['uid'] = $t['owner_uid'];
  822. $todos[$t['id']]['content'] = $t['content'];
  823. $todos[$t['id']]['timeline'] = $t['timeline'];
  824. }
  825. // todo : sort it
  826. if( intval(v('group')) != 1 )
  827. return $this->send_result(array_values($todos));
  828. else
  829. {
  830. $ret = Array();
  831. foreach( $todos as $tt )
  832. {
  833. if( $tt['is_follow'] ==1 )
  834. $ret['follow'][] = $tt;
  835. elseif( $tt['status'] == 3 )
  836. $ret['done'][] = $tt;
  837. elseif( $tt['is_star'] == 1 )
  838. $ret['star'][] = $tt;
  839. else
  840. $ret['normal'][] = $tt;
  841. }
  842. return $this->send_result($ret);
  843. }
  844. }
  845. else
  846. {
  847. if( db_errno() != 0 )
  848. return $this->send_error( LR_API_DB_ERROR , 'DATABASE ERROR ' . mysql_error() );
  849. else
  850. return $this->send_error( LR_API_DB_EMPTY_RESULT , 'DATA NOT EXISTS' );
  851. }
  852. /*
  853. if( $data = get_user_todo_list_by_uid() )
  854. {
  855. return $this->send_result( $data );
  856. }
  857. else
  858. {
  859. return $this-> send_error( LR_API_DB_ERROR , 'DATABASE ERROR ' . db_error() );
  860. }*/
  861. }
  862. /**
  863. * TODO加星
  864. *
  865. *
  866. * @param string token , 必填
  867. * @param string tid - TODO id , 必填
  868. * @return todo array
  869. * @author EasyChen
  870. */
  871. public function todo_star()
  872. {
  873. return $this->todo_set_value( 'is_star' , 1 );
  874. }
  875. /**
  876. * TODO去星
  877. *
  878. *
  879. * @param string token , 必填
  880. * @param string tid - TODO id , 必填
  881. * @return todo array
  882. * @author EasyChen
  883. */
  884. public function todo_unstar()
  885. {
  886. return $this->todo_set_value( 'is_star' , 0 );
  887. }
  888. /**
  889. * TODO设为公开
  890. *
  891. *
  892. * @param string token , 必填
  893. * @param string tid - TODO id , 必填
  894. * @return todo array
  895. * @author EasyChen
  896. */
  897. public function todo_public()
  898. {
  899. return $this->todo_set_value( 'is_public' , 1 );
  900. }
  901. /**
  902. * TODO设为私密
  903. *
  904. *
  905. * @param string token , 必填
  906. * @param string tid - TODO id , 必填
  907. * @return todo array
  908. * @author EasyChen
  909. */
  910. public function todo_private()
  911. {
  912. return $this->todo_set_value( 'is_public' , 0 );
  913. }
  914. /**
  915. * TODO设为已完成
  916. *
  917. *
  918. * @param string token , 必填
  919. * @param string tid - TODO id , 必填
  920. * @return todo array
  921. * @author EasyChen
  922. */
  923. public function todo_done()
  924. {
  925. return $this->todo_set_value( 'status' , 3 );
  926. }
  927. /**
  928. * 重开TODO
  929. *
  930. *
  931. * @param string token , 必填
  932. * @param string tid - TODO id , 必填
  933. * @return todo array
  934. * @author EasyChen
  935. */
  936. public function todo_reopen()
  937. {
  938. return $this->todo_set_value( 'status' , 1 );
  939. }
  940. /**
  941. * @ignore
  942. */
  943. private function todo_set_value( $field , $value )
  944. {
  945. $tid = intval(v('tid'));
  946. if( $tid < 1 ) return $this->send_error( LR_API_ARGS_ERROR , 'id FIELD REQUIRED' );
  947. $sql = "SELECT * FROM `todo_user` WHERE `tid` = '" . intval($tid) . "' AND `uid` = '" . intval($_SESSION['uid']) . "' LIMIT 1" ;
  948. if( !$data = get_line( $sql ))
  949. return $this->send_error( LR_API_FORBIDDEN , 'YOU CANNOT UPDATE OTHERS TODO' );
  950. // delete uid and limit 1
  951. // to make all record updated at sametime
  952. // for all the followers
  953. $sql = "UPDATE `todo_user` SET `" . s( $field ) . "` = '" . intval( $value ) . "' , `last_action_at` = NOW() WHERE `tid` = '" . intval( $tid ) . "' ";
  954. run_sql( $sql );
  955. if( mysql_errno() != 0 )
  956. return $this -> send_error( LR_API_DB_ERROR , 'DATABASE ERROR ' . mysql_error() );
  957. else
  958. {
  959. $todoinfo = get_todo_info_by_id( $tid , true );
  960. kset('dinfo', $todoinfo['details']['is_public'] );
  961. if( $field == 'status' && $value == 3 )
  962. {
  963. if( $todoinfo['details']['is_public'] == 1 )
  964. {
  965. publish_feed( uname().'完成了TODO【'. $todoinfo['content'] .'】' , uid() , 2 , $tid );
  966. // send notice
  967. // 向订阅todo的同学发送通知
  968. $sql = "SELECT `uid` FROM `todo_user` WHERE `tid`= '" . intval($tid) . "' AND `is_follow` = 1 ";
  969. if( $uitems = get_data( $sql ) )
  970. foreach( $uitems as $uitem )
  971. {
  972. if( $uitem['uid'] != uid() )
  973. send_notice( $uitem['uid'] , uname() .'完成了你关注的TODO【'. $todoinfo['content'] .'】' , 1 , array('tid'=>intval($tid) ) );
  974. }
  975. }
  976. }
  977. return $this -> send_result( $todoinfo );
  978. }
  979. }
  980. /**
  981. * TODO取消关注
  982. *
  983. *
  984. * @param string token , 必填
  985. * @param string tid - TODO id , 必填
  986. * @return todo array
  987. * @author EasyChen
  988. */
  989. public function todo_unfollow()
  990. {
  991. $tid = intval(v('tid'));
  992. if( $tid < 1 ) return $this->send_error( LR_API_ARGS_ERROR , 'id FIELD REQUIRED' );
  993. $sql = "SELECT * FROM `todo_user` WHERE `tid` = '" . intval($tid) . "' AND `uid` = '" . intval($_SESSION['uid']) . "' LIMIT 1" ;
  994. if( !$data = get_line( $sql ))
  995. {
  996. return $this->send_error( LR_API_ARGS_ERROR , 'TID NOT EXSITS' );
  997. }
  998. else
  999. {
  1000. $sql = "DELETE FROM `todo_user` WHERE `tid` = '" . intval($tid) . "' AND `uid` = '" . intval($_SESSION['uid']) . "' AND `is_follow` = 1 LIMIT 1";
  1001. run_sql( $sql );
  1002. if( db_errno() != 0 )
  1003. return $this -> send_error( LR_API_DB_ERROR , 'DATABASE ERROR ' . mysql_error() );
  1004. else
  1005. {
  1006. return $this -> send_result(get_todo_info_by_id( $tid , true ));
  1007. }
  1008. }
  1009. }
  1010. /**
  1011. * TODO添加关注
  1012. *
  1013. *
  1014. * @param string token , 必填
  1015. * @param string tid - TODO id , 必填
  1016. * @return todo array
  1017. * @author EasyChen
  1018. */
  1019. public function todo_follow()
  1020. {
  1021. $tid = intval(v('tid'));
  1022. if( $tid < 1 ) return $this->send_error( LR_API_ARGS_ERROR , 'id FIELD REQUIRED' );
  1023. $sql = "SELECT * FROM `todo_user` WHERE `tid` = '" . intval($tid) . "' AND `uid` = '" . intval($_SESSION['uid']) . "' LIMIT 1" ;
  1024. if( !$data = get_line( $sql ))
  1025. {
  1026. // 没数据正常的
  1027. $sql = "INSERT IGNORE INTO `todo_user` ( `uid` , `tid` , `status` , `is_follow` , `last_action_at` ) VALUES ( '" . intval( $_SESSION['uid'] ) . "' , '" . intval( $tid ) . "' , 1 , 1 , NOW() ) ";
  1028. run_sql( $sql );
  1029. if( db_errno() != 0 )
  1030. return $this -> send_error( LR_API_DB_ERROR , 'DATABASE ERROR ' . mysql_error() );
  1031. else
  1032. return $this -> send_result(get_todo_info_by_id( $tid , true ));
  1033. }
  1034. else
  1035. {
  1036. return $this->send_error( LR_API_ARGS_ERROR , 'TID exists' );
  1037. }
  1038. }
  1039. /**
  1040. * TODO更新文字内容
  1041. *
  1042. *
  1043. * @param string token , 必填
  1044. * @param string tid - TODO id , 必填
  1045. * @param string text - TODO内容 , 必填
  1046. * @return todo array
  1047. * @author EasyChen
  1048. */
  1049. public function todo_update()
  1050. {
  1051. $tid = intval(v('tid'));
  1052. if( $tid < 1 ) return $this->send_error( LR_API_ARGS_ERROR , 'id FIELD REQUIRED' );
  1053. // check user
  1054. //$sql = "SELECT * FROM `todo_user` WHERE `tid` = '" . intval($tid) . "' AND `uid` = '" . intval($_SESSION['uid']) . "' LIMIT 1" ;
  1055. $sql = "SELECT * FROM `todo` WHERE `id` = '" . intval($tid) . "' AND `owner_uid` = '" . intval(uid()) . "' LIMIT 1";
  1056. if( !$data = get_line( $sql ))
  1057. return $this->send_error( LR_API_FORBIDDEN , 'YOU CANNOT UPDATE OTHERS TODO' );
  1058. $content = z(t(v('text')));
  1059. if( !not_empty($content) ) return $this->send_error( LR_API_ARGS_ERROR , 'text FIELD REQUIRED' );
  1060. $sql = "UPDATE `todo` SET `content` = '" . s($content) . "' WHERE `id` = '" . intval($tid) . "' LIMIT 1";
  1061. run_sql( $sql );
  1062. if( mysql_errno() != 0 )
  1063. return $this -> send_error( LR_API_DB_ERROR , 'DATABASE ERROR ' . mysql_error() );
  1064. else
  1065. {
  1066. run_sql( "UPDATE `todo_user` SET `last_action_at` = NOW() WHERE `tid` = '" . intval($tid) . "' AND `uid` = '" . intval($_SESSION['uid']) . "' LIMIT 1");
  1067. return $this -> send_result(get_todo_info_by_id( $tid , true ));
  1068. }
  1069. }
  1070. /**
  1071. * 清除已经完成的单个TODO
  1072. *
  1073. *
  1074. * @param string token , 必填
  1075. * @param string tid - TODO id , 必填
  1076. * @return todo array
  1077. * @author EasyChen
  1078. */
  1079. public function todo_remove_done()
  1080. {
  1081. // @TODO clean all the info in other tables
  1082. $sql = "DELETE FROM `todo_user` WHERE `uid` = '" . intval($_SESSION['uid']) . "' AND `status` = 3 " ;
  1083. run_sql( $sql );
  1084. if( mysql_errno() != 0 )
  1085. {
  1086. return $this -> send_error( LR_API_DB_ERROR , 'DATABASE ERROR ' . mysql_error() );
  1087. }
  1088. else
  1089. return $this -> send_result( array('msg'=>'ok') );
  1090. }
  1091. /**
  1092. * 清除所有已经完成的TODO标记为
  1093. *
  1094. *
  1095. * @param string token , 必填
  1096. * @param string tid - TODO id , 必填
  1097. * @return todo array
  1098. * @author EasyChen
  1099. */
  1100. public function todo_all_done()
  1101. {
  1102. // @TODO clean all the info in other tables
  1103. $sql = "UPDATE `todo_user` SET `status` = 3 WHERE `uid` = '" . intval($_SESSION['uid']) . "' AND ( `status` = 1 OR `status` = 2 ) " ;
  1104. run_sql( $sql );
  1105. if( mysql_errno() != 0 )
  1106. {
  1107. return $this -> send_error( LR_API_DB_ERROR , 'DATABASE ERROR ' . mysql_error() );
  1108. }
  1109. else
  1110. return $this -> send_result( array('msg'=>'ok') );
  1111. }
  1112. /**
  1113. * 删除TODO
  1114. *
  1115. *
  1116. * @param string token , 必填
  1117. * @param string tid - TODO id , 必填
  1118. * @return todo array
  1119. * @author EasyChen
  1120. */
  1121. public function todo_remove()
  1122. {
  1123. $tid = intval(v('tid'));
  1124. if( $tid < 1 ) return $this->send_error( LR_API_ARGS_ERROR , 'id FIELD REQUIRED' );
  1125. $old = get_todo_info_by_id( $tid );
  1126. $sql = "DELETE FROM `todo_user` WHERE `tid` = '" . intval($tid) . "' AND `uid` = '" . intval($_SESSION['uid']) . "' LIMIT 1" ;
  1127. run_sql( $sql );
  1128. if( mysql_errno() != 0 )
  1129. {
  1130. return $this -> send_error( LR_API_DB_ERROR , 'DATABASE ERROR ' . mysql_error() );
  1131. }
  1132. else
  1133. return $this -> send_result( $old );
  1134. }
  1135. /**
  1136. * 离线同步TODO
  1137. *
  1138. * 客户端用
  1139. * @ignore
  1140. */
  1141. public function todo_sync()
  1142. {
  1143. // 首先判断text是否存在
  1144. // 然后根据tid 判断是更新还是添加操作
  1145. //
  1146. $content = z(t(v('text')));
  1147. if( !not_empty( $content ) ) return $this->send_error( LR_API_ARGS_ERROR , 'TEXT CANNOT BE EMPTY' );
  1148. $tid = intval(v('tid'));
  1149. if( $tid < 0 )
  1150. {
  1151. if( intval(v('is_delete')) == 1 )
  1152. {
  1153. // 在本地添加后又在本地删除了
  1154. return $this->send_result( array( 'msg' => 'already delete local' ) );
  1155. }
  1156. // add
  1157. return $this->todo_add();
  1158. }
  1159. else
  1160. {
  1161. // 鉴权
  1162. $sql = "SELECT * FROM `todo_user` WHERE `tid` = '" . intval($tid) . "' AND `uid` = '" . intval($_SESSION['uid']) . "' LIMIT 1" ;
  1163. if( !$data = get_line( $sql ))
  1164. return $this->send_error( LR_API_FORBIDDEN , 'YOU CANNOT UPDATE OTHERS TODO' );
  1165. // 判断最后更新时间
  1166. //
  1167. // 服务器的最后操作时间 $data['last_action_at']
  1168. // 本地todo的最后操作时间
  1169. //
  1170. $client_last_action_at = z(t(v('last_action_at')));
  1171. if( not_empty( $data['last_action_at'] ) && not_empty( $client_last_action_at ) )
  1172. {
  1173. if( not_empty(v('client_now')) )
  1174. {
  1175. $offset = time() - strtotime( v('client_now') ) ;
  1176. }else $offset = 0;
  1177. // 客户端时间校正
  1178. // 你不能穿越时空
  1179. if( strtotime( v('last_action_at') ) > strtotime( v('client_now') ) )
  1180. $offset = 0;
  1181. if( strtotime( $client_last_action_at ) - strtotime( $data['last_action_at']) + $offset <= 0 )
  1182. return $this->send_result( array( 'msg' => 'new action happend' ) );
  1183. }
  1184. // update
  1185. if( intval(v('is_delete')) == 1 )
  1186. {
  1187. // remove
  1188. $_REQUEST['tid'] = $tid;
  1189. return $this->todo_remove();
  1190. }
  1191. else
  1192. {
  1193. // update
  1194. // 先更新todo表
  1195. $sql = "UPDATE `todo` SET `content` = '" . s($content) . "' WHERE `id` = '" . intval($tid) . "' LIMIT 1";
  1196. run_sql( $sql );
  1197. $sql = "UPDATE `todo_user` SET
  1198. `is_star` = '" . intval( v('is_star') ) . "',
  1199. `is_public` = '" . intval( v('is_public') ) . "',
  1200. `status` = '" . intval( v('status') ) . "',
  1201. `last_action_at` = NOW() WHERE `tid` = '" . intval($tid) . "' AND `uid` = '" . intval($_SESSION['uid']) . "' LIMIT 1";
  1202. run_sql( $sql );
  1203. return $this -> send_result(get_todo_info_by_id( $tid , true ));
  1204. }
  1205. }
  1206. }
  1207. /**
  1208. * 发布广播
  1209. *
  1210. * 广播时如果不用@进行点名,则通知全部成员
  1211. *
  1212. * @param string text , 必填
  1213. * @param string type - user行为/主动广播 , 默认为主动广播
  1214. * @return todo array
  1215. * @author EasyChen
  1216. */
  1217. public function feed_publish()
  1218. {
  1219. $content = z(t(v('text')));
  1220. if( !not_empty($content) ) return $this->send_error( LR_API_ARGS_ERROR , 'TEXT CAN\'T EMPTY' );
  1221. $reblog_id = intval(v('fid'));
  1222. switch( z(t(v('type'))) )
  1223. {
  1224. case 'user' :
  1225. $type = 3;
  1226. break;
  1227. case 'todo' :
  1228. $type = 2;
  1229. break;
  1230. case 'notice' :
  1231. $type = 1;
  1232. break;
  1233. case 'cast' :
  1234. default:
  1235. $type = 4;
  1236. }
  1237. $sql = "INSERT INTO `feed` ( `content` , `reblog_id` , `uid` , `timeline` , `type` ) VALUES ( '" . s($content) . "' , '" . intval( $reblog_id ) . "' , '" . intval( $_SESSION['uid'] ) . "' , NOW() , " . intval($type) . " )";
  1238. run_sql( $sql );
  1239. if( db_errno() != 0 )
  1240. return $this -> send_error( LR_API_DB_ERROR , 'DATABASE ERROR ' . db_error() );
  1241. $lid = last_id();
  1242. if( intval($lid) < 1 )
  1243. return $this -> send_error( LR_API_DB_ERROR , 'DATABASE ERROR NO LASTID' );
  1244. if($feed = get_feed_by_id( $lid , db() ))
  1245. {
  1246. // feed 发布成功
  1247. // 当用户主动发布时,视为广播,检测at信息
  1248. if( $type == 4 )
  1249. {
  1250. if( $ats = find_at($content) )
  1251. {
  1252. $sql = "SELECT `id` FROM `user` WHERE ";
  1253. foreach( $ats as $at )
  1254. {
  1255. $at =z(t($at));
  1256. if( mb_strlen($at, 'UTF-8') < 2 ) continue;
  1257. $wsql[] = " `name` = '" . s(t($at)) . "' ";
  1258. if( c('at_short_name') )
  1259. if( mb_strlen($at, 'UTF-8') == 2 )
  1260. $wsql[] = " `name` LIKE '_" . s($at) . "' ";
  1261. }
  1262. if( isset( $wsql ) && is_array( $wsql ) )
  1263. {
  1264. $sql = $sql . join( ' OR ' , $wsql );
  1265. if( $udata = get_data( $sql ) )
  1266. foreach( $udata as $uitem )
  1267. $myuids[] = $uitem['id'];
  1268. if( isset( $myuids ) && is_array($myuids) )
  1269. {
  1270. $myuids = array_unique($myuids);
  1271. foreach( $myuids as $muid )
  1272. if( $muid != uid() )
  1273. send_notice( $muid , uname().'在广播【'.$content.'】中@了你' , 2 , array('fid'=>intval($lid) ));
  1274. }
  1275. }
  1276. }
  1277. else
  1278. {
  1279. // 如果没有at,则认为是@全部人
  1280. $sql = "SELECT `id` FROM `user` WHERE `id` !=" . intval(uid());
  1281. if( $udata = get_data( $sql ) )
  1282. {
  1283. foreach( $udata as $uitem )
  1284. $myuids[] = $uitem['id'];
  1285. if( isset( $myuids ) && is_array($myuids) )
  1286. {
  1287. $myuids = array_unique($myuids);
  1288. foreach( $myuids as $muid )
  1289. if( $muid != uid() )
  1290. send_notice( $muid, uname().'发起了广播【'.$content.'】' , 2 , array('fid'=>intval($lid) ));
  1291. }
  1292. }
  1293. }
  1294. }
  1295. return $this->send_result( $feed );
  1296. }
  1297. else
  1298. {
  1299. return $this -> send_error( LR_API_DB_ERROR , 'DATABASE ERROR ' . db_error() );
  1300. }
  1301. }
  1302. /**
  1303. * 获取Feed列表
  1304. *
  1305. *
  1306. * @param string token , 必填
  1307. * @param string since_id - 最小TODO id
  1308. * @param string max_id - 最大TODO id
  1309. * @param string count - 每页TODO条数
  1310. * @param string ord - 排序 , asc 或者 desc
  1311. * @param string by - 排序字段
  1312. * @return feed list array
  1313. * @author EasyChen
  1314. */
  1315. public function feed_list()
  1316. {
  1317. $since_id = intval( v( 'since_id' ) );
  1318. $max_id = intval( v( 'max_id' ) );
  1319. $count = intval( v( 'count' ) );
  1320. $order = strtolower( z( t( v( 'ord' ) ) ) );
  1321. $by = strtolower( z( t( v( 'by' ) ) ) );
  1322. if( strlen($by) < 1 ) $by = 'id';
  1323. if( $order == 'asc' )
  1324. $ord = ' ASC ';
  1325. else
  1326. $ord = ' DESC ';
  1327. if( strlen( $by ) > 0 )
  1328. {
  1329. $osql = ' ORDER BY `' . s( $by ) . '` ' . $ord . ' ';
  1330. }
  1331. else
  1332. $osql = '';
  1333. if( $count < 1 ) $count = 10;
  1334. if( $count > 100 ) $count = 100;
  1335. if( $since_id > 0 )
  1336. {
  1337. $wsql = " AND `id` > '" . intval( $since_id ) . "' ";
  1338. }
  1339. elseif( $max_id > 0 )
  1340. {
  1341. $wsql = " AND `id` < '" . intval( $max_id ) . "' ";
  1342. }
  1343. $sql = "SELECT * FROM `feed` WHERE 1 ";
  1344. $sql = $sql . $wsql . $osql . " LIMIT " . $count ;
  1345. if( !$data = get_data( $sql ))
  1346. {
  1347. if( db_errno() == 0 )
  1348. return $this -> send_error( LR_API_DB_EMPTY_RESULT , 'DATA NOT EXISTS' );
  1349. else
  1350. return $this -> send_error( LR_API_DB_ERROR , 'DATABASE ERROR ' . db_error() );
  1351. }
  1352. else
  1353. {
  1354. $more = 1;
  1355. if( is_array( $data ) )
  1356. {
  1357. if( count($data) < $count ) $more = 0;
  1358. $first = reset( $data );
  1359. $max = $min = $first['id'];
  1360. foreach( $data as $hitem )
  1361. {
  1362. $huids[] = $hitem['uid'];
  1363. if( $hitem['id'] > $max ) $max = $hitem['id'];
  1364. if( $hitem['id'] < $min ) $min = $hitem['id'];
  1365. }
  1366. }
  1367. if( isset( $huids ) && is_array( $huids ) )
  1368. {
  1369. $sql = "SELECT " . USER_INFO . " FROM `user` WHERE `id` IN ( " . join( ' , ' , $huids ) . " ) ";
  1370. if($udata = get_data( $sql ))
  1371. {
  1372. foreach( $udata as $uitem )
  1373. {
  1374. $uarray[$uitem['id']] = $uitem;
  1375. }
  1376. //print_r( $uarray );
  1377. if( isset( $uarray ) )
  1378. {
  1379. foreach( $data as $k=>$hitem )
  1380. {
  1381. if( isset( $uarray[$hitem['uid']] ) )
  1382. $data[$k]['user'] = $uarray[$hitem['uid']];
  1383. }
  1384. }
  1385. }
  1386. }
  1387. return $this->send_result( array( 'max' => intval($max) , 'min' => intval($min) , 'items' => $data , 'more'=> intval( $more ) ) );
  1388. }
  1389. }
  1390. /**
  1391. * 删除Feed的评论
  1392. *
  1393. *
  1394. * @param string token , 必填
  1395. * @param string cid - 必填
  1396. * @return feed array
  1397. * @author EasyChen
  1398. */
  1399. public function feed_remove_comment( $cid = flase )
  1400. {
  1401. $cid = intval(v('cid'));
  1402. if( intval( $cid ) < 1 ) return $this->send_error( LR_API_ARGS_ERROR , 'HCD NOT EXISTS' );
  1403. $sql = "SELECT *,`id` as `cid` FROM `comment` WHERE `id` = '" . intval( $cid ) . "' LIMIT 1";
  1404. if( !$citem = get_line( $sql ) )
  1405. {
  1406. if( db_errno() != 0 )
  1407. return $this->send_error( LR_API_DB_ERROR , 'DATABASE ERROR ' . mysql_error() );
  1408. else
  1409. return $this->send_error( LR_API_DB_EMPTY_RESULT , 'DATA NOT EXISTS' );
  1410. }
  1411. else
  1412. {
  1413. if( ($citem['uid'] != $_SESSION['uid']) && $_SESSION['level'] < 9 )
  1414. {
  1415. return $this->send_err

Large files files are truncated, but you can click here to view the full file