commit 19ec350ca9c3a2ec9da6ee3823f3b0a09efe3eaa
Author: Jonny Barnes <jonny@jonnybarnes.uk>
Date: Tue Nov 22 16:07:42 2016 +0000
Update changelog
commit 73428d3d94c659e5e4431b6740ba10dc2a609e44
Author: Jonny Barnes <jonny@jonnybarnes.uk>
Date: Tue Nov 22 16:03:37 2016 +0000
output of gulp compress
commit 4bb8038e787e35b5d38be9d63600b10bb9d75a07
Author: Jonny Barnes <jonny@jonnybarnes.uk>
Date: Tue Nov 22 16:03:11 2016 +0000
import Guzzle’s ClientException namespace
commit 4bcb676bb95274da2422023fefa88b8d246b7f97
Author: Jonny Barnes <jonny@jonnybarnes.uk>
Date: Tue Nov 22 16:02:24 2016 +0000
Update manual testing token
commit d902de76f00b4f3bba94ce6528f87e43f6c113f9
Author: Jonny Barnes <jonny@jonnybarnes.uk>
Date: Tue Nov 22 16:01:52 2016 +0000
output of gulp js-assets
commit 0a495956e4f540aae0d1515229dd29c30c76fd64
Author: Jonny Barnes <jonny@jonnybarnes.uk>
Date: Tue Nov 22 16:01:27 2016 +0000
Update new note page to use Mapbox GL JS
commit bf22004256179c9487c668eb77785a9bc90227bc
Author: Jonny Barnes <jonny@jonnybarnes.uk>
Date: Mon Nov 21 18:47:59 2016 +0000
output of gulp js-assets
commit 22ed61cb853d98a4638754d44f042841e2b4495c
Author: Jonny Barnes <jonny@jonnybarnes.uk>
Date: Mon Nov 21 18:47:06 2016 +0000
Attempting to use mapbox gl on the newnote page
commit 47fd891f1b3f0da59d10e937f7ed11f3b603c4af
Author: Jonny Barnes <jonny@jonnybarnes.uk>
Date: Sat Nov 19 17:21:53 2016 +0000
gulp derived assets
commit 19e83f33b1c8c7a90a74d0ad17a6cace8761bcef
Author: Jonny Barnes <jonny@jonnybarnes.uk>
Date: Sat Nov 19 17:21:16 2016 +0000
Move .map styles into mapbox.scss
commit 3d848d59126032671907a1e354cf121441d9a6e3
Author: Jonny Barnes <jonny@jonnybarnes.uk>
Date: Sat Nov 19 17:12:51 2016 +0000
gulp derived assets
commit 9e51e8690ac8b782bc56663e7ec682837b27d4a1
Author: Jonny Barnes <jonny@jonnybarnes.uk>
Date: Sat Nov 19 17:12:32 2016 +0000
Link to mapbox-gl files
commit 296b5fd7770f2a1c5c26ed4efedd99a7a0ad0bed
Author: Jonny Barnes <jonny@jonnybarnes.uk>
Date: Sat Nov 19 17:12:08 2016 +0000
Use mapbox gl to add maps to notes
commit bd031df6e969b7af741730acabe41465f68bd3a1
Author: Jonny Barnes <jonny@jonnybarnes.uk>
Date: Sat Nov 19 17:11:27 2016 +0000
Update sass to style mapbox gl maps
commit a7cd5e6eaa9510b5c9de672b6d5ed6917dabd7c6
Author: Jonny Barnes <jonny@jonnybarnes.uk>
Date: Fri Nov 18 16:19:45 2016 +0000
output of gulp compress
commit fe63c7ed394d62cd0e47a9ef718d9629d8643e71
Author: Jonny Barnes <jonny@jonnybarnes.uk>
Date: Fri Nov 18 16:18:47 2016 +0000
output of gulp sass
commit 15ac4012681635753a4b1f52d81f7f9e24830eb4
Author: Jonny Barnes <jonny@jonnybarnes.uk>
Date: Fri Nov 18 16:18:05 2016 +0000
Add a dividing line between notes and bio on the homepage
commit 5ada66b1a01ae57359145eb757cab65769400f1e
Author: Jonny Barnes <jonny@jonnybarnes.uk>
Date: Fri Nov 18 16:12:01 2016 +0000
output of gulp sass
commit 86adf97c3831c3310683a25c2671c7560700de1a
Author: Jonny Barnes <jonny@jonnybarnes.uk>
Date: Fri Nov 18 16:11:33 2016 +0000
Resize note metadata for spacial flow
commit 3f3fc51ea8df8206d5b13512295ac09827bb2ede
Author: Jonny Barnes <jonny@jonnybarnes.uk>
Date: Fri Nov 18 15:37:21 2016 +0000
output of gulp sass
commit df6f7f827641dc4deca621d099357757f760ece4
Author: Jonny Barnes <jonny@jonnybarnes.uk>
Date: Fri Nov 18 15:36:51 2016 +0000
Use system UI fonts
commit b71950275ddaf274b26195694a07c1b58f746725
Author: Jonny Barnes <jonny@jonnybarnes.uk>
Date: Fri Nov 18 15:31:30 2016 +0000
output of gulp compress
commit 5ff5d73a803b9bcc4e2f314946c1d757dcabae67
Author: Jonny Barnes <jonny@jonnybarnes.uk>
Date: Fri Nov 18 15:30:12 2016 +0000
output of gulp js-assets
commit d8ff563569223bddc836ab9f8fc7c43970273b44
Author: Jonny Barnes <jonny@jonnybarnes.uk>
Date: Fri Nov 18 15:29:27 2016 +0000
use containing divs in new place section of form
commit 3cbf3083612210cdd7609c930737cf7a698ec024
Author: Jonny Barnes <jonny@jonnybarnes.uk>
Date: Fri Nov 18 14:39:27 2016 +0000
gulp sass output
commit 239b742a355a397f5b84377b26b2d7a4254bd50e
Author: Jonny Barnes <jonny@jonnybarnes.uk>
Date: Fri Nov 18 14:38:52 2016 +0000
Better spacing of form elements on mobile
commit a20279e3f4216b87ff59ed4e507b6de9e212db9f
Author: Jonny Barnes <jonny@jonnybarnes.uk>
Date: Fri Nov 18 13:41:31 2016 +0000
Derived assets
commit 86ebd05472498814084e86fb0c2d674633f00096
Author: Jonny Barnes <jonny@jonnybarnes.uk>
Date: Fri Nov 18 13:40:42 2016 +0000
Use containing divs for flex layout
commit 00e0e6f3f462ca575e92209a86ada67b7f5ff757
Author: Jonny Barnes <jonny@jonnybarnes.uk>
Date: Thu Nov 17 14:38:39 2016 +0000
Correct scss according to stylelint
commit 6dd8ff4d13c3ab83c6a811501b817c45b89338ce
Author: Jonny Barnes <jonny@jonnybarnes.uk>
Date: Thu Nov 17 14:33:46 2016 +0000
Get stylelint working
commit 9b9a64defd9335014b46070e2b92a392929f4aa5
Author: Jonny Barnes <jonny@jonnybarnes.uk>
Date: Thu Nov 17 09:48:28 2016 +0000
Add missing new-line to match style
commit 2521446f32420047d6d5f7372f4f7afc17200a1c
Author: Jonny Barnes <jonny@jonnybarnes.uk>
Date: Tue Nov 15 13:16:45 2016 +0000
Add logging during an error, improve the error message
commit 095507bec225992aac510a2ca852f65c197f0298
Author: Jonny Barnes <jonny@jonnybarnes.uk>
Date: Tue Nov 15 13:15:59 2016 +0000
Update test token
commit 374ef70fecaedf041f12a57688ed9596e25a2ce6
Author: Jonny Barnes <jonny@jonnybarnes.uk>
Date: Tue Nov 15 13:15:16 2016 +0000
Remove typekit for now
commit f5671ad435732ddb3288a2e02de7631a6acb4183
Author: Jonny Barnes <jonny@jonnybarnes.uk>
Date: Fri Nov 11 16:06:01 2016 +0000
Better designed new note form
commit f38df507b85502e733fa38e970cd584f7d79bca1
Author: Jonny Barnes <jonny@jonnybarnes.uk>
Date: Fri Nov 11 13:28:21 2016 +0000
More styling, use normal pagination, improve bio
commit 077076d4f92014d488bca5d4dbbab5af913e6cf0
Author: Jonny Barnes <jonny@jonnybarnes.uk>
Date: Fri Nov 11 00:05:56 2016 +0000
Use an anchor for permalinks, re-word projects page
commit 37c6e862b693c2bfd3a39654a533627e0f73fd1a
Author: Jonny Barnes <jonny@jonnybarnes.uk>
Date: Thu Nov 10 23:58:54 2016 +0000
The resulting CSS files
commit 1a3b6d7064b1b67238ffd3909d6d1ae54a4f78e1
Author: Jonny Barnes <jonny@jonnybarnes.uk>
Date: Thu Nov 10 23:31:53 2016 +0000
Sass for very basic redesign
commit e5d9e9d41b50d7f316fcae9bae75863aa09a7d63
Author: Jonny Barnes <jonny@jonnybarnes.uk>
Date: Thu Nov 10 23:00:35 2016 +0000
Use app.(s)css
commit 231c5292e68220f588e9d300975bb19dfea20b4f
Author: Jonny Barnes <jonny@jonnybarnes.uk>
Date: Thu Nov 10 22:59:50 2016 +0000
Restructure homepage to show notes, also show bio when on '/', but note '/notes'
commit 11a272b2a3050297dd84105a6c70adc937a0c409
Author: Jonny Barnes <jonny@jonnybarnes.uk>
Date: Thu Nov 10 17:49:30 2016 +0000
Set my homepage to the stream of notes
commit 2e46ccad4038be64b5007f15dabee0321061fe98
Author: Jonny Barnes <jonny@jonnybarnes.uk>
Date: Tue Nov 8 23:58:11 2016 +0000
Drop sanitize.css and use normalize.css instead, also fix compress method
commit 8082403d7464a873691fabab07ae4f6116993cdf
Author: Jonny Barnes <jonny@jonnybarnes.uk>
Date: Tue Nov 8 23:48:35 2016 +0000
Sort out yarn dependencies
commit 8ef7137d160ae8577e42ab1fd19e957aa37cf08b
Author: Jonny Barnes <jonny@jonnybarnes.uk>
Date: Tue Nov 8 23:39:49 2016 +0000
Remove the compiled css
commit 8284cdf838f5222eff87c942f119d6000a1b6fc6
Author: Jonny Barnes <jonny@jonnybarnes.uk>
Date: Tue Nov 8 23:16:27 2016 +0000
Remove sass files
352 lines
11 KiB
PHP
352 lines
11 KiB
PHP
<?php
|
||
|
||
namespace App\Http\Controllers;
|
||
|
||
use Illuminate\Http\Request;
|
||
use Illuminate\Http\Response;
|
||
use App\Services\IndieAuthService;
|
||
use Illuminate\Support\Facades\Log;
|
||
use IndieAuth\Client as IndieClient;
|
||
use GuzzleHttp\Client as GuzzleClient;
|
||
use GuzzleHttp\Exception\ClientException;
|
||
|
||
class MicropubClientController extends Controller
|
||
{
|
||
/**
|
||
* The IndieAuth service container.
|
||
*/
|
||
protected $indieAuthService;
|
||
|
||
/**
|
||
* Inject the dependencies.
|
||
*/
|
||
public function __construct(
|
||
IndieAuthService $indieAuthService = null,
|
||
IndieClient $indieClient = null,
|
||
GuzzleClient $guzzleClient = null
|
||
) {
|
||
$this->indieAuthService = $indieAuthService ?? new IndieAuthService();
|
||
$this->guzzleClient = $guzzleClient ?? new GuzzleClient();
|
||
$this->indieClient = $indieClient ?? new IndieClient();
|
||
}
|
||
|
||
/**
|
||
* Display the new notes form.
|
||
*
|
||
* @param \Illuminate\Http\Request $request
|
||
* @return \Illuminate\View\Factory view
|
||
*/
|
||
public function newNotePage(Request $request)
|
||
{
|
||
$url = $request->session()->get('me');
|
||
$syndication = $request->session()->get('syndication');
|
||
|
||
return view('micropubnewnotepage', [
|
||
'url' => $url,
|
||
'syndication' => $syndication,
|
||
]);
|
||
}
|
||
|
||
/**
|
||
* Post the notes content to the relavent micropub API endpoint.
|
||
*
|
||
* @todo make sure this works with multiple syndication targets
|
||
*
|
||
* @param \Illuminate\Http\Request $request
|
||
* @return mixed
|
||
*/
|
||
public function postNewNote(Request $request)
|
||
{
|
||
$domain = $request->session()->get('me');
|
||
$token = $request->session()->get('token');
|
||
|
||
$micropubEndpoint = $this->indieAuthService->discoverMicropubEndpoint(
|
||
$domain,
|
||
$this->indieClient
|
||
);
|
||
if (! $micropubEndpoint) {
|
||
return redirect('notes/new')->withErrors('Unable to determine micropub API endpoint', 'endpoint');
|
||
}
|
||
|
||
$response = $this->postNoteRequest($request, $micropubEndpoint, $token);
|
||
|
||
if ($response->getStatusCode() == 201) {
|
||
$location = $response->getHeader('Location');
|
||
if (is_array($location)) {
|
||
return redirect($location[0]);
|
||
}
|
||
|
||
return redirect($location);
|
||
}
|
||
|
||
return redirect('notes/new')->withErrors('Endpoint didn’t create the note.', 'endpoint');
|
||
}
|
||
|
||
/**
|
||
* We make a request to the micropub endpoint requesting syndication targets
|
||
* and store them in the session.
|
||
*
|
||
* @todo better handling of response regarding mp-syndicate-to
|
||
* and syndicate-to
|
||
*
|
||
* @param \Illuminate\Http\Request $request
|
||
* @param \IndieAuth\Client $indieClient
|
||
* @param \GuzzleHttp\Client $guzzleClient
|
||
* @return \Illuminate\Routing\Redirector redirect
|
||
*/
|
||
public function refreshSyndicationTargets(Request $request)
|
||
{
|
||
$domain = $request->session()->get('me');
|
||
$token = $request->session()->get('token');
|
||
$micropubEndpoint = $this->indieAuthService->discoverMicropubEndpoint($domain, $this->indieClient);
|
||
|
||
if (! $micropubEndpoint) {
|
||
return redirect('notes/new')->withErrors('Unable to determine micropub API endpoint', 'endpoint');
|
||
}
|
||
|
||
try {
|
||
$response = $this->guzzleClient->get($micropubEndpoint, [
|
||
'headers' => ['Authorization' => 'Bearer ' . $token],
|
||
'query' => ['q' => 'syndicate-to'],
|
||
]);
|
||
} catch (\GuzzleHttp\Exception\BadResponseException $e) {
|
||
return redirect('notes/new')->withErrors('Bad response when refreshing syndication targets', 'endpoint');
|
||
}
|
||
$body = (string) $response->getBody();
|
||
$syndication = $this->parseSyndicationTargets($body);
|
||
|
||
$request->session()->put('syndication', $syndication);
|
||
|
||
return redirect('notes/new');
|
||
}
|
||
|
||
/**
|
||
* This method performs the actual POST request.
|
||
*
|
||
* @param \Illuminate\Http\Request $request
|
||
* @param string The Micropub endpoint to post to
|
||
* @param string The token to authenticate the request with
|
||
* @return \GuzzleHttp\Response $response | \Illuminate\RedirectFactory redirect
|
||
*/
|
||
private function postNoteRequest(
|
||
Request $request,
|
||
$micropubEndpoint,
|
||
$token
|
||
) {
|
||
$multipart = [
|
||
[
|
||
'name' => 'h',
|
||
'contents' => 'entry',
|
||
],
|
||
[
|
||
'name' => 'content',
|
||
'contents' => $request->input('content'),
|
||
],
|
||
];
|
||
if ($request->hasFile('photo')) {
|
||
$photos = $request->file('photo');
|
||
foreach ($photos as $photo) {
|
||
$multipart[] = [
|
||
'name' => 'photo[]',
|
||
'contents' => fopen($photo->path(), 'r'),
|
||
'filename' => $photo->getClientOriginalName(),
|
||
];
|
||
}
|
||
}
|
||
if ($request->input('in-reply-to') != '') {
|
||
$multipart[] = [
|
||
'name' => 'in-reply-to',
|
||
'contents' => $request->input('in-reply-to'),
|
||
];
|
||
}
|
||
if ($request->input('syndicate-to')) {
|
||
foreach ($request->input('syndicate-to') as $syn) {
|
||
$multipart[] = [
|
||
'name' => 'syndicate-to[]',
|
||
'contents' => $syn,
|
||
];
|
||
}
|
||
}
|
||
if ($request->input('location')) {
|
||
if ($request->input('location') !== 'no-location') {
|
||
$multipart[] = [
|
||
'name' => 'location',
|
||
'contents' => $request->input('location'),
|
||
];
|
||
}
|
||
}
|
||
$headers = [
|
||
'Authorization' => 'Bearer ' . $token,
|
||
];
|
||
try {
|
||
$response = $this->guzzleClient->post($micropubEndpoint, [
|
||
'multipart' => $multipart,
|
||
'headers' => $headers,
|
||
]);
|
||
} catch (\GuzzleHttp\Exception\BadResponseException $e) {
|
||
return redirect('notes/new')
|
||
->withErrors('There was a bad response from the micropub endpoint.', 'endpoint');
|
||
}
|
||
|
||
return $response;
|
||
}
|
||
|
||
/**
|
||
* Create a new place.
|
||
*
|
||
* @param \Illuminate\Http\Request $request
|
||
* @return mixed
|
||
*/
|
||
public function postNewPlace(Request $request)
|
||
{
|
||
if ($request->session()->has('token') === false) {
|
||
return response()->json([
|
||
'error' => true,
|
||
'error_description' => 'No known token',
|
||
], 400);
|
||
}
|
||
$domain = $request->session()->get('me');
|
||
$token = $request->session()->get('token');
|
||
|
||
$micropubEndpoint = $this->indieAuthService->discoverMicropubEndpoint($domain, $this->indieClient);
|
||
if (! $micropubEndpoint) {
|
||
return response()->json([
|
||
'error' => true,
|
||
'error_description' => 'Could not determine the micropub endpoint.',
|
||
], 400);
|
||
}
|
||
|
||
$place = $this->postPlaceRequest($request, $micropubEndpoint, $token);
|
||
if ($place === false) {
|
||
return response()->json([
|
||
'error' => true,
|
||
'error_description' => 'Unable to create the new place',
|
||
], 400);
|
||
}
|
||
|
||
return response()->json([
|
||
'uri' => $place,
|
||
'name' => $request->input('place-name'),
|
||
'latitude' => $request->input('place-latitude'),
|
||
'longitude' => $request->input('place-longitude'),
|
||
]);
|
||
}
|
||
|
||
/**
|
||
* Actually make a micropub request to make a new place.
|
||
*
|
||
* @param \Illuminate\Http\Request $request
|
||
* @param string The Micropub endpoint to post to
|
||
* @param string The token to authenticate the request with
|
||
* @param \GuzzleHttp\Client $client
|
||
* @return \GuzzleHttp\Response $response | \Illuminate\RedirectFactory redirect
|
||
*/
|
||
private function postPlaceRequest(
|
||
Request $request,
|
||
$micropubEndpoint,
|
||
$token
|
||
) {
|
||
$formParams = [
|
||
'h' => 'card',
|
||
'name' => $request->input('place-name'),
|
||
'description' => $request->input('place-description'),
|
||
'geo' => 'geo:' . $request->input('place-latitude') . ',' . $request->input('place-longitude'),
|
||
];
|
||
$headers = [
|
||
'Authorization' => 'Bearer ' . $token,
|
||
];
|
||
try {
|
||
$response = $this->guzzleClient->request('POST', $micropubEndpoint, [
|
||
'form_params' => $formParams,
|
||
'headers' => $headers,
|
||
]);
|
||
} catch (ClientException $e) {
|
||
return false;
|
||
}
|
||
if ($response->getStatusCode() == 201) {
|
||
return $response->getHeader('Location')[0];
|
||
}
|
||
|
||
return false;
|
||
}
|
||
|
||
/**
|
||
* Make a request to the micropub endpoint requesting any nearby places.
|
||
*
|
||
* @param \Illuminate\Http\Request $request
|
||
* @param string $latitude
|
||
* @param string $longitude
|
||
* @return \Illuminate\Http\Response
|
||
*/
|
||
public function nearbyPlaces(
|
||
Request $request,
|
||
$latitude,
|
||
$longitude
|
||
) {
|
||
if ($request->session()->has('token') === false) {
|
||
return response()->json([
|
||
'error' => true,
|
||
'error_description' => 'No known token',
|
||
], 400);
|
||
}
|
||
$domain = $request->session()->get('me');
|
||
$token = $request->session()->get('token');
|
||
|
||
$micropubEndpoint = $this->indieAuthService->discoverMicropubEndpoint($domain, $this->indieClient);
|
||
|
||
if (! $micropubEndpoint) {
|
||
return response()->json([
|
||
'error' => true,
|
||
'error_description' => 'No known endpoint',
|
||
], 400);
|
||
}
|
||
|
||
try {
|
||
$query = 'geo:' . $latitude . ',' . $longitude;
|
||
if ($request->input('u') !== null) {
|
||
$query .= ';u=' . $request->input('u');
|
||
}
|
||
$response = $this->guzzleClient->get($micropubEndpoint, [
|
||
'headers' => ['Authorization' => 'Bearer ' . $token],
|
||
'query' => ['q' => $query],
|
||
]);
|
||
} catch (\GuzzleHttp\Exception\BadResponseException $e) {
|
||
Log::info($e->getResponse()->getBody());
|
||
|
||
return response()->json([
|
||
'error' => true,
|
||
'error_description' => 'The endpoint ' . $micropubEndpoint . ' returned a non-good response',
|
||
], 400);
|
||
}
|
||
|
||
return (new Response($response->getBody(), 200))
|
||
->header('Content-Type', 'application/json');
|
||
}
|
||
|
||
/**
|
||
* Parse the syndication targets retreived from a cookie, to a form that can
|
||
* be used in a view.
|
||
*
|
||
* @param string $syndicationTargets
|
||
* @return array|null
|
||
*/
|
||
private function parseSyndicationTargets($syndicationTargets = null)
|
||
{
|
||
if ($syndicationTargets === null) {
|
||
return;
|
||
}
|
||
$syndicateTo = [];
|
||
$data = json_decode($syndicationTargets, true);
|
||
if (array_key_exists('syndicate-to', $data)) {
|
||
foreach ($data['syndicate-to'] as $syn) {
|
||
$syndicateTo[] = [
|
||
'target' => $syn['uid'],
|
||
'name' => $syn['name'],
|
||
];
|
||
}
|
||
}
|
||
if (count($syndicateTo) > 0) {
|
||
return $syndicateTo;
|
||
}
|
||
}
|
||
}
|