ArticleController.php 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450
  1. <?php
  2. namespace App\Http\Controllers;
  3. use App\Models\Article;
  4. use App\Models\ArticleCollection;
  5. use App\Models\Collection;
  6. use Illuminate\Http\Request;
  7. use Illuminate\Support\Str;
  8. use App\Http\Resources\ArticleResource;
  9. use App\Http\Api\AuthApi;
  10. use App\Http\Api\ShareApi;
  11. use App\Http\Api\StudioApi;
  12. use Illuminate\Support\Facades\DB;
  13. use Illuminate\Support\Facades\Log;
  14. use App\Tools\OpsLog;
  15. class ArticleController extends Controller
  16. {
  17. public static function userCanRead($user_uid,Article $article){
  18. if($article->status === 30 ){
  19. return true;
  20. }
  21. if(empty($user_uid)){
  22. return false;
  23. }
  24. //私有文章,判断是否为所有者
  25. if($user_uid === $article->owner){
  26. return true;
  27. }
  28. //非所有者
  29. //判断是否为文章协作者
  30. $power = ShareApi::getResPower($user_uid,$article->uid);
  31. if($power >= 10 ){
  32. return true;
  33. }
  34. //无读取权限
  35. //判断文集是否有读取权限
  36. $inCollection = ArticleCollection::where('article_id',$article->uid)
  37. ->select('collect_id')
  38. ->groupBy('collect_id')->get();
  39. if(!$inCollection){
  40. return false;
  41. }
  42. //查找与文章同主人的文集
  43. $collections = Collection::whereIn('uid',$inCollection)
  44. ->where('owner',$article->owner)
  45. ->select('uid')
  46. ->get();
  47. if(!$collections){
  48. return false;
  49. }
  50. //查找与文章同主人的文集是否是共享的
  51. $power = 0;
  52. foreach ($collections as $collection) {
  53. # code...
  54. $currPower = ShareApi::getResPower($user_uid,$collection->uid);
  55. if($currPower >= 10){
  56. return true;
  57. }
  58. }
  59. return false;
  60. }
  61. public static function userCanEdit($user_uid,$article){
  62. if(empty($user_uid)){
  63. return false;
  64. }
  65. //私有文章,判断是否为所有者
  66. if($user_uid === $article->owner){
  67. return true;
  68. }
  69. //非所有者
  70. //判断是否为文章协作者
  71. $power = ShareApi::getResPower($user_uid,$article->uid);
  72. if($power >= 20 ){
  73. return true;
  74. }
  75. //无读取权限
  76. //判断文集是否有读取权限
  77. $inCollection = ArticleCollection::where('article_id',$article->uid)
  78. ->select('collect_id')
  79. ->groupBy('collect_id')->get();
  80. if(!$inCollection){
  81. return false;
  82. }
  83. //查找与文章同主人的文集
  84. $collections = Collection::whereIn('uid',$inCollection)
  85. ->where('owner',$article->owner)
  86. ->select('uid')
  87. ->get();
  88. if(!$collections){
  89. return false;
  90. }
  91. //查找与文章同主人的文集是否是共享的
  92. $power = 0;
  93. foreach ($collections as $collection) {
  94. # code...
  95. $currPower = ShareApi::getResPower($user_uid,$collection->uid);
  96. if($currPower >= 20){
  97. return true;
  98. }
  99. }
  100. return false;
  101. }
  102. public static function userCanManage($user_uid,$studioName){
  103. if(empty($user_uid)){
  104. return false;
  105. }
  106. //判断是否为所有者
  107. if($user_uid === StudioApi::getIdByName($studioName)){
  108. return true;
  109. }else{
  110. return false;
  111. }
  112. }
  113. /**
  114. * Display a listing of the resource.
  115. *
  116. * @return \Illuminate\Http\Response
  117. */
  118. public function index(Request $request)
  119. {
  120. //
  121. $field = ['uid','title','subtitle',
  122. 'summary','owner','lang',
  123. 'status','editor_id','updated_at','created_at'];
  124. if($request->get('content')==="true"){
  125. $field[] = 'content';
  126. $field[] = 'content_type';
  127. }
  128. $table = Article::select($field);
  129. switch ($request->get('view')) {
  130. case 'template':
  131. $studioId = StudioApi::getIdByName($request->get('studio_name'));
  132. $table = $table->where('owner', $studioId);
  133. break;
  134. case 'studio':
  135. # 获取studio内所有 article
  136. $user = AuthApi::current($request);
  137. if(!$user){
  138. return $this->error(__('auth.failed'),[],401);
  139. }
  140. //判断当前用户是否有指定的studio的权限
  141. $studioId = StudioApi::getIdByName($request->get('name'));
  142. if($user['user_uid'] !== $studioId){
  143. return $this->error(__('auth.failed'),[],403);
  144. }
  145. if($request->get('view2','my')==='my'){
  146. $table = $table->where('owner', $studioId);
  147. }else{
  148. //协作
  149. $resList = ShareApi::getResList($studioId,3);
  150. $resId=[];
  151. foreach ($resList as $res) {
  152. $resId[] = $res['res_id'];
  153. }
  154. $table = $table->whereIn('uid', $resId)->where('owner','<>', $studioId);
  155. }
  156. //根据anthology过滤
  157. if($request->has('anthology')){
  158. switch ($request->get('anthology')) {
  159. case 'all':
  160. break;
  161. case 'none':
  162. # 我的文集
  163. $myCollection = Collection::where('owner',$studioId)->select('uid')->get();
  164. //收录在我的文集里面的文章
  165. $articles = ArticleCollection::whereIn('collect_id',$myCollection)
  166. ->select('article_id')->groupBy('article_id')->get();
  167. //不在这些范围之内的文章
  168. $table = $table->whereNotIn('uid',$articles);
  169. break;
  170. default:
  171. $articles = ArticleCollection::where('collect_id',$request->get('anthology'))
  172. ->select('article_id')->get();
  173. $table = $table->whereIn('uid',$articles);
  174. break;
  175. }
  176. }
  177. break;
  178. case 'public':
  179. $table = $table->where('status',30);
  180. break;
  181. default:
  182. $this->error("view error");
  183. break;
  184. }
  185. //处理搜索
  186. if($request->has("search") && !empty($request->get("search"))){
  187. $table = $table->where('title', 'like', "%".$request->get("search")."%");
  188. }
  189. if($request->has("subtitle") && !empty($request->get("subtitle"))){
  190. $table = $table->where('subtitle', 'like', $request->get("subtitle"));
  191. }
  192. //获取记录总条数
  193. $count = $table->count();
  194. //处理排序
  195. $table = $table->orderBy($request->get("order",'updated_at'),
  196. $request->get("dir",'desc'));
  197. //处理分页
  198. $table = $table->skip($request->get("offset",0))
  199. ->take($request->get("limit",1000));
  200. //获取数据
  201. $result = $table->get();
  202. return $this->ok(["rows"=>ArticleResource::collection($result),"count"=>$count]);
  203. }
  204. /**
  205. * Display a listing of the resource.
  206. *
  207. * @return \Illuminate\Http\Response
  208. */
  209. public function showMyNumber(Request $request){
  210. $user = AuthApi::current($request);
  211. if(!$user){
  212. return $this->error(__('auth.failed'));
  213. }
  214. //判断当前用户是否有指定的studio的权限
  215. $studioId = StudioApi::getIdByName($request->get('studio'));
  216. if($user['user_uid'] !== $studioId){
  217. return $this->error(__('auth.failed'));
  218. }
  219. //我的
  220. $my = Article::where('owner', $studioId)->count();
  221. //协作
  222. $resList = ShareApi::getResList($studioId,3);
  223. $resId=[];
  224. foreach ($resList as $res) {
  225. $resId[] = $res['res_id'];
  226. }
  227. $collaboration = Article::whereIn('uid', $resId)->where('owner','<>', $studioId)->count();
  228. return $this->ok(['my'=>$my,'collaboration'=>$collaboration]);
  229. }
  230. /**
  231. * Store a newly created resource in storage.
  232. *
  233. * @param \Illuminate\Http\Request $request
  234. * @return \Illuminate\Http\Response
  235. */
  236. public function store(Request $request)
  237. {
  238. //判断权限
  239. $user = AuthApi::current($request);
  240. if(!$user){
  241. Log::error('未登录');
  242. return $this->error(__('auth.failed'),[],401);
  243. }else{
  244. $user_uid=$user['user_uid'];
  245. }
  246. $canManage = ArticleController::userCanManage($user_uid,$request->get('studio'));
  247. if(!$canManage){
  248. Log::error('userCanManage 失败');
  249. //判断是否有文集权限
  250. if($request->has('anthologyId')){
  251. $currPower = ShareApi::getResPower($user_uid,$request->get('anthologyId'));
  252. if($currPower <= 10){
  253. Log::error('没有文集编辑权限');
  254. return $this->error(__('auth.failed'),[],403);
  255. }
  256. }else{
  257. Log::error('没有文集id');
  258. return $this->error(__('auth.failed'),[],403);
  259. }
  260. }
  261. //权限判断结束
  262. //查询标题是否重复
  263. /*
  264. if(Article::where('title',$request->get('title'))->where('owner',$studioUuid)->exists()){
  265. return $this->error(__('validation.exists'));
  266. }*/
  267. $newArticle = new Article;
  268. DB::transaction(function() use($user,$request,$newArticle){
  269. $studioUuid = StudioApi::getIdByName($request->get('studio'));
  270. //新建文章,加入文集必须都成功。否则回滚
  271. $newArticle->id = app('snowflake')->id();
  272. $newArticle->uid = Str::uuid();
  273. $newArticle->title = $request->get('title');
  274. $newArticle->lang = $request->get('lang');
  275. $newArticle->owner = $studioUuid;
  276. $newArticle->owner_id = $user['user_id'];
  277. $newArticle->editor_id = $user['user_id'];
  278. $newArticle->parent = $request->get('parentId');
  279. $newArticle->create_time = time()*1000;
  280. $newArticle->modify_time = time()*1000;
  281. $newArticle->save();
  282. OpsLog::debug($user['user_uid'],$newArticle);
  283. if(Str::isUuid($request->get('anthologyId'))){
  284. $articleMap = new ArticleCollection();
  285. $articleMap->id = app('snowflake')->id();
  286. $articleMap->article_id = $newArticle->uid;
  287. $articleMap->collect_id = $request->get('anthologyId');
  288. $articleMap->title = Article::find($newArticle->uid)->title;
  289. $articleMap->level = 1;
  290. $articleMap->save();
  291. }
  292. });
  293. if(Str::isUuid($newArticle->uid)){
  294. return $this->ok($newArticle);
  295. }else{
  296. return $this->error('fail');
  297. }
  298. }
  299. /**
  300. * Display the specified resource.
  301. * @param \Illuminate\Http\Request $request
  302. * @param \App\Models\Article $article
  303. * @return \Illuminate\Http\Response
  304. */
  305. public function show(Request $request,Article $article)
  306. {
  307. //
  308. if(!$article){
  309. return $this->error("no recorder");
  310. }
  311. //判断权限
  312. $user = AuthApi::current($request);
  313. if(!$user){
  314. $user_uid="";
  315. }else{
  316. $user_uid=$user['user_uid'];
  317. }
  318. $canRead = ArticleController::userCanRead($user_uid,$article);
  319. if(!$canRead){
  320. return $this->error(__('auth.failed'),[],403);
  321. }
  322. return $this->ok(new ArticleResource($article));
  323. }
  324. /**
  325. * Display the specified resource.
  326. * @param \Illuminate\Http\Request $request
  327. * @param string $article
  328. * @return \Illuminate\Http\Response
  329. */
  330. public function preview(Request $request,string $articleId)
  331. {
  332. //
  333. $article = Article::find($articleId);
  334. if(!$article){
  335. return $this->error("no recorder");
  336. }
  337. //判断权限
  338. $user = AuthApi::current($request);
  339. if(!$user){
  340. $user_uid="";
  341. }else{
  342. $user_uid=$user['user_uid'];
  343. }
  344. $canRead = ArticleController::userCanRead($user_uid,$article);
  345. if(!$canRead){
  346. return $this->error(__('auth.failed'),[],401);
  347. }
  348. if($request->has('content')){
  349. $article->content = $request->get('content');
  350. return $this->ok(new ArticleResource($article));
  351. }else{
  352. return $this->error('no content',[],200);
  353. }
  354. }
  355. /**
  356. * Update the specified resource in storage.
  357. *
  358. * @param \Illuminate\Http\Request $request
  359. * @param \App\Models\Article $article
  360. * @return \Illuminate\Http\Response
  361. */
  362. public function update(Request $request, Article $article)
  363. {
  364. //
  365. if(!$article){
  366. return $this->error("no recorder");
  367. }
  368. //鉴权
  369. $user = AuthApi::current($request);
  370. if(!$user){
  371. return $this->error(__('auth.failed'),[],401);
  372. }else{
  373. $user_uid=$user['user_uid'];
  374. }
  375. $canEdit = ArticleController::userCanEdit($user_uid,$article);
  376. if(!$canEdit){
  377. return $this->error(__('auth.failed'),[],401);
  378. }
  379. /*
  380. //查询标题是否重复
  381. if(Article::where('title',$request->get('title'))
  382. ->where('owner',$article->owner)
  383. ->where('uid',"<>",$article->uid)
  384. ->exists()){
  385. return $this->error(__('validation.exists'));
  386. }*/
  387. $article->title = $request->get('title');
  388. $article->subtitle = $request->get('subtitle');
  389. $article->summary = $request->get('summary');
  390. $article->content = $request->get('content');
  391. $article->lang = $request->get('lang');
  392. $article->status = $request->get('status',10);
  393. $article->editor_id = $user['user_id'];
  394. $article->modify_time = time()*1000;
  395. $article->save();
  396. OpsLog::debug($user_uid,$article);
  397. return $this->ok($article);
  398. }
  399. /**
  400. * Remove the specified resource from storage.
  401. * @param \Illuminate\Http\Request $request
  402. * @param \App\Models\Article $article
  403. * @return \Illuminate\Http\Response
  404. */
  405. public function destroy(Request $request,Article $article)
  406. {
  407. //
  408. $user = AuthApi::current($request);
  409. if(!$user){
  410. return $this->error(__('auth.failed'));
  411. }
  412. //判断当前用户是否有指定的studio的权限
  413. if($user['user_uid'] !== $article->owner){
  414. return $this->error(__('auth.failed'));
  415. }
  416. $delete = 0;
  417. DB::transaction(function() use($article,$delete){
  418. //TODO 删除文集中的文章
  419. $delete = $article->delete();
  420. ArticleMapController::deleteArticle($article->uid);
  421. });
  422. return $this->ok($delete);
  423. }
  424. }