DiscussionController.php 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399
  1. <?php
  2. namespace App\Http\Controllers;
  3. use Illuminate\Support\Facades\Log;
  4. use Illuminate\Http\Request;
  5. use App\Models\Discussion;
  6. use App\Models\Wbw;
  7. use App\Models\WbwBlock;
  8. use App\Models\PaliSentence;
  9. use App\Models\Sentence;
  10. use App\Http\Resources\DiscussionResource;
  11. use App\Http\Api\MdRender;
  12. use App\Http\Api\AuthApi;
  13. use App\Http\Api\Mq;
  14. use App\Http\Controllers\ArticleController;
  15. use App\Http\Api\UserApi;
  16. class DiscussionController extends Controller
  17. {
  18. /**
  19. * Display a listing of the resource.
  20. *
  21. * @return \Illuminate\Http\Response
  22. */
  23. public function index(Request $request)
  24. {
  25. //
  26. $user = AuthApi::current($request);
  27. if($user){
  28. $userInfo = UserApi::getByUuid($user['user_uid']);
  29. }
  30. switch ($request->get('view')) {
  31. case 'question-by-topic':
  32. $topic = Discussion::where('id',$request->get('id'));
  33. $topic->where('status',$request->get('status','active'))
  34. ->select('res_id')->first();
  35. if(!$topic){
  36. return $this->error("无效的id");
  37. }
  38. $table = Discussion::where('res_id',$topic->res_id);
  39. $activeNumber = Discussion::where('res_id',$topic->res_id)
  40. ->where('status','active')->count();
  41. $closeNumber = Discussion::where('res_id',$topic->res_id)
  42. ->where('status','close')->count();
  43. $table->where('status',$request->get('status','active'))
  44. ->where('parent',null);
  45. break;
  46. case 'question':
  47. /**
  48. * 禁止:
  49. * 未注册用户看到任何人发表的discussion
  50. * basic用户看到别人发表的discussion
  51. */
  52. if(!$user && $request->get('type')==='discussion'){
  53. return $this->ok([
  54. "rows" => [],
  55. "count" => 0,
  56. 'active' => 0,
  57. 'close' => 0,
  58. 'can_create' => false,
  59. 'can_reply' => false,
  60. ]);
  61. }
  62. $table = Discussion::where('res_id',$request->get('id'))
  63. ->where('type', $request->get('type','discussion'))
  64. ->where('status',$request->get('status','active'))
  65. ->where('parent',null);
  66. if($request->get('type')==='discussion'){
  67. if(isset($userInfo) && in_array('basic',$userInfo['roles'])){
  68. $table = $table->where('editor_uid',$userInfo['id']);
  69. }
  70. }
  71. $activeNumber = Discussion::where('res_id',$request->get('id'))
  72. ->where('parent',null)
  73. ->where('type', $request->get('type','discussion'))
  74. ->where('status','active')->count();
  75. $closeNumber = Discussion::where('res_id',$request->get('id'))
  76. ->where('parent',null)
  77. ->where('type', $request->get('type','discussion'))
  78. ->where('status','close')->count();
  79. break;
  80. case 'answer':
  81. $table = Discussion::where('parent',$request->get('id'));
  82. $activeNumber = Discussion::where('parent',$request->get('id'))
  83. ->where('status','active')->count();
  84. $closeNumber = Discussion::where('parent',$request->get('id'))
  85. ->where('status','close')->count();
  86. break;
  87. case 'res_id':
  88. /**
  89. * 先获取顶级节点
  90. * 需要确定用户身份,manager查看全部topic 普通用户只显示自己提交的topic
  91. */
  92. $roots = Discussion::where('res_id',$request->get('id'))
  93. ->where('type', $request->get('type','discussion'))
  94. ->whereIn('status',explode(',',$request->get('status','active')) )
  95. ->where('parent',null)
  96. ->select('id')
  97. ->get();
  98. $table = Discussion::where(function ($query) use ($roots) {
  99. $query->whereIn('id' , $roots)
  100. ->orWhereIn('parent', $roots);
  101. });
  102. $activeNumber = Discussion::where('res_id',$request->get('id'))
  103. ->where('type', $request->get('type','discussion'))
  104. ->where('status','active')->count();
  105. $closeNumber = Discussion::where('res_id',$request->get('id'))
  106. ->where('type', $request->get('type','discussion'))
  107. ->where('status','close')->count();
  108. break;
  109. case 'topic-by-user':
  110. /**
  111. * 某用户发表的全部topic
  112. *
  113. */
  114. if(!$user){
  115. return $this->error('',403,403);
  116. }
  117. $table = Discussion::where('editor_uid',$user['user_uid'])
  118. ->where('type', $request->get('type','discussion'))
  119. ->whereIn('status',explode(',',$request->get('status','active')) )
  120. ->where('parent',null);
  121. $activeNumber = Discussion::where('editor_uid',$user['user_uid'])
  122. ->where('parent',null)
  123. ->where('type', $request->get('type','discussion'))
  124. ->where('status','active')->count();
  125. $closeNumber = Discussion::where('editor_uid',$user['user_uid'])
  126. ->where('parent',null)
  127. ->where('type', $request->get('type','discussion'))
  128. ->where('status','close')->count();
  129. break;
  130. case 'all':
  131. $table = Discussion::where('parent',null);
  132. $activeNumber = Discussion::where('parent',null)
  133. ->where('status','active')->count();
  134. $closeNumber = Discussion::where('parent',null)
  135. ->where('status','close')->count();
  136. break;
  137. }
  138. if(!empty($search)){
  139. $table = $table->where('title', 'like', $search."%");
  140. }
  141. $count = $table->count();
  142. $table = $table->orderBy($request->get('order','created_at'),$request->get('dir','desc'));
  143. $table = $table->skip($request->get("offset",0))
  144. ->take($request->get('limit',1000));
  145. $result = $table->get();
  146. $can_create = false;
  147. $can_reply = false;
  148. $user = AuthApi::current($request);
  149. switch ($request->get('type','discussion')) {
  150. case 'qa':
  151. switch ($request->get('res_type')) {
  152. case 'article':
  153. if($user && ArticleController::userCanEditId($user['user_uid'],$request->get('id'))){
  154. $can_create = true;
  155. $can_reply = true;
  156. }
  157. break;
  158. }
  159. break;
  160. case 'help':
  161. switch ($request->get('res_type')) {
  162. case 'article':
  163. if($user){
  164. $can_reply = true;
  165. if(ArticleController::userCanEditId($user['user_uid'],$request->get('id'))){
  166. $can_create = true;
  167. }
  168. }
  169. break;
  170. }
  171. break;
  172. case 'discussion':
  173. if($user){
  174. $can_create = true;
  175. $can_reply = true;
  176. }
  177. break;
  178. }
  179. return $this->ok([
  180. "rows" => DiscussionResource::collection($result),
  181. "count" => $count,
  182. 'active' => $activeNumber,
  183. 'close' => $closeNumber,
  184. 'can_create' => $can_create,
  185. 'can_reply' => $can_reply,
  186. ]);
  187. }
  188. public function discussion_tree(Request $request){
  189. $output = [];
  190. $sentences = $request->get("data");
  191. foreach ($sentences as $key => $sentence) {
  192. # 先查句子信息
  193. $sentInfo = Sentence::where('book_id',$sentence['book'])
  194. ->where('paragraph',$sentence['paragraph'])
  195. ->where('word_start',$sentence['word_start'])
  196. ->where('word_end',$sentence['word_end'])
  197. ->where('channel_uid',$sentence['channel_id'])
  198. ->first();
  199. if($sentInfo){
  200. $sentPr = Discussion::where('res_id',$sentInfo['uid'])
  201. ->whereNull('parent')
  202. ->select('title','children_count','editor_uid')
  203. ->orderBy('created_at','desc')->get();
  204. if(count($sentPr)>0){
  205. $output[] = [
  206. 'sentence' => [
  207. 'book' => $sentInfo->book_id,
  208. 'paragraph' => $sentInfo->paragraph,
  209. 'word_start' => $sentInfo->word_start,
  210. 'word_end' => $sentInfo->word_end,
  211. 'channel_id' => $sentInfo->channel_uid,
  212. 'content' => $sentInfo->content,
  213. 'pr_count' => count($sentPr),
  214. ],
  215. 'pr' => $sentPr,
  216. ];
  217. }
  218. }
  219. }
  220. return $this->ok(['rows'=>$output,'count'=>count($output)]);
  221. }
  222. /**
  223. * Store a newly created resource in storage.
  224. *
  225. * @param \Illuminate\Http\Request $request
  226. * @return \Illuminate\Http\Response
  227. */
  228. public function store(Request $request)
  229. {
  230. $user = AuthApi::current($request);
  231. if(!$user){
  232. Log::error('discussion store auth failed {request}',['request'=>$request]);
  233. return $this->error(__('auth.failed'),[401],401);
  234. }
  235. //
  236. // validate
  237. // read more on validation at http://laravel.com/docs/validation
  238. if($request->has('parent')){
  239. $rules = [];
  240. $parentInfo = Discussion::find($request->get('parent'));
  241. if(!$parentInfo){
  242. return $this->error('no record');
  243. }
  244. }else{
  245. $rules = array(
  246. 'res_id' => 'required',
  247. 'res_type' => 'required',
  248. 'title' => 'required',
  249. );
  250. }
  251. $validated = $request->validate($rules);
  252. $discussion = new Discussion;
  253. if($request->has('parent')){
  254. $discussion->res_id = $parentInfo->res_id;
  255. $discussion->res_type = $parentInfo->res_type;
  256. }else{
  257. $discussion->res_id = $request->get('res_id');
  258. $discussion->res_type = $request->get('res_type');
  259. }
  260. $discussion->type = $request->get('type','discussion');
  261. $discussion->tpl_id = $request->get('tpl_id');
  262. $discussion->title = $request->get('title',null);
  263. $discussion->content = $request->get('content',null);
  264. $discussion->content_type = $request->get('content_type',"markdown");
  265. $discussion->parent = $request->get('parent',null);
  266. $discussion->editor_uid = $user['user_uid'];
  267. $discussion->save();
  268. //更新parent children_count
  269. if($request->has('parent')){
  270. $parentInfo->increment('children_count',1);
  271. $parentInfo->save();
  272. }
  273. Mq::publish('discussion',new DiscussionResource($discussion));
  274. return $this->ok(new DiscussionResource($discussion));
  275. }
  276. /**
  277. * Display the specified resource.
  278. *
  279. * @param \App\Models\Discussion $discussion
  280. * @return \Illuminate\Http\Response
  281. */
  282. public function show(Discussion $discussion)
  283. {
  284. //
  285. return $this->ok(new DiscussionResource($discussion));
  286. }
  287. /**
  288. * 获取discussion 锚点的数据。以句子为最小单位,逐词解析也要显示单词所在的句子
  289. *
  290. * @param string $id
  291. * @return \Illuminate\Http\Response
  292. */
  293. public function anchor($id)
  294. {
  295. //
  296. $discussion = Discussion::find($id);
  297. switch ($discussion->res_type) {
  298. case 'wbw':
  299. # 从逐词解析表获取逐词解析数据
  300. $wbw = Wbw::where('uid',$discussion->res_id)->first();
  301. if(!$wbw){
  302. return $this->error('no wbw data');
  303. }
  304. $wbwBlock = WbwBlock::where('uid',$wbw->block_uid)->first();
  305. if(!$wbwBlock){
  306. return $this->error('no wbwBlock data');
  307. }
  308. $sent = PaliSentence::where('book',$wbw->book_id)
  309. ->where('paragraph',$wbw->paragraph)
  310. ->where('word_begin','<=',$wbw->wid)
  311. ->where('word_end','>=',$wbw->wid)
  312. ->first();
  313. if(!$sent){
  314. return $this->error('no sent data');
  315. }
  316. $sentId = "{$sent['book']}-{$sent['paragraph']}-{$sent['word_begin']}-{$sent['word_end']}";
  317. $channel = $wbwBlock->channel_uid;
  318. $content = MdRender::render("{{".$sentId."}}",[$channel]);
  319. return $this->ok($content);
  320. break;
  321. default:
  322. # code...
  323. break;
  324. }
  325. return $this->ok();
  326. }
  327. /**
  328. * Update the specified resource in storage.
  329. *
  330. * @param \Illuminate\Http\Request $request
  331. * @param \App\Models\Discussion $discussion
  332. * @return \Illuminate\Http\Response
  333. */
  334. public function update(Request $request, Discussion $discussion)
  335. {
  336. //
  337. $user = AuthApi::current($request);
  338. if(!$user){
  339. return $this->error(__('auth.failed'),[403],403);
  340. }
  341. //
  342. if($discussion->editor_uid !== $user['user_uid']){
  343. return $this->error(__('auth.failed'),[403],403);
  344. }
  345. $discussion->title = $request->get('title',null);
  346. $discussion->content = $request->get('content',null);
  347. $discussion->status = $request->get('status','active');
  348. if($request->has('type')){
  349. $discussion->type = $request->get('type');
  350. }
  351. $discussion->editor_uid = $user['user_uid'];
  352. $discussion->save();
  353. return $this->ok(new DiscussionResource($discussion));
  354. }
  355. /**
  356. * Remove the specified resource from storage.
  357. *
  358. * @param \App\Models\Discussion $discussion
  359. * @return \Illuminate\Http\Response
  360. */
  361. public function destroy(Request $request,Discussion $discussion)
  362. {
  363. //
  364. $user = AuthApi::current($request);
  365. if(!$user){
  366. return $this->error(__('auth.failed'),[401],401);
  367. }
  368. //TODO 其他有权限的人也可以删除
  369. if($discussion->editor_uid !== $user['user_uid']){
  370. return $this->error(__('auth.failed'),[403],403);
  371. }
  372. $delete = $discussion->delete();
  373. return $this->ok($delete);
  374. }
  375. }