with('webmentions', 'place', 'media')->simplePaginate(10); foreach ($notes as $note) { $replies = 0; foreach ($note->webmentions as $webmention) { if ($webmention->type == 'in-reply-to') { $replies++; } } $note->replies = $replies; $note->twitter = $this->checkTwitterReply($note->in_reply_to); $note->iso8601_time = $note->updated_at->toISO8601String(); $note->human_time = $note->updated_at->diffForHumans(); if ($note->location && ($note->place === null)) { $pieces = explode(':', $note->location); $latlng = explode(',', $pieces[0]); $note->latitude = trim($latlng[0]); $note->longitude = trim($latlng[1]); if (count($pieces) == 2) { $note->address = $pieces[1]; } } if ($note->place !== null) { $lnglat = explode(' ', $note->place->location); $note->latitude = $lnglat[1]; $note->longitude = $lnglat[0]; $note->address = $note->place->name; $note->placeLink = '/places/' . $note->place->slug; } $photoURLs = []; $photos = $note->getMedia(); foreach ($photos as $photo) { $photoURLs[] = $photo->getUrl(); } $note->photoURLs = $photoURLs; } return view('allnotes', ['notes' => $notes]); } /** * Show a single note. * * @param string The id of the note * @return \Illuminate\View\Factory view */ public function singleNote($urlId) { $numbers = new Numbers(); $authorship = new Authorship(); $realId = $numbers->b60tonum($urlId); $note = Note::find($realId); $replies = []; $reposts = []; $likes = []; foreach ($note->webmentions as $webmention) { /* reply->url | reply->photo | Author reply->name | reply->source reply->date reply->reply repost->url | repost->photo | Author repost->name | repost->date repost->source like->url | like->photo | Author like->name | */ $microformats = json_decode($webmention->mf2); $authorHCard = $authorship->findAuthor($microformats); $content['url'] = $authorHCard['properties']['url'][0]; $content['photo'] = $this->createPhotoLink($authorHCard['properties']['photo'][0]); $content['name'] = $authorHCard['properties']['name'][0]; switch ($webmention->type) { case 'in-reply-to': $content['source'] = $webmention->source; $content['date'] = $carbon->parse($content['date'])->toDayDateTimeString(); $content['reply'] = $microformats['items'][0]['properties']['content'][0]['html_purified']; $replies[] = $content; break; case 'repost-of': $content['date'] = $carbon->parse($content['date'])->toDayDateTimeString(); $content['source'] = $webmention->source; $reposts[] = $content; break; case 'like-of': $likes[] = $content; break; } } $note->twitter = $this->checkTwitterReply($note->in_reply_to); $note->iso8601_time = $note->updated_at->toISO8601String(); $note->human_time = $note->updated_at->diffForHumans(); if ($note->location && ($note->place === null)) { $pieces = explode(':', $note->location); $latlng = explode(',', $pieces[0]); $note->latitude = trim($latlng[0]); $note->longitude = trim($latlng[1]); if (count($pieces) == 2) { $note->address = $pieces[1]; } } if ($note->place !== null) { $lnglat = explode(' ', $note->place->location); $note->latitude = $lnglat[1]; $note->longitude = $lnglat[0]; $note->address = $note->place->name; $note->placeLink = '/places/' . $note->place->slug; } $note->photoURLs = []; foreach ($note->getMedia() as $photo) { $note->photoURLs[] = $photo->getUrl(); } return view('singlenote', [ 'note' => $note, 'replies' => $replies, 'reposts' => $reposts, 'likes' => $likes, ]); } /** * Redirect /note/{decID} to /notes/{nb60id}. * * @param string The decimal id of he note * @return \Illuminate\Routing\RedirectResponse redirect */ public function singleNoteRedirect($decId) { $numbers = new Numbers(); $realId = $numbers->numto60($decId); $url = config('app.url') . '/notes/' . $realId; return redirect($url); } /** * Show all notes tagged with {tag}. * * @param string The tag * @return \Illuminate\View\Factory view */ public function taggedNotes($tag) { $notes = Note::whereHas('tags', function ($query) use ($tag) { $query->where('tag', $tag); })->get(); foreach ($notes as $note) { $note->iso8601_time = $note->updated_at->toISO8601String(); $note->human_time = $note->updated_at->diffForHumans(); } return view('taggednotes', ['notes' => $notes, 'tag' => $tag]); } /** * Create the photo link. * * We shall leave twitter.com and twimg.com links as they are. Then we shall * check for local copies, if that fails leave the link as is. * * @param string * @return string */ public function createPhotoLink($url) { $host = parse_url($url, PHP_URL_HOST); if ($host == 'pbs.twimg.com') { //make sure we use HTTPS, we know twitter supports it return str_replace('http://', 'https://', $url); } if ($host == 'twitter.com') { if (Cache::has($url)) { return Cache::get($url); } $username = parse_url($url, PHP_URL_PATH); try { $info = Twitter::getUsers(['screen_name' => $username]); $profile_image = $info->profile_image_url_https; Cache::put($url, $profile_image, 10080); //1 week } catch (Exception $e) { return $url; //not sure here } return $profile_image; } $filesystem = new Filesystem(); if ($filesystem->exists(public_path() . '/assets/profile-images/' . $host . '/image')) { return '/assets/profile-images/' . $host . '/image'; } return $url; } /** * Twitter!!! * * @param string The reply to URL * @return string | null */ private function checkTwitterReply($url) { if ($url == null) { return; } if (mb_substr($url, 0, 20, 'UTF-8') !== 'https://twitter.com/') { return; } $arr = explode('/', $url); $tweetId = end($arr); if (Cache::has($tweetId)) { return Cache::get($tweetId); } try { $oEmbed = Twitter::getOembed([ 'id' => $tweetId, 'align' => 'center', 'omit_script' => true, 'maxwidth' => 550, ]); } catch (\Exception $e) { return; } Cache::put($tweetId, $oEmbed, ($oEmbed->cache_age / 60)); return $oEmbed; } }