PageRenderTime 72ms CodeModel.GetById 20ms RepoModel.GetById 1ms app.codeStats 0ms

/controller/api.class.php

https://github.com/nigelbaor/TeamToy
PHP | 2847 lines | 1587 code | 611 blank | 649 comment | 449 complexity | 954cd926360ca611ed4d81755197b24d 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 , __('INPUT_CHECK_BAD_ARGS' , 'NAME' ) );
  73. if( !is_email( v( 'email' ) ) ) return self::send_error( LR_API_ARGS_ERROR , __('INPUT_CHECK_BAD_EMAIL') );
  74. if( strlen( v( 'password' ) ) < 1 ) return self::send_error( LR_API_ARGS_ERROR , __('INPUT_CHECK_BAD_ARGS' , 'PASSWORD' ) );// 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 , __('INPUT_CHECK_BAD_ARGS' , 'CODE' ) );
  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 , __('INPUT_CHECK_BAD_ACTVECODE') );
  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 , __('INPUT_CHECK_EMAIL_EXISTS') );
  94. $dsql = array();
  95. $dsql[] = "'" . s( v( 'name' ) ) . "'";
  96. $dsql[] = "'" . s( pinyin(strtolower(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 , __('API_MESSAGE_DATABASE_ERROR') . db_error() );
  105. }
  106. $lid = last_id();
  107. if( $lid < 1 )
  108. {
  109. return self::send_error( LR_API_DB_ERROR , __('API_MESSAGE_DATABASE_ERROR') . db_error() );
  110. }
  111. if( !$data = get_user_info_by_id( $lid ) )
  112. return self::send_error( LR_API_DB_ERROR , __('API_MESSAGE_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( __( 'API_TEXT_JOINT_TEAMTOY' , $data['name'] ) , $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 , __('API_MESSAGE_ONLY_ADMIN') );
  138. $uid = intval(v('uid'));
  139. if( $uid < 1 ) return self::send_error( LR_API_ARGS_ERROR , __('INPUT_CHECK_BAD_ARGS' , 'UID' ) );
  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 , __('API_MESSAGE_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 = __( 'API_TEXT_NEW_VERSION' , $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 , __('API_MESSAGE_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 , __('API_MESSAGE_BAD_ACCOUNT') );
  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 , __('API_MESSAGE_ONLY_ADMIN') );
  287. $uid = intval(v('uid'));
  288. if( $uid < 1 ) return self::send_error( LR_API_ARGS_ERROR , __('INPUT_CHECK_BAD_ARGS' , 'UID' ) );
  289. if( $uid == uid() ) return self::send_error( LR_API_ARGS_ERROR , __('API_MESSAGE_CANNOT_RESET_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 , __('API_MESSAGE_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 , __('API_MESSAGE_ONLY_ADMIN') );
  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 , __('API_MESSAGE_UPGARDE_INFO_DATA_ERROR') );
  317. $url = t($info['url']);
  318. $vid = intval($info['version']);
  319. if( $vid < 1 ) return self::send_error( LR_API_UPGRADE_ERROR , __('API_MESSAGE_UPGARDE_INFO_DATA_ERROR') );
  320. if( $vid == local_version() )
  321. {
  322. return self::send_error( LR_API_UPGRADE_ABORT , __('API_MESSAGE_UPGARDE_ALREADY_LATEST') );
  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() , __('API_TEXT_ALREADY_UPGARDE_TO' , array ( $vid , c('site_url') . $pscript) ), 0 );
  338. return self::send_result( array('msg'=>'ok','post_script'=>$pscript) );
  339. }
  340. else
  341. return self::send_error( LR_API_UPGRADE_ERROR , __('API_MESSAGE_UPGARDE_FILE_UNZIP_ERROR') );
  342. }
  343. else
  344. {
  345. return self::send_error( LR_API_UPGRADE_ERROR , __('API_MESSAGE_UPGARDE_FILE_FETCH_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 , __('INPUT_CHECK_BAD_ARGS' , 'UID' ) );
  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 , __('INPUT_CHECK_BAD_ARGS' , 'EMAIL' ) );
  388. if( !not_empty($mobile) ) return self::send_error( LR_API_ARGS_ERROR , __('INPUT_CHECK_BAD_ARGS' , 'MOBILE' ) );
  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 , __('API_MESSAGE_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 , __('API_MESSAGE_FETCH_SETTINGS_DATA_ERROR') );
  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 , __('API_MESSAGE_CANNOT_CHANGE_PASSWORD') );
  427. $opassword = z(t(v('opassword')));
  428. if( !not_empty($opassword) ) return self::send_error( LR_API_ARGS_ERROR , __('INPUT_CHECK_BAD_ARGS' , 'OPASSWORD' ) );
  429. $password = z(t(v('password')));
  430. if( !not_empty($password) ) return self::send_error( LR_API_ARGS_ERROR , __('INPUT_CHECK_BAD_ARGS' , 'PASSWORD' ) );
  431. if( $opassword == $password ) return self::send_error( LR_API_ARGS_ERROR , __('API_MESSAGE_SAME_PASSWORD') );
  432. $passwordv1 = md5( $opassword );
  433. $passwordv2 = ttpassv2( $opassword , uid() );
  434. $sql = "SELECT COUNT(*) FROM `user` WHERE `id` = '" . intval( uid() ) . "' AND ( `password` = '" . s($passwordv1) . "' OR `password` = '" . s($passwordv2) . "' ) ";
  435. if( get_var( $sql ) < 1 )
  436. return self::send_error( LR_API_ARGS_ERROR , __('API_MESSAGE_BAD_OPASSWORD') );
  437. $newpass = ttpassv2( $password , uid() );
  438. $sql = "UPDATE `user` SET `password` = '" . s($newpass) . "' WHERE `id` = '" . intval( uid() ) . "' AND ( `password` = '" . s($passwordv1) . "' OR `password` = '" . s($passwordv2) . "' ) LIMIT 1";
  439. run_sql( $sql );
  440. if( db_errno() != 0 )
  441. return self::send_error( LR_API_DB_ERROR , __('API_MESSAGE_DATABASE_ERROR') . db_error() );
  442. else
  443. return self::send_result( array('msg'=>'ok') );
  444. }
  445. /**
  446. * 更新用户扩展设置
  447. *
  448. * @ignore
  449. */
  450. function user_update_settings()
  451. {
  452. $key = z(t(v('key')));
  453. if( !not_empty($key) ) return self::send_error( LR_API_ARGS_ERROR , __('INPUT_CHECK_BAD_ARGS' , 'KEY' ) );
  454. if(!$value = unserialize(v('value')))
  455. {
  456. $value = z(t(v('value')));
  457. if( !not_empty($value) ) return self::send_error( LR_API_ARGS_ERROR , __('INPUT_CHECK_BAD_ARGS' , 'VALUE' ) );
  458. }
  459. else
  460. {
  461. if( !is_array($value) ) return self::send_error( LR_API_ARGS_ERROR , __('INPUT_CHECK_BAD_ARGS' , 'VALUE' ) );
  462. }
  463. if(!is_array( $settings = get_user_settings_by_id( $_SESSION['uid'] ) ))
  464. return self::send_error( LR_API_DB_ERROR , __('API_MESSAGE_FETCH_SETTINGS_DATA_ERROR') );
  465. else
  466. {
  467. $settings[$key] = $value;
  468. update_user_settings_array( $settings );
  469. if( db_errno() != 0 )
  470. return self::send_error( LR_API_DB_ERROR , __('API_MESSAGE_DATABASE_ERROR') . db_error() );
  471. else
  472. return self::send_result( $settings );
  473. }
  474. }
  475. /**
  476. * 更新用户等级
  477. *
  478. * 必须是管理员的token,level9为管理员,不能修改自己的等级
  479. *
  480. * @param string token , 必填
  481. * @param string uid , 必填
  482. * @return user array
  483. * @author EasyChen
  484. */
  485. function user_level()
  486. {
  487. $uid = intval(v('uid'));
  488. if( $uid < 1 ) return self::send_error( LR_API_ARGS_ERROR , __('INPUT_CHECK_BAD_ARGS' , 'UID' ) );
  489. if( $uid == uid() ) return self::send_error( LR_API_ARGS_ERROR , __('API_MESSAGE_CANNOT_CHANGE_OWN_LEVEL') );
  490. if(!$user = get_user_info_by_id( $uid ))
  491. return self::send_error( LR_API_ARGS_ERROR , __('API_MESSAGE_USER_NOT_EXISTS') );
  492. $level = intval(v('level'));
  493. if( $_SESSION['level'] != '9' )
  494. return self::send_error( LR_API_FORBIDDEN , __('API_MESSAGE_ONLY_ADMIN') );
  495. if( $level == 0 ) $more = " , `is_closed` = 1 ";
  496. else $more = "";
  497. $sql = "UPDATE `user` SET `level` = '" . intval( $level ) . "' " . $more . " WHERE `id` = '" . intval($uid) . "' LIMIT 1";
  498. run_sql( $sql );
  499. if( db_errno() != 0 )
  500. return self::send_error( LR_API_DB_ERROR , __('API_MESSAGE_DATABASE_ERROR') . db_error() );
  501. else
  502. {
  503. if( $level == 0 )
  504. {
  505. publish_feed( __('API_MESSAGE_ACCOUNT_CLOSED' , array( uname() , $user['name'] ) ) , uid() , 1 );
  506. $user['level'] = 0;
  507. return self::send_result( $user );
  508. }
  509. else
  510. {
  511. // uname().'修改了账号【'. $user['name'] .'】权限为'.$level
  512. if( $level == 0 ) $level_text = __('ACCOUNT_CLOSED');
  513. elseif( $level == 9 ) $level_text = __('ACCOUNT_SUPER_ADMIN');
  514. else $level_text = $level;
  515. publish_feed( __('API_MESSAGE_USER_LEVEL_UPDATED' , array( uname() , $user['name'] , $level_text ) ) , uid() , 1 );
  516. return self::send_result( get_user_info_by_id($uid) );
  517. }
  518. }
  519. }
  520. /**
  521. * 关闭用户
  522. *
  523. * 必须是管理员的token
  524. *
  525. * @param string token , 必填
  526. * @param string uid , 必填
  527. * @return user array
  528. * @author EasyChen
  529. */
  530. function user_close()
  531. {
  532. $uid = intval(v('uid'));
  533. if( $uid < 1 ) return self::send_error( LR_API_ARGS_ERROR , __('INPUT_CHECK_BAD_ARGS' , 'UID' ) );
  534. if(!$user = get_user_info_by_id( $uid ))
  535. return self::send_error( LR_API_ARGS_ERROR , __('API_MESSAGE_USER_NOT_EXISTS') );
  536. if( $_SESSION['level'] != '9' )
  537. return self::send_error( LR_API_FORBIDDEN , __('API_MESSAGE_ONLY_ADMIN') );
  538. if( $user['is_closed'] == '1' )
  539. return self::send_error( LR_API_USER_CLOSED , __('API_MESSAGE_USER_CLOSED_BY_ADMIN') );
  540. if( $_SESSION['level'] == '9' && $uid == uid() )
  541. {
  542. $admin_num = get_var( "SELECT COUNT(*) FROM `user` WHERE `is_closed` = 0 AND `level` = 9 " );
  543. if( $admin_num < 2 ) return self::send_error( LR_API_FORBIDDEN , __('API_MESSAGE_CANNOT_CLOSE_ONLY_ADMIN') );
  544. }
  545. close_user_by_id($uid);
  546. if( db_errno() != 0 )
  547. return self::send_error( LR_API_DB_ERROR , __('API_MESSAGE_DATABASE_ERROR') . db_error() );
  548. else
  549. {
  550. publish_feed( __('API_MESSAGE_ACCOUNT_CLOSED' , array( uname() , $user['name'] ) ) , uid() , 1 );
  551. return self::send_result( $user );
  552. }
  553. }
  554. /**
  555. * 添加TODO
  556. *
  557. *
  558. * @param string token , 必填
  559. * @param string text - TODO内容 , 必填
  560. * @param string is_public - 是否公开 , 默认为1
  561. * @param string uid - 要给添加TODO的用户id , uid为0时添加给自己。私有TODO不能添加给其他人
  562. * @return todo array
  563. * @author EasyChen
  564. */
  565. public function todo_add()
  566. {
  567. $content = z(t(v('text')));
  568. if( !not_empty($content) ) return self::send_error( LR_API_ARGS_ERROR , __('INPUT_CHECK_BAD_ARGS' , 'TEXT' ) );
  569. $is_public = intval(v('is_public'));
  570. if( $is_public != 0 ) $is_public = 1;
  571. $uid = intval(v('uid'));
  572. $owner_uid=$uid>0?$uid:uid();
  573. // 检查是否已经存在
  574. $sql = "SELECT * FROM `todo` WHERE `content` = '" . s( $content ) . "' AND `owner_uid` = '" . intval($owner_uid) . "' LIMIT 1";
  575. if( $todo = get_line($sql) )
  576. {
  577. if( get_var( "SELECT COUNT(*) FROM `todo_user` WHERE `tid` = '" . intval( $todo['id'] ) . "' AND `uid` = '" . intval( $owner_uid ) . "' AND `status` != 3 " ) > 0 )
  578. return self::send_error( LR_API_ARGS_ERROR , __('API_MESSAGE_TODO_EXISTS') );
  579. }
  580. if( !$tid = add_todo( $content , $is_public ))
  581. {
  582. return self::send_error( LR_API_DB_ERROR , __('API_MESSAGE_DATABASE_ERROR') . db_error() );
  583. }
  584. $tinfo = get_todo_info_by_id( $tid );
  585. if( $is_public == 1 )
  586. {
  587. if( $uid > 0 && $uid !=uid() )
  588. {
  589. $this->todo_assign( $tid , $uid , true );
  590. $tinfo['other'] = 1;
  591. }
  592. else
  593. publish_feed( __('API_TEXT_TODO_ADDED' , array( uname() , $content ) ) , uid() , 2 , $tid );
  594. // .'添加了TODO【'. .'】'
  595. }
  596. return self::send_result( $tinfo );
  597. }
  598. /**
  599. * 删除TODO评论
  600. *
  601. *
  602. * @param string token , 必填
  603. * @param string hid - 评论id, 必填
  604. * @return comment array
  605. * @author EasyChen
  606. */
  607. public function todo_remove_comment()
  608. {
  609. $hid = intval(v('hid'));
  610. if( intval( $hid ) < 1 ) return self::send_error( LR_API_ARGS_ERROR , __('INPUT_CHECK_BAD_ARGS' , 'HID') );
  611. $sql = "SELECT *,`id` as `hid` FROM `todo_history` WHERE `id` = '" . intval( $hid ) . "' LIMIT 1";
  612. if( !$hitem = get_line( $sql ) )
  613. {
  614. if( db_errno() != 0 )
  615. return self::send_error( LR_API_DB_ERROR , __('API_MESSAGE_DATABASE_ERROR') . mysql_error() );
  616. else
  617. return self::send_error( LR_API_DB_EMPTY_RESULT , __( 'API_MESSAGE_EMPTY_RESULT_DATA' ) );
  618. }
  619. else
  620. {
  621. if( ($hitem['uid'] != $_SESSION['uid']) && $_SESSION['level'] < 9 )
  622. {
  623. return self::send_error( LR_API_FORBIDDEN , __('API_MESSAGE_CANNOT_REMOVE_OTHERS_COMMENT') );
  624. }
  625. if( $hitem['type'] != 2 )
  626. {
  627. return self::send_error( LR_API_ARGS_ERROR , __('INPUT_CHECK_BAD_HTYPE') );
  628. }
  629. $sql = "DELETE FROM `todo_history` WHERE `id` = '" . intval($hid) . "' LIMIT 1";
  630. run_sql( $sql );
  631. if( db_errno() != 0 )
  632. return self::send_error( LR_API_DB_ERROR , __('API_MESSAGE_DATABASE_ERROR') . mysql_error() );
  633. else
  634. {
  635. // 更新todo 评论计数
  636. $tid = $hitem['tid'];
  637. $count = get_var( "SELECT COUNT(*) FROM `todo_history` WHERE `tid` = '" . intval($tid) . "' AND `type` = 2 " , db()) ;
  638. $sql = "UPDATE `todo` SET `comment_count` = '" . intval($count) . "' WHERE `id` = '" . intval($tid) . "' LIMIT 1";
  639. run_sql( $sql );
  640. $sql = "UPDATE `feed` SET `comment_count` = '" . intval( $count ) . "' WHERE `tid` = '" . intval( $tid ) . "' AND `comment_count` != '" . intval( $count ) . "' ";
  641. run_sql( $sql );
  642. return self::send_result( $hitem );
  643. }
  644. }
  645. }
  646. /**
  647. * 为TODO添加评论
  648. *
  649. *
  650. * @param string token , 必填
  651. * @param string tid - TODOid, 必填
  652. * @param string text - 评论内容, 必填
  653. * @return comment array
  654. * @author EasyChen
  655. */
  656. public function todo_add_comment()
  657. {
  658. $content = z(t(v('text')));
  659. if( !not_empty($content) ) return self::send_error( LR_API_ARGS_ERROR , __('INPUT_CHECK_BAD_ARGS' , 'TEXT') );
  660. $tid = intval(v('tid'));
  661. if( intval( $tid ) < 1 ) return self::send_error( LR_API_ARGS_ERROR , __('INPUT_CHECK_BAD_ARGS' , 'TID') );
  662. $tinfo = get_line("SELECT * FROM `todo` WHERE `id` = '" . intval( $tid ) . "' LIMIT 1");
  663. if( is_mobile_request() ) $device = 'mobile';
  664. else $device = 'web';
  665. $sql = "INSERT INTO `todo_history` ( `tid` , `uid` , `content` , `type` , `timeline` , `device` )
  666. VALUES ( '" . intval($tid) . "' , '" . intval($_SESSION['uid']) . "' , '" . s( $content ) . "' , '2' , NOW() , '" . s($device) . "' ) ";
  667. run_sql( $sql );
  668. if( db_errno() != 0 )
  669. return self::send_error( LR_API_DB_ERROR , __('API_MESSAGE_DATABASE_ERROR') . mysql_error() );
  670. else
  671. {
  672. $lid = last_id();
  673. // 更新todo 评论计数
  674. $count = get_var( "SELECT COUNT(*) FROM `todo_history` WHERE `tid` = '" . intval($tid) . "' AND `type` = 2 " , db()) ;
  675. $sql = "UPDATE `todo` SET `comment_count` = '" . intval($count) . "' WHERE `id` = '" . intval($tid) . "' LIMIT 1";
  676. run_sql( $sql );
  677. $sql = "UPDATE `feed` SET `comment_count` = '" . intval( $count ) . "' WHERE `tid` = '" . intval( $tid ) . "' AND `comment_count` != '" . intval( $count ) . "' ";
  678. run_sql( $sql );
  679. // 向订阅todo的同学发送通知
  680. $sql = "SELECT `uid` FROM `todo_user` WHERE `tid`= '" . intval($tid) . "' AND `is_follow` = 1 ";
  681. $follow_uids = array();
  682. if( $uitems = get_data( $sql ) )
  683. foreach( $uitems as $uitem )
  684. {
  685. if( $uitem['uid'] != uid() )
  686. {
  687. if( !in_array( $uitem['uid'] , $follow_uids ) )
  688. {
  689. // .'评论了你关注的TODO【'. $tinfo['content'] .'】: '.$content
  690. send_notice( $uitem['uid'] , __('API_TEXT_COMMENT_TODO_FOLLOWED' , array( uname() , $tinfo['content'] , $content ) ) , 1 , array('tid'=>intval($tid) , 'count' => $count ) );
  691. $follow_uids[] = $uitem['uid'];
  692. }
  693. }
  694. }
  695. // 向todo作者发通知
  696. if( $tinfo['owner_uid'] != uid() )
  697. {
  698. if( !in_array( $tinfo['owner_uid'] , $follow_uids ) )
  699. send_notice( $tinfo['owner_uid'] , __('API_TEXT_COMMENT_TODO_OWNED' , array( uname() , $tinfo['content'] , $content ) ) , 1 , array('tid'=>intval($tid) , 'count' => $count ) );
  700. }
  701. // 向被@的同学,发送通知
  702. if( $ats = find_at($content) )
  703. {
  704. $sql = "SELECT `id` FROM `user` WHERE ";
  705. foreach( $ats as $at )
  706. {
  707. $at =z(t($at));
  708. if( $gname = get_group_names() )
  709. {
  710. if( in_array(strtoupper($at),$gname) )
  711. {
  712. if( $ndata = get_group_unames($at) )
  713. foreach( $ndata as $nname )
  714. $names[] = $nname;
  715. }else $names[] = $at;
  716. }
  717. else
  718. {
  719. $names[] = $at;
  720. }
  721. }
  722. foreach( $names as $at )
  723. {
  724. $at =z(t($at));
  725. if( mb_strlen($at, 'UTF-8') < 2 ) continue;
  726. $wsql[] = " `name` = '" . s(t($at)) . "' ";
  727. if( c('at_short_name') )
  728. if( mb_strlen($at, 'UTF-8') == 2 )
  729. $wsql[] = " `name` LIKE '_" . s($at) . "' ";
  730. }
  731. if( isset( $wsql ) && is_array( $wsql ) )
  732. {
  733. $sql = $sql . join( ' OR ' , $wsql );
  734. if( $udata = get_data( $sql ) )
  735. foreach( $udata as $uitem )
  736. if( !in_array( $uitem['id'] , $follow_uids ) )
  737. $myuids[] = $uitem['id'];
  738. if( isset( $myuids ) && is_array($myuids) )
  739. {
  740. $myuids = array_unique($myuids);
  741. foreach( $myuids as $muid )
  742. {
  743. if( $muid != uid() && $muid != $tinfo['owner_uid'] )
  744. send_notice( $muid , __('API_TEXT_AT_IN_TODO_COMMENT' , array( uname() , $tinfo['content'] , $tinfo['content'] ) ) , 1 , array('tid'=>intval($tid) , 'count' => $count ));
  745. }
  746. }
  747. }
  748. }
  749. if( $comment = get_line( "SELECT * FROM `todo_history` WHERE `id` = '" . intval($lid) . "' LIMIT 1" , db() ) )
  750. {
  751. $comment['user'] = get_user_info_by_id( $_SESSION['uid'] );
  752. if($tinfo['is_public'] == 1)
  753. publish_feed( __('API_TEXT_COMMENT_TODO' , array( uname() , $tinfo['content'] , $tinfo['content'] ) ) , uid() , 2 , $tid );
  754. return self::send_result( $comment );
  755. }
  756. else
  757. {
  758. if( db_errno() != 0 )
  759. return self::send_error( LR_API_DB_ERROR , __('API_MESSAGE_DATABASE_ERROR') . mysql_error() );
  760. else
  761. return self::send_error( LR_API_DB_EMPTY_RESULT , __( 'API_MESSAGE_EMPTY_RESULT_DATA' ) );
  762. }
  763. }
  764. }
  765. /**
  766. * 读取TODO详细信息
  767. *
  768. * 其他人的私有TODO会无法读取
  769. *
  770. * @param string token , 必填
  771. * @param string tid - TODOid, 必填
  772. * @return todo array
  773. * @author EasyChen
  774. */
  775. public function todo_detail()
  776. {
  777. $tid = intval(v('tid'));
  778. if( intval( $tid ) < 1 ) return self::send_error( LR_API_ARGS_ERROR , __('INPUT_CHECK_BAD_ARGS' , 'TID') );
  779. if( $tinfo = get_todo_info_by_id( $tid ) )
  780. {
  781. return self::send_result( $tinfo );
  782. }
  783. else
  784. {
  785. if( db_errno() != 0 )
  786. return self::send_error( LR_API_DB_ERROR , __('API_MESSAGE_DATABASE_ERROR') . mysql_error() );
  787. else
  788. return self::send_error( LR_API_DB_EMPTY_RESULT , __( 'API_MESSAGE_EMPTY_RESULT_DATA' ) );
  789. }
  790. }
  791. /**
  792. * 指派TODO给其他人
  793. *
  794. * 不可以分配给自己
  795. *
  796. * @param string token , 必填
  797. * @param string tid - TODOid, 必填
  798. * @param string uid - 要指派的用户id, 必填
  799. * @return todo array
  800. * @author EasyChen
  801. */
  802. public function todo_assign( $tid = false , $uid = false , $in = false )
  803. {
  804. if( !$tid ) $tid = intval(v('tid'));
  805. if( intval( $tid ) < 1 ) return self::send_error( LR_API_ARGS_ERROR , __('INPUT_CHECK_BAD_ARGS' , 'TID') );
  806. if( !$uid ) $uid = intval(v('uid'));
  807. if( intval( $uid ) < 1 ) return self::send_error( LR_API_ARGS_ERROR , __('INPUT_CHECK_BAD_ARGS' , 'UID') );
  808. if( $uid == $_SESSION['uid'] ) return self::send_error( LR_API_ARGS_ERROR , __('API_MESSAGE_TODO_ASSIGN_TO_SELF') );
  809. if( !$tinfo = get_line( "SELECT * FROM `todo_user` WHERE `tid` = '" . intval($tid) . "' AND `uid` = '" . uid() . "' LIMIT 1" ) )
  810. {
  811. if( db_errno() != 0 )
  812. return self::send_error( LR_API_DB_ERROR , __('API_MESSAGE_DATABASE_ERROR') . mysql_error() );
  813. else
  814. return self::send_error( LR_API_DB_EMPTY_RESULT , __( 'API_MESSAGE_EMPTY_RESULT_DATA' ) );
  815. }
  816. else
  817. {
  818. if( $tinfo['uid'] != uid() ) return self::send_error( LR_API_FORBIDDEN , __('API_MESSAGE_CANNOT_ASSIGN_OTHERS_TODO') );
  819. // 更新todo表
  820. $sql = "UPDATE `todo` SET `owner_uid` = '" . intval( $uid ) . "' WHERE `id` = '" . intval($tid) . "' LIMIT 1";
  821. run_sql( $sql );
  822. if( db_errno() != 0 )
  823. if( $in )
  824. return false;
  825. else
  826. return self::send_error( LR_API_DB_ERROR , __('API_MESSAGE_DATABASE_ERROR') . mysql_error() );
  827. // 将新的uid加入 todo_user 表
  828. $sql = "REPLACE INTO `todo_user` ( `uid` , `tid` , `status` , `last_action_at` ) VALUES ( '" . intval( $uid ) . "' , '" . intval( $tid ) . "' , 1 , NOW() ) ";
  829. run_sql( $sql );
  830. if( db_errno() != 0 )
  831. if( $in )
  832. return false;
  833. else
  834. return self::send_error( LR_API_DB_ERROR , __('API_MESSAGE_DATABASE_ERROR') . mysql_error() );
  835. // 将现有uid 变为follow状态
  836. $sql = "UPDATE `todo_user` SET `is_follow` = 1 WHERE `tid` = '" . intval($tid) . "' AND `uid` = '" . intval($_SESSION['uid']) . "' LIMIT 1";
  837. run_sql( $sql );
  838. if( db_errno() != 0 )
  839. if( $in )
  840. return false;
  841. else
  842. return self::send_error( LR_API_DB_ERROR , __('API_MESSAGE_DATABASE_ERROR') . mysql_error() );
  843. // 获取被转让人的信息
  844. $uinfo = get_user_info_by_id($uid);
  845. $todo_text = get_todo_text_by_id( $tid );
  846. $todo_count = get_var( "SELECT `comment_count` FROM `todo` WHERE `id` = '" . intval( $tid ) . "'" );
  847. // 向todo新主人发送通知
  848. send_notice( intval( $uid ) , __('API_TEXT_ASSIGN_TODO_TO_U',array( uname() , $todo_text )) , 1 , array('tid'=>intval($tid) , 'count'=> $todo_count ) );
  849. // 向todo关注者发送通知
  850. $sql = "SELECT `uid` FROM `todo_user` WHERE `tid`= '" . intval($tid) . "' AND `is_follow` = 1 ";
  851. if( $uitems = get_data( $sql ) )
  852. foreach( $uitems as $uitem )
  853. {
  854. // 避免向当前转让人发送通知
  855. if( $uitem['uid'] != uid() )
  856. send_notice( $uitem['uid'] , __('API_TEXT_ASSIGN_TODO_FOLLOWED' , array( uname() , $todo_text , $uinfo['name'] ) ) , 1 , array('tid'=>intval($tid) , 'count'=> $todo_count ) );
  857. }
  858. add_history( $tid , __('API_TEXT_ASSIGN_TODO') );
  859. publish_feed( __('API_TEXT_ASSIGN_TODO_DETAIL' , array( uname() , $todo_text , $uinfo['name'] ) ) , uid() , 2 , $tid );
  860. if( $in )
  861. return get_todo_info_by_id( $tid ) ;
  862. else
  863. return self::send_result( get_todo_info_by_id( $tid ) );
  864. }
  865. }
  866. /**
  867. * 获取TODO列表
  868. *
  869. *
  870. * @param string token , 必填
  871. * @param string since_id - 最小TODO id
  872. * @param string max_id - 最大TODO id
  873. * @param string count - 每页TODO条数
  874. * @param string ord - 排序 , asc 或者 desc
  875. * @param string by - 排序字段
  876. * @param string group - 按分组输出,默认为false
  877. * @return todo list array
  878. * @author EasyChen
  879. */
  880. public function todo_list()
  881. {
  882. $uid = intval(v('uid'));
  883. if( $uid < 1 ) $uid = $_SESSION['uid'];
  884. $since_id = intval( v( 'since_id' ) );
  885. $max_id = intval( v( 'max_id' ) );
  886. $count = intval( v( 'count' ) );
  887. $order = strtolower( z( t( v( 'ord' ) ) ) );
  888. $by = strtolower( z( t( v( 'by' ) ) ) );
  889. if( $order != 'desc' )
  890. $ord = ' ASC ';
  891. else
  892. $ord = ' DESC ';
  893. if( strlen( $by ) > 0 )
  894. {
  895. $osql = ' ORDER BY `' . s( $by ) . '` ' . $ord . ' ';
  896. }
  897. else
  898. $osql = '';
  899. if( $count < 1 ) $count = 10;
  900. if( $count > 100 ) $count = 100;
  901. if( $since_id > 0 )
  902. $wsql = " AND `tid` > '" . intval( $since_id ) . "' ";
  903. elseif( $max_id > 0 )
  904. $wsql = " AND `tid` < '" . intval( $max_id ) . "' ";
  905. else
  906. $wsql = '';
  907. if( $uid != uid() ) $wsql .= ' AND `is_public` = 1 ';
  908. $sql = "SELECT * FROM `todo_user` WHERE `uid` = '" . intval($uid) . "' ";
  909. $sql = $sql . $wsql . $osql . " LIMIT " . $count ;
  910. if( !$data = get_data( $sql ) ) return self::send_error( LR_API_DB_EMPTY_RESULT , __( 'API_MESSAGE_EMPTY_RESULT_DATA' ) );
  911. if( db_errno() != 0 )
  912. return self::send_error( LR_API_DB_ERROR , __('API_MESSAGE_DATABASE_ERROR') );
  913. $tids = array();
  914. foreach( $data as $item )
  915. {
  916. $tids[] = $item['tid'];
  917. $todos[$item['tid']] = $item;
  918. }
  919. if( count( $tids ) > 0 )
  920. {
  921. $sql = "SELECT * FROM `todo` WHERE `id` IN ( " . join( ' , ' , $tids ) . ") ORDER BY FIELD( `id` , " . join( ' , ' , $tids ) . " )";
  922. $todo = get_data( $sql );
  923. foreach( $todo as $t )
  924. {
  925. $todos[$t['id']]['uid'] = $t['owner_uid'];
  926. $todos[$t['id']]['content'] = $t['content'];
  927. $todos[$t['id']]['timeline'] = $t['timeline'];
  928. }
  929. // todo : sort it
  930. if( intval(v('group')) != 1 )
  931. return self::send_result(array_values($todos));
  932. else
  933. {
  934. $ret = Array();
  935. foreach( $todos as $tt )
  936. {
  937. if( $tt['is_follow'] ==1 )
  938. $ret['follow'][] = $tt;
  939. elseif( $tt['status'] == 3 )
  940. $ret['done'][] = $tt;
  941. elseif( $tt['is_star'] == 1 )
  942. $ret['star'][] = $tt;
  943. else
  944. $ret['normal'][] = $tt;
  945. }
  946. return self::send_result($ret);
  947. }
  948. }
  949. else
  950. {
  951. if( db_errno() != 0 )
  952. return self::send_error( LR_API_DB_ERROR , __('API_MESSAGE_DATABASE_ERROR') . mysql_error() );
  953. else
  954. return self::send_error( LR_API_DB_EMPTY_RESULT , __( 'API_MESSAGE_EMPTY_RESULT_DATA' ) );
  955. }
  956. /*
  957. if( $data = get_user_todo_list_by_uid() )
  958. {
  959. return self::send_result( $data );
  960. }
  961. else
  962. {
  963. return self::send_error( LR_API_DB_ERROR , __('API_MESSAGE_DATABASE_ERROR') . db_error() );
  964. }*/
  965. }
  966. /**
  967. * TODO进行中
  968. *
  969. *
  970. * @param string token , 必填
  971. * @param string tid - TODO id , 必填
  972. * @return todo array
  973. * @author EasyChen
  974. */
  975. public function todo_start()
  976. {
  977. return $this->todo_set_value( 'status' , 2 );
  978. }
  979. /**
  980. * TODO暂停
  981. *
  982. *
  983. * @param string token , 必填
  984. * @param string tid - TODO id , 必填
  985. * @return todo array
  986. * @author EasyChen
  987. */
  988. public function todo_pause()
  989. {
  990. return $this->todo_set_value( 'status' , 1 );
  991. }
  992. /**
  993. * TODO加星
  994. *
  995. *
  996. * @param string token , 必填
  997. * @param string tid - TODO id , 必填
  998. * @return todo array
  999. * @author EasyChen
  1000. */
  1001. public function todo_star()
  1002. {
  1003. return $this->todo_set_value( 'is_star' , 1 );
  1004. }
  1005. /**
  1006. * TODO去星
  1007. *
  1008. *
  1009. * @param string token , 必填
  1010. * @param string tid - TODO id , 必填
  1011. * @return todo array
  1012. * @author EasyChen
  1013. */
  1014. public function todo_unstar()
  1015. {
  1016. return $this->todo_set_value( 'is_star' , 0 );
  1017. }
  1018. /**
  1019. * TODO设为公开
  1020. *
  1021. *
  1022. * @param string token , 必填
  1023. * @param string tid - TODO id , 必填
  1024. * @return todo array
  1025. * @author EasyChen
  1026. */
  1027. public function todo_public()
  1028. {
  1029. return $this->todo_set_value( 'is_public' , 1 );
  1030. }
  1031. /**
  1032. * TODO设为私密
  1033. *
  1034. *
  1035. * @param string token , 必填
  1036. * @param string tid - TODO id , 必填
  1037. * @return todo array
  1038. * @author EasyChen
  1039. */
  1040. public function todo_private()
  1041. {
  1042. return $this->todo_set_value( 'is_public' , 0 );
  1043. }
  1044. /**
  1045. * TODO设为已完成
  1046. *
  1047. *
  1048. * @param string token , 必填
  1049. * @param string tid - TODO id , 必填
  1050. * @return todo array
  1051. * @author EasyChen
  1052. */
  1053. public function todo_done()
  1054. {
  1055. return $this->todo_set_value( 'status' , 3 );
  1056. }
  1057. /**
  1058. * 重开TODO
  1059. *
  1060. *
  1061. * @param string token , 必填
  1062. * @param string tid - TODO id , 必填
  1063. * @return todo array
  1064. * @author EasyChen
  1065. */
  1066. public function todo_reopen()
  1067. {
  1068. return $this->todo_set_value( 'status' , 1 );
  1069. }
  1070. /**
  1071. * @ignore
  1072. */
  1073. private function todo_set_value( $field , $value )
  1074. {
  1075. $tid = intval(v('tid'));
  1076. if( $tid < 1 ) return self::send_error( LR_API_ARGS_ERROR , __('INPUT_CHECK_BAD_ARGS','TID') );
  1077. $sql = "SELECT * FROM `todo_user` WHERE `tid` = '" . intval($tid) . "' AND `uid` = '" . intval($_SESSION['uid']) . "' LIMIT 1" ;
  1078. if( !$data = get_line( $sql ))
  1079. return self::send_error( LR_API_FORBIDDEN , __('API_MESSAGE_CANNOT_UPDATE_OTHERS_TODO') );
  1080. // delete uid and limit 1
  1081. // to make all record updated at sametime
  1082. // for all the followers
  1083. $sql = "UPDATE `todo_user` SET `" . s( $field ) . "` = '" . intval( $value ) . "' , `last_action_at` = NOW() WHERE `tid` = '" . intval( $tid ) . "' ";
  1084. run_sql( $sql );
  1085. if( mysql_errno() != 0 )
  1086. return self::send_error( LR_API_DB_ERROR , __('API_MESSAGE_DATABASE_ERROR') . mysql_error() );
  1087. else
  1088. {
  1089. $todoinfo = get_todo_info_by_id( $tid , true );
  1090. kset('dinfo', $todoinfo['details']['is_public'] );
  1091. if( $field == 'status' && $value == 3 )
  1092. {
  1093. if( $todoinfo['details']['is_public'] == 1 )
  1094. {
  1095. // .'完成了TODO【'. .'】'
  1096. publish_feed( __('API_TEXT_FINISH_TODO' , array( uname() , $todoinfo['content'] ) ) , uid() , 2 , $tid );
  1097. // send notice
  1098. // 向订阅todo的同学发送通知
  1099. $sql = "SELECT `uid` FROM `todo_user` WHERE `tid`= '" . intval($tid) . "' AND `is_follow` = 1 ";
  1100. if( $uitems = get_data( $sql ) )
  1101. foreach( $uitems as $uitem )
  1102. {
  1103. if( $uitem['uid'] != uid() )
  1104. send_notice( $uitem['uid'] , __('API_TEXT_FINISH_TODO_FOLLOWED' , array( uname() , $todoinfo['content'] ) ) , 1 , array('tid'=>intval($tid) , 'count' => $todoinfo['comment_count'] ) );
  1105. }
  1106. }
  1107. }
  1108. return self::send_result( $todoinfo );
  1109. }
  1110. }
  1111. /**
  1112. * TODO取消关注
  1113. *
  1114. *
  1115. * @param string token , 必填
  1116. * @param string tid - TODO id , 必填
  1117. * @return todo array
  1118. * @author EasyChen
  1119. */
  1120. public function todo_unfollow()
  1121. {
  1122. $tid = intval(v('tid'));
  1123. if( $tid < 1 ) return self::send_error( LR_API_ARGS_ERROR , __('INPUT_CHECK_BAD_ARGS','TID') );
  1124. $sql = "SELECT * FROM `todo_user` WHERE `tid` = '" . intval($tid) . "' AND `uid` = '" . intval($_SESSION['uid']) . "' LIMIT 1" ;
  1125. if( !$data = get_line( $sql ))
  1126. {
  1127. return self::send_error( LR_API_ARGS_ERROR , __('API_MESSAGE_EMPTY_RESULT_DATA') );
  1128. }
  1129. else
  1130. {
  1131. $sql = "DELETE FROM `todo_user` WHERE `tid` = '" . intval($tid) . "' AND `uid` = '" . intval($_SESSION['uid']) . "' AND `is_follow` = 1 LIMIT 1";
  1132. run_sql( $sql );
  1133. if( db_errno() != 0 )
  1134. return self::send_error( LR_API_DB_ERROR , __('API_MESSAGE_DATABASE_ERROR') . mysql_error() );
  1135. else
  1136. {
  1137. return self::send_result(get_todo_info_by_id( $tid , true ));
  1138. }
  1139. }
  1140. }
  1141. /**
  1142. * TODO添加关注
  1143. *
  1144. *
  1145. * @param string token , 必填
  1146. * @param string tid - TODO id , 必填
  1147. * @return todo array
  1148. * @author EasyChen
  1149. */
  1150. public function todo_follow()
  1151. {
  1152. $tid = intval(v('tid'));
  1153. if( $tid < 1 ) return self::send_error( LR_API_ARGS_ERROR , __('INPUT_CHECK_BAD_ARGS','TID') );
  1154. $sql = "SELECT * FROM `todo_user` WHERE `tid` = '" . intval($tid) . "' AND `uid` = '" . intval($_SESSION['uid']) . "' LIMIT 1" ;
  1155. if( !$data = get_line( $sql ))
  1156. {
  1157. // 没数据正常的
  1158. $sql = "INSERT IGNORE INTO `todo_user` ( `uid` , `tid` , `status` , `is_follow` , `last_action_at` ) VALUES ( '" . intval( $_SESSION['uid'] ) . "' , '" . intval( $tid ) . "' , 1 , 1 , NOW() ) ";
  1159. run_sql( $sql );
  1160. if( db_errno() != 0 )
  1161. return self::send_error( LR_API_DB_ERROR , __('API_MESSAGE_DATABASE_ERROR') . mysql_error() );
  1162. else
  1163. return self::send_result(get_todo_info_by_id( $tid , true ));
  1164. }
  1165. else
  1166. {
  1167. return self::send_error( LR_API_ARGS_ERROR , __('API_MESSAGE_TODO_ALREADY_FOLLOWED') );
  1168. }
  1169. }
  1170. /**
  1171. * TODO更新文字内容
  1172. *
  1173. *
  1174. * @param string token , 必填
  1175. * @param string tid - TODO id , 必填
  1176. * @param string text - TODO内容 , 必填
  1177. * @return todo array
  1178. * @author EasyChen
  1179. */
  1180. public function todo_update()
  1181. {
  1182. $tid = intval(v('tid'));
  1183. if( $tid < 1 ) return self::send_error( LR_API_ARGS_ERROR , __('INPUT_CHECK_BAD_ARGS','TID') );
  1184. // check user
  1185. //$sql = "SELECT * FROM `todo_user` WHERE `tid` = '" . intval($tid) . "' AND `uid` = '" . intval($_SESSION['uid']) . "' LIMIT 1" ;
  1186. $sql = "SELECT * FROM `todo` WHERE `id` = '" . intval($tid) . "' AND `owner_uid` = '" . intval(uid()) . "' LIMIT 1";
  1187. if( !$data = get_line( $sql ))
  1188. return self::send_error( LR_API_FORBIDDEN , __('API_MESSAGE_CANNOT_UPDATE_OTHERS_TODO') );
  1189. $content = z(t(v('text')));
  1190. if( !not_empty($content) ) return self::send_error( LR_API_ARGS_ERROR , __('INPUT_CHECK_BAD_ARGS','TEXT') );
  1191. $sql = "UPDATE `todo` SET `content` = '" . s($content) . "' WHERE `id` = '" . intval($tid) . "' LIMIT 1";
  1192. run_sql( $sql );
  1193. if( mysql_errno() != 0 )
  1194. return self::send_error( LR_API_DB_ERROR , __('API_MESSAGE_DATABASE_ERROR') . mysql_error() );
  1195. else
  1196. {
  1197. run_sql( "UPDATE `todo_user` SET `last_action_at` = NOW() WHERE `tid` = '" . intval($tid) . "' AND `uid` = '" . intval($_SESSION['uid']) . "' LIMIT 1");
  1198. return self::send_result(get_todo_info_by_id( $tid , true ));
  1199. }
  1200. }
  1201. /**
  1202. * 清除已经完成的单个TODO
  1203. *
  1204. *
  1205. * @param string token , 必填
  1206. * @param string tid - TODO id , 必填
  1207. * @return todo array
  1208. * @author EasyChen
  1209. */
  1210. public function todo_remove_done()
  1211. {
  1212. // @TODO clean all the info in other tables
  1213. $sql = "DELETE FROM `todo_user` WHERE `uid` = '" . intval($_SESSION['uid']) . "' AND `status` = 3 " ;
  1214. run_sql( $sql );
  1215. if( mysql_errno() != 0 )
  1216. {
  1217. return self::send_error( LR_API_DB_ERROR , __('API_MESSAGE_DATABASE_ERROR') . mysql_error() );
  1218. }
  1219. else
  1220. return self::send_result( array('msg'=>'ok') );
  1221. }
  1222. /**
  1223. * 清除所有已经完成的TODO标记为
  1224. *
  1225. *
  1226. * @param string token , 必填
  1227. * @param string tid - TODO id , 必填
  1228. * @return todo array
  1229. * @author EasyChen
  1230. */
  1231. public function todo_all_done()
  1232. {
  1233. // @TODO clean all the info in other tables
  1234. $sql = "UPDATE `todo_user` SET `status` = 3 WHERE `uid` = '" . intval($_SESSION['uid']) . "' AND ( `status` = 1 OR `status` = 2 ) " ;
  1235. run_sql( $sql );
  1236. if( mysql_errno() != 0 )
  1237. {
  1238. return self::send_error( LR_API_DB_ERROR , __('API_MESSAGE_DATABASE_ERROR') . mysql_error() );
  1239. }
  1240. else
  1241. return self::send_result( array('msg'=>'ok') );
  1242. }
  1243. /**
  1244. * 删除TODO
  1245. *
  1246. *
  1247. * @param string token , 必填
  1248. * @param string tid - TODO id , 必填
  1249. * @return todo array
  1250. * @author EasyChen
  1251. */
  1252. public function todo_remove()
  1253. {
  1254. $tid = intval(v('tid'));
  1255. if( $tid < 1 ) return self::send_error( LR_API_ARGS_ERROR , __('INPUT_CHECK_BAD_ARGS','TID') );
  1256. $old = get_todo_info_by_id( $tid );
  1257. $sql = "DELETE FROM `todo_user` WHERE `tid` = '" . intval($tid) . "' AND `uid` = '" . intval($_SESSION['uid']) . "' LIMIT 1" ;
  1258. run_sql( $sql );
  1259. if( mysql_errno() != 0 )
  1260. {
  1261. return self::send_error( LR_API_DB_ERROR , __('API_MESSAGE_DATABASE_ERROR') . mysql_error() );
  1262. }
  1263. else
  1264. return self::send_result( $old );
  1265. }
  1266. /**
  1267. * 离线同步TODO
  1268. *
  1269. * 客户端用
  1270. * @ignore
  1271. */
  1272. public function todo_sync()
  1273. {
  1274. // 首先判断text是否存在
  1275. // 然后根据tid 判断是更新还是添加操作
  1276. //
  1277. $content = z(t(v('text')));
  1278. if( !not_empty( $content ) ) return self::send_error( LR_API_ARGS_ERROR , __('INPUT_CHECK_BAD_ARGS','TEXT') );
  1279. $tid = intval(v('tid'));
  1280. if( $tid < 0 )
  1281. {
  1282. if( intval(v('is_delete')) == 1 )
  1283. {
  1284. // 在本地添加后又在本地删除了
  1285. return self::send_result( array( 'msg' => __('API_MESSAGE_TODO_ALREADY_DELETE_LOCALLY') ) );
  1286. }
  1287. // add
  1288. return $this->todo_add();
  1289. }
  1290. else
  1291. {
  1292. // 鉴权
  1293. $sql = "SELECT * FROM `todo_user` WHERE `tid` = '" . intval($tid) . "' AND `uid` = '" . intval($_SESSION['uid']) . "' LIMIT 1" ;
  1294. if( !$data = get_line( $sql ))
  1295. return self::send_error( LR_API_FORBIDDEN , __('API_MESSAGE_CANNOT_UPDATE_OTHERS_TODO') );
  1296. // 判断最后更新时间
  1297. //
  1298. // 服务器的最后操作时间 $data['last_action_at']
  1299. // 本地todo的最后操作时间
  1300. //
  1301. $client_last_action_at = z(t(v('last_action_at')));
  1302. if( not_empty( $data['last_action_at'] ) && not_empty( $client_last_action_at ) )
  1303. {
  1304. if( not_empty(v('client_now')) )
  1305. {
  1306. $offset = time() - strtotime( v('client_now') ) ;
  1307. }else $offset = 0;
  1308. // 客户端时间校正
  1309. // 你不能穿越时空
  1310. if( strtotime( v('last_action_at') ) > strtotime( v('client_now') ) )
  1311. $offset = 0;
  1312. if( strtotime( $client_last_action_at ) - strtotime( $data['last_action_at']) + $offset <= 0 )
  1313. return self::send_result( array( 'msg' => __('API_MESSAGE_TODO_ALREADY_HAD_OTHER_ACTION') ) );
  1314. }
  1315. // update
  1316. if( intval(v('is_delete')) == 1 )
  1317. {
  1318. // remove
  1319. $_REQUEST['tid'] = $tid;
  1320. return $this->todo_remove();
  1321. }
  1322. else
  1323. {
  1324. // update
  1325. // 先更新todo表
  1326. $sql = "UPDATE `todo` SET `content` = '" . s($content) . "' WHERE `id` = '" . intval($tid) . "' LIMIT 1";
  1327. run_sql( $sql );
  1328. $sql = "UPDATE `todo_user` SET
  1329. `is_star` = '" . intval( v('is_star') ) . "',
  1330. `is_public` = '" . intval( v('is_public') ) . "',
  1331. `status` = '" . intval( v('status') ) . "',
  1332. `last_action_at` = NOW() WHERE `tid` = '" . intval($tid) . "' AND `uid` = '" . intval($_SESSION['uid']) . "' LIMIT 1";
  1333. run_sql( $sql );
  1334. return self::se

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