diff --git a/app/Exceptions/Handler.php b/app/Exceptions/Handler.php index 0704b84f..2ad2cd9a 100644 --- a/app/Exceptions/Handler.php +++ b/app/Exceptions/Handler.php @@ -6,6 +6,7 @@ use Exception; use Illuminate\Validation\ValidationException; use Illuminate\Session\TokenMismatchException; use Illuminate\Auth\Access\AuthorizationException; +use Symfony\Component\Debug\Exception\FlattenException; use Illuminate\Database\Eloquent\ModelNotFoundException; use Symfony\Component\HttpKernel\Exception\HttpException; use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler; @@ -78,10 +79,12 @@ class Handler extends ExceptionHandler }); $whoops->pushHandler($handler); + $flattened = FlattenException::create($exc); + return new \Illuminate\Http\Response( $whoops->handleException($exc), - $exc->getStatusCode(), - $exc->getHeaders() + $flattened->getStatusCode(), + $flattened->getHeaders() ); } } diff --git a/app/Http/Controllers/MicropubClientController.php b/app/Http/Controllers/MicropubClientController.php index 9978d985..858822fb 100644 --- a/app/Http/Controllers/MicropubClientController.php +++ b/app/Http/Controllers/MicropubClientController.php @@ -160,10 +160,10 @@ class MicropubClientController extends Controller 'contents' => $request->input('reply-to'), ]; } - if ($request->input('mp-syndicate-to')) { - foreach ($request->input('mp-syndicate-to') as $syn) { + if ($request->input('syndicate-to')) { + foreach ($request->input('syndicate-to') as $syn) { $multipart[] = [ - 'name' => 'mp-syndicate-to', + 'name' => 'syndicate-to', 'contents' => $syn, ]; } @@ -320,14 +320,14 @@ class MicropubClientController extends Controller if ($syndicationTargets === null) { return; } - $mpSyndicateTo = []; + $syndicateTo = []; $parts = explode(';', $syndicationTargets); foreach ($parts as $part) { $target = explode('=', $part); - $mpSyndicateTo[] = urldecode($target[1]); + $syndicateTo[] = urldecode($target[1]); } - if (count($mpSyndicateTo) > 0) { - return $mpSyndicateTo; + if (count($syndicateTo) > 0) { + return $syndicateTo; } } } diff --git a/app/Http/Controllers/MicropubController.php b/app/Http/Controllers/MicropubController.php index 1a941125..b348ade1 100644 --- a/app/Http/Controllers/MicropubController.php +++ b/app/Http/Controllers/MicropubController.php @@ -109,7 +109,7 @@ class MicropubController extends Controller //we have a valid token, is `syndicate-to` set? if ($request->input('q') === 'syndicate-to') { $content = http_build_query([ - 'mp-syndicate-to' => 'twitter.com/jonnybarnes', + 'syndicate-to' => 'twitter.com/jonnybarnes', ]); return (new Response($content, 200)) diff --git a/app/Http/Controllers/NotesAdminController.php b/app/Http/Controllers/NotesAdminController.php index 6fd48096..c8841d4b 100644 --- a/app/Http/Controllers/NotesAdminController.php +++ b/app/Http/Controllers/NotesAdminController.php @@ -9,6 +9,13 @@ use App\Services\NoteService; class NotesAdminController extends Controller { + protected $noteService; + + public function __construct(NoteService $noteService = null) + { + $this->noteService = $noteService ?? new NoteService(); + } + /** * Show the form to make a new note. * diff --git a/app/Http/Controllers/WebMentionsController.php b/app/Http/Controllers/WebMentionsController.php index ccffd451..fc254058 100644 --- a/app/Http/Controllers/WebMentionsController.php +++ b/app/Http/Controllers/WebMentionsController.php @@ -5,7 +5,6 @@ namespace App\Http\Controllers; use App\Note; use Illuminate\Http\Request; use Illuminate\Http\Response; -use App\Jobs\SendWebMentions; use App\Jobs\ProcessWebMention; use Jonnybarnes\IndieWeb\Numbers; use Illuminate\Database\Eloquent\ModelNotFoundException; @@ -64,37 +63,4 @@ class WebMentionsController extends Controller break; } } - - /** - * Send a webmention. - * - * @param \App\Note $note - * @return array An array of successful then failed URLs - */ - public function send(Note $note) - { - //grab the URLs - $urlsInReplyTo = explode(' ', $note->in_reply_to); - $urlsNote = $this->getLinks($note->note); - $urls = array_filter(array_merge($urlsInReplyTo, $urlsNote)); //filter out none URLs - foreach ($urls as $url) { - $this->dispatch(new SendWebMentions($url, $note->longurl)); - } - } - - /** - * Get the URLs from a note. - */ - private function getLinks($html) - { - $urls = []; - $dom = new \DOMDocument(); - $dom->loadHTML($html); - $anchors = $dom->getElementsByTagName('a'); - foreach ($anchors as $anchor) { - $urls[] = ($anchor->hasAttribute('href')) ? $anchor->getAttribute('href') : false; - } - - return $urls; - } } diff --git a/app/Jobs/SendWebMentions.php b/app/Jobs/SendWebMentions.php index 796fc97c..98ae4431 100644 --- a/app/Jobs/SendWebMentions.php +++ b/app/Jobs/SendWebMentions.php @@ -2,6 +2,7 @@ namespace App\Jobs; +use App\Note; use GuzzleHttp\Client; use Illuminate\Queue\SerializesModels; use Illuminate\Queue\InteractsWithQueue; @@ -11,35 +12,41 @@ class SendWebMentions extends Job implements ShouldQueue { use InteractsWithQueue, SerializesModels; - protected $url; - protected $source; + protected $note; /** - * Create a new job instance. + * Create the job instance, inject dependencies. * + * @param Note $note * @return void */ - public function __construct($url, $source) + public function __construct(Note $note) { - $this->url = $url; - $this->source = $source; + $this->note = $note; } /** * Execute the job. * + * @param \GuzzleHttp\Client $guzzle * @return void */ - public function handle(Client $client) + public function handle(Client $guzzle) { - $endpoint = $this->discoverWebmentionEndpoint($this->url, $client); - if ($endpoint) { - $client->post($endpoint, [ - 'form_params' => [ - 'source' => $this->source, - 'target' => $this->url, - ], - ]); + //grab the URLs + $urlsInReplyTo = explode(' ', $this->note->in_reply_to); + $urlsNote = $this->getLinks($this->note->note); + $urls = array_filter(array_merge($urlsInReplyTo, $urlsNote)); //filter out none URLs + foreach ($urls as $url) { + $endpoint = $this->discoverWebmentionEndpoint($url, $guzzle); + if ($endpoint) { + $guzzle->post($endpoint, [ + 'form_params' => [ + 'source' => $this->note->longurl, + 'target' => $url, + ], + ]); + } } } @@ -47,14 +54,19 @@ class SendWebMentions extends Job implements ShouldQueue * Discover if a URL has a webmention endpoint. * * @param string The URL - * @param \GuzzleHttp\Client $client + * @param \GuzzleHttp\Client $guzzle * @return string The webmention endpoint URL */ - private function discoverWebmentionEndpoint($url, $client) + private function discoverWebmentionEndpoint($url, $guzzle) { + //let’s not send webmentions to myself + if (parse_url($url, PHP_URL_HOST) == env('LONG_URL', 'localhost')) { + return false; + } + $endpoint = null; - $response = $client->get($url); + $response = $guzzle->get($url); //check HTTP Headers for webmention endpoint $links = \GuzzleHttp\Psr7\parse_header($response->getHeader('Link')); foreach ($links as $link) { @@ -83,4 +95,23 @@ class SendWebMentions extends Job implements ShouldQueue return false; } + + /** + * Get the URLs from a note. + * + * @param string $html + * @return array $urls + */ + private function getLinks($html) + { + $urls = []; + $dom = new \DOMDocument(); + $dom->loadHTML($html); + $anchors = $dom->getElementsByTagName('a'); + foreach ($anchors as $anchor) { + $urls[] = ($anchor->hasAttribute('href')) ? $anchor->getAttribute('href') : false; + } + + return $urls; + } } diff --git a/app/Services/NoteService.php b/app/Services/NoteService.php index 0b680090..defa5330 100644 --- a/app/Services/NoteService.php +++ b/app/Services/NoteService.php @@ -5,9 +5,9 @@ namespace App\Services; use App\Note; use App\Place; use Illuminate\Http\Request; +use App\Jobs\SendWebMentions; use App\Jobs\SyndicateToTwitter; use Illuminate\Foundation\Bus\DispatchesJobs; -use App\Http\Controllers\WebMentionsController; class NoteService { @@ -45,10 +45,7 @@ class NoteService } } - if ($request->input('webmentions')) { - $wmc = new WebMentionsController(); - $wmc->send($note); - } + $this->dispatch(new SendWebMentions($note)); if (//micropub request, syndication sent as array (is_array($request->input('mp-syndicate-to')) diff --git a/changelog.md b/changelog.md index 1df607d8..856eb7ca 100644 --- a/changelog.md +++ b/changelog.md @@ -1,5 +1,9 @@ # Changelog +## Version 0.0.5 (2016-06-23) + - Automatically send webmentions + - Change `mp-syndicate-to` to `syndicate-to` + ## Version 0.0.4 (2016-06-21) - Move bower components into their own subdir - Move my js into `resources/`, apply an eslint pre-commit hook diff --git a/composer.lock b/composer.lock index 33b1209c..bd5ed773 100644 --- a/composer.lock +++ b/composer.lock @@ -59,16 +59,16 @@ }, { "name": "aws/aws-sdk-php", - "version": "3.18.18", + "version": "3.18.19", "source": { "type": "git", "url": "https://github.com/aws/aws-sdk-php.git", - "reference": "68b9d0b7e007782bc0f2633cdf5a4a6bf08aaafc" + "reference": "2ffb032afe91b143293f75b48ec7593659c66ddb" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/68b9d0b7e007782bc0f2633cdf5a4a6bf08aaafc", - "reference": "68b9d0b7e007782bc0f2633cdf5a4a6bf08aaafc", + "url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/2ffb032afe91b143293f75b48ec7593659c66ddb", + "reference": "2ffb032afe91b143293f75b48ec7593659c66ddb", "shasum": "" }, "require": { @@ -135,7 +135,7 @@ "s3", "sdk" ], - "time": "2016-06-14 20:35:03" + "time": "2016-06-21 21:41:45" }, { "name": "barnabywalters/mf-cleaner", @@ -1470,16 +1470,16 @@ }, { "name": "league/flysystem-aws-s3-v3", - "version": "1.0.12", + "version": "1.0.13", "source": { "type": "git", "url": "https://github.com/thephpleague/flysystem-aws-s3-v3.git", - "reference": "d9c27edda5b4b2840c3f602d4ce6fbfeaab10e5a" + "reference": "dc56a8faf3aff0841f9eae04b6af94a50657896c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/thephpleague/flysystem-aws-s3-v3/zipball/d9c27edda5b4b2840c3f602d4ce6fbfeaab10e5a", - "reference": "d9c27edda5b4b2840c3f602d4ce6fbfeaab10e5a", + "url": "https://api.github.com/repos/thephpleague/flysystem-aws-s3-v3/zipball/dc56a8faf3aff0841f9eae04b6af94a50657896c", + "reference": "dc56a8faf3aff0841f9eae04b6af94a50657896c", "shasum": "" }, "require": { @@ -1513,7 +1513,7 @@ } ], "description": "Flysystem adapter for the AWS S3 SDK v3.x", - "time": "2016-06-06 11:18:47" + "time": "2016-06-21 21:34:35" }, { "name": "league/glide", @@ -2437,16 +2437,16 @@ }, { "name": "spatie/laravel-medialibrary", - "version": "4.2.1", + "version": "4.3.0", "source": { "type": "git", "url": "https://github.com/spatie/laravel-medialibrary.git", - "reference": "3499014e3b2de852f1e5f4bd4006e4031dd49daa" + "reference": "d5ec391023ea27c78131f2d1823908d45f9e38ae" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/spatie/laravel-medialibrary/zipball/3499014e3b2de852f1e5f4bd4006e4031dd49daa", - "reference": "3499014e3b2de852f1e5f4bd4006e4031dd49daa", + "url": "https://api.github.com/repos/spatie/laravel-medialibrary/zipball/d5ec391023ea27c78131f2d1823908d45f9e38ae", + "reference": "d5ec391023ea27c78131f2d1823908d45f9e38ae", "shasum": "" }, "require": { @@ -2493,7 +2493,7 @@ "media", "spatie" ], - "time": "2016-06-03 11:06:43" + "time": "2016-06-23 08:22:21" }, { "name": "spatie/pdf-to-image", diff --git a/resources/views/templates/new-note-form.blade.php b/resources/views/templates/new-note-form.blade.php index e0c55ca2..17d976eb 100644 --- a/resources/views/templates/new-note-form.blade.php +++ b/resources/views/templates/new-note-form.blade.php @@ -4,9 +4,8 @@ New Note -
@if ($micropub === true) - @if($syndication)@endif + @if($syndication)@endif Refresh Syndication Targets
@endif diff --git a/tests/MicropubTest.php b/tests/MicropubTest.php index 1cac5657..1854f3fb 100644 --- a/tests/MicropubTest.php +++ b/tests/MicropubTest.php @@ -38,7 +38,7 @@ class MicropubTest extends TestCase public function testMicropubRequestWithValidToken() { $this->call('GET', $this->appurl . '/api/post', [], [], [], ['HTTP_Authorization' => 'Bearer ' . $this->getToken()]); - $this->see('me=https%3A%2F%2Fjbl5.dev'); + $this->see('me=https%3A%2F%2Fjonnybarnes.localhost'); } public function testMicropubRequestForSyndication() @@ -79,8 +79,6 @@ class MicropubTest extends TestCase public function testMicropubRequestCreateNewPlace() { - $faker = \Faker\Factory::create(); - $note = $faker->text; $this->call( 'POST', $this->appurl . '/api/post', @@ -101,7 +99,7 @@ class MicropubTest extends TestCase $signer = new Sha256(); $token = (new Builder()) ->set('client_id', 'https://quill.p3k.io') - ->set('me', 'https://jbl5.dev') + ->set('me', 'https://jonnybarnes.localhost') ->set('scope', 'post') ->set('issued_at', time()) ->sign($signer, env('APP_KEY')) diff --git a/tests/NotesAdminTest.php b/tests/NotesAdminTest.php new file mode 100644 index 00000000..06da88ce --- /dev/null +++ b/tests/NotesAdminTest.php @@ -0,0 +1,33 @@ +appurl = config('app.url'); + $this->notesAdminController = new \App\Http\Controllers\NotesAdminController(); + } + + public function testCreatedNoteDispatchesSendWebmentionsJob() + { + $this->expectsJobs(\App\Jobs\SendWebMentions::class); + + $this->withSession(['loggedin' => true]) + ->visit($this->appurl . '/admin/note/new') + ->type('Mentioning', 'content') + ->press('Submit'); + } +}