PageRenderTime 61ms CodeModel.GetById 19ms RepoModel.GetById 1ms app.codeStats 0ms

/controller/api.class.php

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

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