PageRenderTime 44ms CodeModel.GetById 13ms RepoModel.GetById 0ms app.codeStats 0ms

/app/Http/Controllers/AnnotationsController.php

https://gitlab.com/dusandevic/hypothesis
PHP | 416 lines | 302 code | 99 blank | 15 comment | 15 complexity | 69c5a34027e3c7f31b9812e0dcb8adfa MD5 | raw file
  1. <?php
  2. namespace App\Http\Controllers;
  3. use Illuminate\Http\Request;
  4. use App\Jobs\ProcessAnnotations;
  5. use App\Http\Requests;
  6. use Carbon\Carbon;
  7. use Illuminate\Support\Collection;
  8. class AnnotationsController extends Controller
  9. {
  10. private $jsons = [];
  11. private function collapseJSONs(){
  12. $decoded = new Collection();
  13. $jsons = $this->jsons;
  14. foreach($jsons as $json){
  15. $decodedSet = json_decode($json);
  16. $decoded->push($decodedSet->rows);
  17. }
  18. return $decoded->collapse();
  19. }
  20. public function callAPI($apiKey, $groupID, $offset=0){
  21. $context = stream_context_create(array (
  22. 'http' => array (
  23. 'header' => 'Authorization: Bearer '.$apiKey
  24. )
  25. ));
  26. $url = "https://hypothes.is/api/search?group=".$groupID."&limit=200&offset=".$offset;
  27. $json = file_get_contents($url, false, $context);
  28. $decoded = json_decode($json);
  29. $this->jsons[] = $json; //$json;
  30. $total = $decoded->total;
  31. if($total > $offset){
  32. \Log::info("TOTAL: ".$total.", OFFSET: ".$offset);
  33. $this->callAPI($apiKey, $groupID, $offset + 200); //recursive call
  34. }else{
  35. return $this->jsons;
  36. }
  37. }
  38. public function getFeed(){
  39. $groups = \App\Group::all();
  40. $jsons = [];
  41. foreach($groups as $group){
  42. $this->callAPI($group->api_key, $group->hypothesis_id);
  43. $jsons[$group->id] = $this->collapseJSONs();
  44. }
  45. $report = [];
  46. foreach($jsons as $groupID => $annotations){
  47. $saved = 0;
  48. $skipped = 0;
  49. foreach($annotations as $annotation){
  50. $existingUser = $this->findByHypothesisUsername($annotation->user);
  51. $existingLocalAnnotation = \App\Annotation::where("hypothesis_id", $annotation->id)->count();
  52. if($existingUser && $existingLocalAnnotation == 0){
  53. $publishedAt = \Carbon\Carbon::parse($annotation->created);
  54. $title = $annotation->document;
  55. $title = $title->title[0];
  56. $localAnnotation = new \App\Annotation();
  57. $localAnnotation->hypothesis_id = $annotation->id;
  58. $localAnnotation->group_id = $groupID;
  59. $localAnnotation->user_id = $existingUser->id;
  60. $localAnnotation->content = $annotation->text;
  61. $localAnnotation->document = $annotation->uri;
  62. $localAnnotation->doc_title = $title;
  63. $localAnnotation->source = json_encode($annotation);
  64. $localAnnotation->published_at = $publishedAt;
  65. $localAnnotation->save();
  66. $saved++;
  67. }else{
  68. !$existingUser ? \Log::warning("There is no registered user with this username: ".$this->cutUsernameString($annotation->user)) : "";
  69. $existingLocalAnnotation > 0 ? \Log::warning("Annotation: ".$annotation->id." already persisted.") : "";
  70. $skipped++;
  71. }
  72. }
  73. $ind = 0;
  74. $group = \App\Group::findOrFail($groupID);
  75. $report[$ind]['Group'] = $group->name;
  76. $report[$ind]['Annotations Recorded'] = $saved;
  77. $report[$ind]['Annotations Skipped'] = $skipped;
  78. $ind++;
  79. }
  80. dispatch(new ProcessAnnotations());
  81. return $report;
  82. }
  83. public function testRelations(){
  84. //$annotation = \App\Annotation::findOrFail(2);
  85. //dd($annotation->user->name);
  86. //dd($annotation->group->name);
  87. //return $annotation;
  88. //$group = \App\Group::findOrFail(1);
  89. //return $group->annotations;
  90. //$user = \App\User::findOrFail(1);
  91. //return ($user->annotations);
  92. //$annotation = \App\Annotation::findOrFail(49);
  93. //dd($annotation->likes->count());
  94. }
  95. public function annotationsByDocuments(){
  96. $module_id = "DOCUMENTS";
  97. $documents = \App\Annotation::distinct('document')->select('document')->get();
  98. $documentsArray = [];
  99. $index = 0;
  100. //check documents and prepare the collection
  101. foreach($documents as $document){
  102. $annotations = \App\Annotation::where("document", $document->document)->get();
  103. $documentsArray[$index]['url'] = $document->document;
  104. $documentsArray[$index]['title'] = $annotations[0]->doc_title;
  105. $documentsArray[$index]['count'] = $annotations->count();
  106. $documentsArray[$index]['annotations'] = $annotations;
  107. $documentsArray[$index]['shouldNotify'] = $annotations->count() >= 2 ? true : false;
  108. $index++;
  109. }
  110. foreach($documentsArray as $doc){
  111. if($doc['shouldNotify']){
  112. foreach($doc['annotations'] as $annotation){
  113. $data['annotation'] = $annotation;
  114. $data['count'] = $doc['count'];
  115. $data['title'] = $doc['title'];
  116. $userEmail = $annotation->user->email;
  117. $userName = $annotation->user->name;
  118. $link = new \App\Link();
  119. $link->endpoint = $doc['url'];
  120. $link->entity_id = $annotation->hypothesis_id;
  121. $link->user_id = $annotation->user->id;
  122. $link->clicked = 0;
  123. $link->module_name = $module_id;
  124. $link->save();
  125. $data['emailLink'] = $link->getApplicationLink();
  126. $alreadyNotified = $this->alreadyNotified($module_id, $annotation->user->id, $annotation->hypothesis_id);
  127. if(!$alreadyNotified){
  128. \Mail::send('emails.documentReached', $data, function ($m) use ($userEmail, $userName, $data) {
  129. $m->from('noreply@HypothesisApp.com', 'Hypothesis App');
  130. $m->to($userEmail, $userName)->subject($data['title'].' reached ' .$data['count']. ' annotations!');
  131. });
  132. $log = new \App\MailLog();
  133. $log->module_id = $module_id;
  134. $log->user_id = $annotation->user->id;
  135. $log->entity_id = $annotation->hypothesis_id;
  136. $log->save();
  137. }else{
  138. \Log::info("User ".$annotation->user->name. " is already notified about module ".$module_id. " and entity (annotation) ".$annotation->hypothesis_id);
  139. }
  140. }
  141. }
  142. }
  143. }
  144. public function testEmail(){
  145. $groups = \App\Group::all();
  146. foreach($groups as $group){
  147. $count = $group->annotations->count();
  148. if($count > 3){
  149. \Log::info("Group ".$group->name. " has ".$count . " annotations, we should notify our users...");
  150. $usersToNotify = [];
  151. foreach($group->annotations as $annotation){
  152. $data = [ "count" => $count,
  153. "group" => $group,
  154. "user" => $annotation->user,
  155. "link" => "https://hypothes.is/stream?q=group:".$group->hypothesis_id
  156. ];
  157. $usersToNotify[$annotation->user->id] = $annotation->user; //to avoid many emails to the same user
  158. }
  159. foreach($usersToNotify as $user){
  160. //return $data;
  161. $userEmail = $user->email;
  162. $userName = $user->name;
  163. \Mail::send('emails.annotationsReached', $data, function ($m) use ($userEmail, $userName, $data) {
  164. $m->from('noreply@HypothesisApp.com', 'Hypothesis App');
  165. $m->to($userEmail, $userName)->subject('Group '.$data['group']->name.' has '.$data['count'].' annotations!');
  166. });
  167. }
  168. }else{
  169. \Log::info("Group ".$group->name. " does not have enough annotations, no further action needed.");
  170. }
  171. }
  172. }
  173. public function cutUsernameString($string){
  174. $cutPrefix = substr($string, 5);
  175. $cutSufix = str_replace("@hypothes.is", "", $cutPrefix);
  176. return $cutSufix;
  177. }
  178. public function findByHypothesisUsername($username){
  179. $username = $this->cutUsernameString($username);
  180. return \App\User::findByHypothesisUsername($username);
  181. }
  182. public function testMentions(){
  183. $annotations = \App\Annotation::all();
  184. $mentions = [];
  185. foreach($annotations as $annot){
  186. $hasMention = $this->checkMentions($annot->content);
  187. if($hasMention){
  188. $mentions[$annot->id] = $hasMention;
  189. }
  190. }
  191. foreach($mentions as $annotID => $userArray){
  192. $annotation = \App\Annotation::findOrFail($annotID);
  193. foreach($userArray as $mention){
  194. $mention = substr($mention, 1); //to cut @
  195. $mentionedUser = \App\User::findByHypothesisUsername($mention);
  196. if($mentionedUser){
  197. $data['link'] = "https://hypothes.is/stream?q=user:".$mention;
  198. $data['user'] = $mentionedUser;
  199. $data['author'] = $annotation->user->name . " (@" .$annotation->user->hypothesis_username.")";
  200. $data['annotation'] = $annotation;
  201. $userEmail = $mentionedUser->email;
  202. $userName = $mentionedUser->name;
  203. \Mail::send('emails.mentionNotification', $data, function ($m) use ($userEmail, $userName, $data) {
  204. $m->from('noreply@HypothesisApp.com', 'Hypothesis App');
  205. $m->to($userEmail, $userName)->subject('New mention by '.$data['author'].'!');
  206. });
  207. }else{
  208. \Log::warning("User @".$mention. " was mentioned in annotation #".$annotID." but that user profile is missing");
  209. }
  210. }
  211. }
  212. }
  213. private function checkMentions($string){
  214. $matches = null;
  215. $returnValue = preg_match_all('/\\B@[a-z0-9_-]+/', $string, $matches);
  216. return $returnValue > 0 ? $matches[0] : false;
  217. }
  218. public function getLikes(){
  219. return \App\Like::all();
  220. }
  221. public function getLikesForAnnotation($id){
  222. return \App\Like::where("annotation_id", $id)->get();
  223. }
  224. public function postLike(){
  225. $input = \Request::all();
  226. $like = new \App\Like();
  227. $like->annotation_id = $input['annotation_id'];
  228. $like->user_id = $input['user_id'];
  229. $like->save();
  230. return $like;
  231. }
  232. public function deleteLikeForAnnotation(){
  233. $input = \Request::all();
  234. if(isset($input['annotation_id']) && isset($input['user_id'])){
  235. $like = \App\Like::where("annotation_id", $input['annotation_id'])
  236. ->where("user_id", $input['user_id'])->delete();
  237. return "DELETED";
  238. }
  239. return "OK";
  240. }
  241. public function linkRedirect($id){
  242. $link = \App\Link::findOrFail($id);
  243. $link->clicked = 1;
  244. $link->save();
  245. return redirect()->away($link->endpoint);
  246. }
  247. public function groupEmails(){
  248. $mailItems = \App\MailItem::all()->groupBy('user_id');
  249. //dd($mailItems);
  250. $users = []; //list of the users that should be emailed
  251. foreach($mailItems as $userItems){
  252. $userId = $userItems[0]->user_id;
  253. $users[$userId] = false; //assumption: no new items to send
  254. foreach($userItems as $emailItem){
  255. is_null($emailItem->mail_id) ? $users[$userId] = true : ""; //if mail_id is null then it should be sent
  256. }
  257. if($users[$userId]){
  258. //there is something to send, create a new Email Instance;
  259. $mail = new \App\Mail();
  260. $mail->user_id = $userId;
  261. $mail->subject = "Hypothesis: New notifications for you";
  262. $mail->sent_at = null;
  263. $mail->save();
  264. //update mail_items table with our new mail_id;
  265. \App\MailItem::where('user_id', $userId)
  266. ->where('mail_id', null)
  267. ->update(['mail_id' => $mail->id]);
  268. }
  269. }
  270. }
  271. public function sendEmails(){
  272. \Log::info('sendEmails cron-job started at (EU) '.Carbon::now(new \DateTimeZone('Europe/Belgrade')));
  273. \Log::info('sendEmails cron-job started at (Surrey) '.Carbon::now(new \DateTimeZone('America/Vancouver')));
  274. $emails = \App\Mail::where('sent_at', null)->get();
  275. if($emails->count() == 0){
  276. \Log::info("No emails to send");
  277. }else{
  278. $sent = 0;
  279. foreach($emails as $email){
  280. $userEmail = $email->user->email;
  281. $userName = $email->user->name;
  282. $subject = $email->subject;
  283. $data['email'] = $email;
  284. \Mail::send('emails.groupEmail', $data, function ($m) use ($userEmail, $userName, $subject) {
  285. $m->from('noreply@hypo.dusandevic.com', 'Hypothesis App');
  286. $m->to($userEmail, $userName)->subject($subject);
  287. });
  288. $email->touch();
  289. $email->save();
  290. $email->sent_at = $email->updated_at;
  291. $email->save();
  292. $sent++;
  293. }
  294. \Log::info($sent." emails are sent");
  295. }
  296. }
  297. public function showHomepage(){
  298. return view("welcome");
  299. }
  300. public function getGroups(){
  301. $data['groups'] = \App\Group::all();
  302. return view("groups", $data);
  303. }
  304. public function postGroup(){
  305. $g = new \App\Group;
  306. $g->name = \Request::get('name');
  307. $g->hypothesis_id = \Request::get('hypothesis_id');
  308. $g->api_key = \Request::get('api_key');
  309. $g->save();
  310. return redirect()->action('AnnotationsController@getGroups');
  311. }
  312. public function deleteGroup($id){
  313. $g = \App\Group::findOrFail($id);
  314. $g->delete();
  315. return redirect()->action('AnnotationsController@getGroups');
  316. }
  317. }