diff --git a/.env.travis b/.env.travis index a160c615..766e9ed8 100644 --- a/.env.travis +++ b/.env.travis @@ -1,9 +1,9 @@ APP_ENV=testing APP_DEBUG=true APP_KEY=base64:6DJhvZLVjE6dD4Cqrteh+6Z5vZlG+v/soCKcDHLOAH0= -APP_URL=http://localhost:8000 -APP_LONGURL=localhost -APP_SHORTURL=local +APP_URL=http://jonnybarnes.localhost:8000 +APP_LONGURL=jonnybarnes.localhost +APP_SHORTURL=jmb.localhost DB_CONNECTION=travis diff --git a/.travis.yml b/.travis.yml index 5240b18d..68e984a2 100644 --- a/.travis.yml +++ b/.travis.yml @@ -7,12 +7,13 @@ cache: - apt addons: + hosts: + - jmb.localhost + - jonnybarnes.localhost postgresql: "9.6" apt: - sources: - - sourceline: 'deb http://ppa.launchpad.net/nginx/development/ubuntu trusty main' packages: - - nginx + - nginx-full - realpath - postgresql-9.6-postgis-2.3 - imagemagick @@ -36,10 +37,6 @@ php: - 7.1 - 7.2 -matrix: - allow_failures: - - php: 7.2 - before_install: - printf "\n" | pecl install imagick - cp .env.travis .env @@ -67,7 +64,10 @@ before_script: #- sleep 5 script: - - php vendor/bin/phpunit --coverage-text + - php vendor/bin/phpunit --coverage-clover build/logs/clover.xml - phpcs #- php artisan dusk - php vendor/bin/security-checker security:check --end-point=http://security.sensiolabs.org/check_lock + +after_success: + - travis_retry php vendor/bin/coveralls diff --git a/app/Article.php b/app/Article.php index 22d8b5e8..7a1d4c71 100644 --- a/app/Article.php +++ b/app/Article.php @@ -17,7 +17,7 @@ class Article extends Model * * @var array */ - protected $dates = ['deleted_at']; + protected $dates = ['created_at', 'updated_at', 'deleted_at']; /** * The database table used by the model. @@ -40,16 +40,6 @@ class Article extends Model ]; } - /** - * Define the relationship with webmentions. - * - * @var array - */ - public function webmentions() - { - return $this->morphMany('App\WebMention', 'commentable'); - } - /** * We shall set a blacklist of non-modifiable model attributes. * @@ -66,7 +56,7 @@ class Article extends Model { $markdown = new CommonMarkConverter(); $html = $markdown->convertToHtml($this->main); - //change
[lang] ~>
+ // changes [lang] ~>
$match = '/\[(.*)\]\n/';
$replace = '';
$text = preg_replace($match, $replace, $html);
@@ -130,20 +120,20 @@ class Article extends Model
*
* @return \Illuminate\Database\Eloquent\Builder
*/
- public function scopeDate($query, $year = null, $month = null)
+ public function scopeDate($query, int $year = null, int $month = null)
{
if ($year == null) {
return $query;
}
$start = $year . '-01-01 00:00:00';
$end = ($year + 1) . '-01-01 00:00:00';
- if (($month !== null) && ($month !== '12')) {
+ if (($month !== null) && ($month !== 12)) {
$start = $year . '-' . $month . '-01 00:00:00';
$end = $year . '-' . ($month + 1) . '-01 00:00:00';
}
- if ($month === '12') {
+ if ($month === 12) {
$start = $year . '-12-01 00:00:00';
- //$end as above
+ $end = ($year + 1) . '-01-01 00:00:00';
}
return $query->where([
diff --git a/app/Console/Commands/SecurityCheck.php b/app/Console/Commands/SecurityCheck.php
index c2888b0f..6b60caa1 100644
--- a/app/Console/Commands/SecurityCheck.php
+++ b/app/Console/Commands/SecurityCheck.php
@@ -5,6 +5,9 @@ namespace App\Console\Commands;
use Illuminate\Console\Command;
use SensioLabs\Security\SecurityChecker;
+/**
+ * @codeCoverageIgnore
+ */
class SecurityCheck extends Command
{
/**
diff --git a/app/Exceptions/Handler.php b/app/Exceptions/Handler.php
index 500911a0..971523ba 100644
--- a/app/Exceptions/Handler.php
+++ b/app/Exceptions/Handler.php
@@ -7,6 +7,9 @@ use Illuminate\Support\Facades\Route;
use Illuminate\Session\TokenMismatchException;
use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler;
+/**
+ * @codeCoverageIgnore
+ */
class Handler extends ExceptionHandler
{
/**
diff --git a/app/Exceptions/InternetArchiveErrorSavingException.php b/app/Exceptions/InternetArchiveErrorSavingException.php
deleted file mode 100644
index 939a79ed..00000000
--- a/app/Exceptions/InternetArchiveErrorSavingException.php
+++ /dev/null
@@ -1,10 +0,0 @@
-delete();
+ MicropubClient::where('id', $clientId)->delete();
return redirect('/admin/clients');
}
diff --git a/app/Http/Controllers/Admin/ContactsController.php b/app/Http/Controllers/Admin/ContactsController.php
index b77b630b..6e6b6927 100644
--- a/app/Http/Controllers/Admin/ContactsController.php
+++ b/app/Http/Controllers/Admin/ContactsController.php
@@ -83,16 +83,14 @@ class ContactsController extends Controller
$contact->facebook = $request->input('facebook');
$contact->save();
- if ($request->hasFile('avatar')) {
- if ($request->input('homepage') != '') {
- $dir = parse_url($request->input('homepage'))['host'];
- $destination = public_path() . '/assets/profile-images/' . $dir;
- $filesystem = new Filesystem();
- if ($filesystem->isDirectory($destination) === false) {
- $filesystem->makeDirectory($destination);
- }
- $request->file('avatar')->move($destination, 'image');
+ if ($request->hasFile('avatar') && ($request->input('homepage') != '')) {
+ $dir = parse_url($request->input('homepage'), PHP_URL_HOST);
+ $destination = public_path() . '/assets/profile-images/' . $dir;
+ $filesystem = new Filesystem();
+ if ($filesystem->isDirectory($destination) === false) {
+ $filesystem->makeDirectory($destination);
}
+ $request->file('avatar')->move($destination, 'image');
}
return redirect('/admin/contacts');
@@ -123,37 +121,47 @@ class ContactsController extends Controller
*/
public function getAvatar($contactId)
{
+ // Initialising
+ $avatarURL = null;
+ $avatar = null;
$contact = Contact::findOrFail($contactId);
- $homepage = $contact->homepage;
- if (($homepage !== null) && ($homepage !== '')) {
- $client = new Client();
+ if (mb_strlen($contact->homepage !== null) !== 0) {
+ $client = resolve(Client::class);
try {
- $response = $client->get($homepage);
- $html = (string) $response->getBody();
- $mf2 = \Mf2\parse($html, $homepage);
+ $response = $client->get($contact->homepage);
} catch (\GuzzleHttp\Exception\BadResponseException $e) {
- return "Bad Response from $homepage";
+ return redirect('/admin/contacts/' . $contactId . '/edit')
+ ->with('error', 'Bad resposne from contact’s homepage');
}
- $avatarURL = null; // Initialising
+ $mf2 = \Mf2\parse((string) $response->getBody(), $contact->homepage);
foreach ($mf2['items'] as $microformat) {
- if ($microformat['type'][0] == 'h-card') {
- $avatarURL = $microformat['properties']['photo'][0];
+ if (array_get($microformat, 'type.0') == 'h-card') {
+ $avatarURL = array_get($microformat, 'properties.photo.0');
break;
}
}
- try {
- $avatar = $client->get($avatarURL);
- } catch (\GuzzleHttp\Exception\BadResponseException $e) {
- return "Unable to get $avatarURL";
+ if ($avatarURL !== null) {
+ try {
+ $avatar = $client->get($avatarURL);
+ } catch (\GuzzleHttp\Exception\BadResponseException $e) {
+ return redirect('/admin/contacts/' . $contactId . '/edit')
+ ->with('error', 'Unable to download avatar');
+ }
}
- $directory = public_path() . '/assets/profile-images/' . parse_url($homepage)['host'];
- $filesystem = new Filesystem();
- if ($filesystem->isDirectory($directory) === false) {
- $filesystem->makeDirectory($directory);
- }
- $filesystem->put($directory . '/image', $avatar->getBody());
+ if ($avatar !== null) {
+ $directory = public_path() . '/assets/profile-images/' . parse_url($contact->homepage, PHP_URL_HOST);
+ $filesystem = new Filesystem();
+ if ($filesystem->isDirectory($directory) === false) {
+ $filesystem->makeDirectory($directory);
+ }
+ $filesystem->put($directory . '/image', $avatar->getBody());
- return view('admin.contacts.getavatarsuccess', ['homepage' => parse_url($homepage)['host']]);
+ return view('admin.contacts.getavatarsuccess', [
+ 'homepage' => parse_url($contact->homepage, PHP_URL_HOST),
+ ]);
+ }
}
+
+ return redirect('/admin/contacts/' . $contactId . '/edit');
}
}
diff --git a/app/Http/Controllers/Admin/NotesController.php b/app/Http/Controllers/Admin/NotesController.php
index 0ace90fb..951e0841 100644
--- a/app/Http/Controllers/Admin/NotesController.php
+++ b/app/Http/Controllers/Admin/NotesController.php
@@ -3,21 +3,12 @@
namespace App\Http\Controllers\Admin;
use App\Note;
-use Validator;
use Illuminate\Http\Request;
use App\Jobs\SendWebMentions;
-use App\Services\NoteService;
use App\Http\Controllers\Controller;
class NotesController extends Controller
{
- protected $noteService;
-
- public function __construct(NoteService $noteService)
- {
- $this->noteService = $noteService;
- }
-
/**
* List the notes that can be edited.
*
@@ -51,30 +42,10 @@ class NotesController extends Controller
*/
public function store(Request $request)
{
- $validator = Validator::make(
- $request->all(),
- ['photo' => 'photosize'],
- ['photosize' => 'At least one uploaded file exceeds size limit of 5MB']
- );
- if ($validator->fails()) {
- return redirect('/admin/notes/create')
- ->withErrors($validator)
- ->withInput();
- }
-
- $data = [];
- $data['content'] = $request->input('content');
- $data['in-reply-to'] = $request->input('in-reply-to');
- $data['location'] = $request->input('location');
- $data['syndicate'] = [];
- if ($request->input('twitter')) {
- $data['syndicate'][] = 'twitter';
- }
- if ($request->input('facebook')) {
- $data['syndicate'][] = 'facebook';
- }
-
- $note = $this->noteService->createNote($data);
+ Note::create([
+ 'in-reply-to' => $request->input('in-reply-to'),
+ 'note' => $request->input('content'),
+ ]);
return redirect('/admin/notes');
}
diff --git a/app/Http/Controllers/Admin/PlacesController.php b/app/Http/Controllers/Admin/PlacesController.php
index 9d1ef100..f08b0c49 100644
--- a/app/Http/Controllers/Admin/PlacesController.php
+++ b/app/Http/Controllers/Admin/PlacesController.php
@@ -47,11 +47,7 @@ class PlacesController extends Controller
*/
public function store(Request $request)
{
- $data = [];
- $data['name'] = $request->name;
- $data['description'] = $request->description;
- $data['latitude'] = $request->latitude;
- $data['longitude'] = $request->longitude;
+ $data = $request->only(['name', 'description', 'latitude', 'longitude']);
$place = $this->placeService->createPlace($data);
return redirect('/admin/places');
@@ -67,14 +63,7 @@ class PlacesController extends Controller
{
$place = Place::findOrFail($placeId);
- return view('admin.places.edit', [
- 'id' => $placeId,
- 'name' => $place->name,
- 'description' => $place->description,
- 'latitude' => $place->latitude,
- 'longitude' => $place->longitude,
- 'icon' => $place->icon ?? 'marker',
- ]);
+ return view('admin.places.edit', compact('place'));
}
/**
diff --git a/app/Http/Controllers/ArticlesController.php b/app/Http/Controllers/ArticlesController.php
index 77a35ef5..127f7e3b 100644
--- a/app/Http/Controllers/ArticlesController.php
+++ b/app/Http/Controllers/ArticlesController.php
@@ -15,7 +15,7 @@ class ArticlesController extends Controller
public function index($year = null, $month = null)
{
$articles = Article::where('published', '1')
- ->date($year, $month)
+ ->date((int) $year, (int) $month)
->orderBy('updated_at', 'desc')
->simplePaginate(5);
@@ -31,7 +31,7 @@ class ArticlesController extends Controller
{
$article = Article::where('titleurl', $slug)->firstOrFail();
if ($article->updated_at->year != $year || $article->updated_at->month != $month) {
- throw new \Exception;
+ return redirect('/blog/' . $article->updated_at->year . '/' . $article->updated_at->month .'/' . $slug);
}
return view('articles.show', compact('article'));
diff --git a/app/Http/Controllers/Auth/ForgotPasswordController.php b/app/Http/Controllers/Auth/ForgotPasswordController.php
deleted file mode 100644
index 6a247fef..00000000
--- a/app/Http/Controllers/Auth/ForgotPasswordController.php
+++ /dev/null
@@ -1,32 +0,0 @@
-middleware('guest');
- }
-}
diff --git a/app/Http/Controllers/Auth/LoginController.php b/app/Http/Controllers/Auth/LoginController.php
deleted file mode 100644
index b2ea669a..00000000
--- a/app/Http/Controllers/Auth/LoginController.php
+++ /dev/null
@@ -1,39 +0,0 @@
-middleware('guest')->except('logout');
- }
-}
diff --git a/app/Http/Controllers/Auth/RegisterController.php b/app/Http/Controllers/Auth/RegisterController.php
deleted file mode 100644
index f77265ab..00000000
--- a/app/Http/Controllers/Auth/RegisterController.php
+++ /dev/null
@@ -1,71 +0,0 @@
-middleware('guest');
- }
-
- /**
- * Get a validator for an incoming registration request.
- *
- * @param array $data
- * @return \Illuminate\Contracts\Validation\Validator
- */
- protected function validator(array $data)
- {
- return Validator::make($data, [
- 'name' => 'required|string|max:255',
- 'email' => 'required|string|email|max:255|unique:users',
- 'password' => 'required|string|min:6|confirmed',
- ]);
- }
-
- /**
- * Create a new user instance after a valid registration.
- *
- * @param array $data
- * @return \App\User
- */
- protected function create(array $data)
- {
- return User::create([
- 'name' => $data['name'],
- 'email' => $data['email'],
- 'password' => bcrypt($data['password']),
- ]);
- }
-}
diff --git a/app/Http/Controllers/Auth/ResetPasswordController.php b/app/Http/Controllers/Auth/ResetPasswordController.php
deleted file mode 100644
index cf726eec..00000000
--- a/app/Http/Controllers/Auth/ResetPasswordController.php
+++ /dev/null
@@ -1,39 +0,0 @@
-middleware('guest');
- }
-}
diff --git a/app/Http/Controllers/MicropubController.php b/app/Http/Controllers/MicropubController.php
index e1877bd3..b9471497 100644
--- a/app/Http/Controllers/MicropubController.php
+++ b/app/Http/Controllers/MicropubController.php
@@ -5,47 +5,41 @@ namespace App\Http\Controllers;
use Storage;
use Monolog\Logger;
use Ramsey\Uuid\Uuid;
-use App\Jobs\ProcessImage;
-use App\Services\LikeService;
-use App\Services\BookmarkService;
+use App\Jobs\ProcessMedia;
+use Illuminate\Http\UploadedFile;
use Monolog\Handler\StreamHandler;
use App\{Like, Media, Note, Place};
use Intervention\Image\ImageManager;
use Illuminate\Http\{Request, Response};
use App\Exceptions\InvalidTokenException;
use Phaza\LaravelPostgis\Geometries\Point;
-use Illuminate\Database\Eloquent\ModelNotFoundException;
-use Ramsey\Uuid\Exception\UnsatisfiedDependencyException;
+use Intervention\Image\Exception\NotReadableException;
use App\Services\{NoteService, PlaceService, TokenService};
+use App\Services\Micropub\{HCardService, HEntryService, UpdateService};
class MicropubController extends Controller
{
- /**
- * The Token service container.
- */
protected $tokenService;
-
- /**
- * The Note service container.
- */
protected $noteService;
-
- /**
- * The Place service container.
- */
protected $placeService;
+ protected $hentryService;
+ protected $hcardService;
+ protected $updateService;
- /**
- * Inject the dependencies.
- */
public function __construct(
TokenService $tokenService,
NoteService $noteService,
- PlaceService $placeService
+ PlaceService $placeService,
+ HEntryService $hentryService,
+ HCardService $hcardService,
+ UpdateService $updateService
) {
$this->tokenService = $tokenService;
$this->noteService = $noteService;
$this->placeService = $placeService;
+ $this->hentryService = $hentryService;
+ $this->hcardService = $hcardService;
+ $this->updateService = $updateService;
}
/**
@@ -60,262 +54,46 @@ class MicropubController extends Controller
try {
$tokenData = $this->tokenService->validateToken($request->bearerToken());
} catch (InvalidTokenException $e) {
+ return $this->invalidTokenResponse();
+ }
+
+ if ($tokenData->hasClaim('scope') === false) {
+ return $this->tokenHasNoScopeResponse();
+ }
+
+ $this->logMicropubRequest($request);
+
+ if (($request->input('h') == 'entry') || ($request->input('type.0') == 'h-entry')) {
+ if (stristr($tokenData->getClaim('scope'), 'create') === false) {
+ return $this->insufficientScopeResponse();
+ }
+ $location = $this->hentryService->process($request);
+
return response()->json([
- 'response' => 'error',
- 'error' => 'invalid_token',
- 'error_description' => 'The provided token did not pass validation',
- ], 400);
- }
- // Log the request
- $logger = new Logger('micropub');
- $logger->pushHandler(new StreamHandler(storage_path('logs/micropub.log')), Logger::DEBUG);
- $logger->debug('MicropubLog', $request->all());
- if ($tokenData->hasClaim('scope')) {
- if (($request->input('h') == 'entry') || ($request->input('type.0') == 'h-entry')) {
- if (stristr($tokenData->getClaim('scope'), 'create') === false) {
- return $this->returnInsufficientScopeResponse();
- }
- if ($request->has('properties.like-of') || $request->has('like-of')) {
- $like = (new LikeService())->createLike($request);
-
- return response()->json([
- 'response' => 'created',
- 'location' => config('app.url') . "/likes/$like->id",
- ], 201)->header('Location', config('app.url') . "/likes/$like->id");
- }
- if ($request->has('properties.bookmark-of') || $request->has('bookmark-of')) {
- $bookmark = (new BookmarkService())->createBookmark($request);
-
- return response()->json([
- 'response' => 'created',
- 'location' => config('app.url') . "/bookmarks/$bookmark->id",
- ], 201)->header('Location', config('app.url') . "/bookmarks/$bookmark->id");
- }
- $data = [];
- $data['client-id'] = $tokenData->getClaim('client_id');
- if ($request->header('Content-Type') == 'application/json') {
- if (is_string($request->input('properties.content.0'))) {
- $data['content'] = $request->input('properties.content.0'); //plaintext content
- }
- if (is_array($request->input('properties.content.0'))
- && array_key_exists('html', $request->input('properties.content.0'))
- ) {
- $data['content'] = $request->input('properties.content.0.html');
- }
- $data['in-reply-to'] = $request->input('properties.in-reply-to.0');
- // check location is geo: string
- if (is_string($request->input('properties.location.0'))) {
- $data['location'] = $request->input('properties.location.0');
- }
- // check location is h-card
- if (is_array($request->input('properties.location.0'))) {
- if ($request->input('properties.location.0.type.0' === 'h-card')) {
- try {
- $place = $this->placeService->createPlaceFromCheckin(
- $request->input('properties.location.0')
- );
- $data['checkin'] = $place->longurl;
- } catch (\Exception $e) {
- //
- }
- }
- }
- $data['published'] = $request->input('properties.published.0');
- //create checkin place
- if (array_key_exists('checkin', $request->input('properties'))) {
- $data['swarm-url'] = $request->input('properties.syndication.0');
- try {
- $place = $this->placeService->createPlaceFromCheckin(
- $request->input('properties.checkin.0')
- );
- $data['checkin'] = $place->longurl;
- } catch (\Exception $e) {
- $data['checkin'] = null;
- $data['swarm-url'] = null;
- }
- }
- } else {
- $data['content'] = $request->input('content');
- $data['in-reply-to'] = $request->input('in-reply-to');
- $data['location'] = $request->input('location');
- $data['published'] = $request->input('published');
- }
- $data['syndicate'] = [];
- $targets = array_pluck(config('syndication.targets'), 'uid', 'service.name');
- $mpSyndicateTo = null;
- if ($request->has('mp-syndicate-to')) {
- $mpSyndicateTo = $request->input('mp-syndicate-to');
- }
- if ($request->has('properties.mp-syndicate-to')) {
- $mpSyndicateTo = $request->input('properties.mp-syndicate-to');
- }
- if (is_string($mpSyndicateTo)) {
- $service = array_search($mpSyndicateTo, $targets);
- if ($service == 'Twitter') {
- $data['syndicate'][] = 'twitter';
- }
- if ($service == 'Facebook') {
- $data['syndicate'][] = 'facebook';
- }
- }
- if (is_array($mpSyndicateTo)) {
- foreach ($mpSyndicateTo as $uid) {
- $service = array_search($uid, $targets);
- if ($service == 'Twitter') {
- $data['syndicate'][] = 'twitter';
- }
- if ($service == 'Facebook') {
- $data['syndicate'][] = 'facebook';
- }
- }
- }
- $data['photo'] = [];
- $photos = null;
- if ($request->has('photo')) {
- $photos = $request->input('photo');
- }
- if ($request->has('properties.photo')) {
- $photos = $request->input('properties.photo');
- }
- if ($photos !== null) {
- foreach ($photos as $photo) {
- if (is_string($photo)) {
- //only supporting media URLs for now
- $data['photo'][] = $photo;
- }
- }
- if (starts_with($request->input('properties.syndication.0'), 'https://www.instagram.com')) {
- $data['instagram-url'] = $request->input('properties.syndication.0');
- }
- }
- try {
- $note = $this->noteService->createNote($data);
- } catch (\Exception $exception) {
- return response()->json(['error' => true], 400);
- }
-
- return response()->json([
- 'response' => 'created',
- 'location' => $note->longurl,
- ], 201)->header('Location', $note->longurl);
- }
- if ($request->input('h') == 'card' || $request->input('type')[0] == 'h-card') {
- if (stristr($tokenData->getClaim('scope'), 'create') === false) {
- return $this->returnInsufficientScopeResponse();
- }
- $data = [];
- if ($request->header('Content-Type') == 'application/json') {
- $data['name'] = $request->input('properties.name');
- $data['description'] = $request->input('properties.description') ?? null;
- if ($request->has('properties.geo')) {
- $data['geo'] = $request->input('properties.geo');
- }
- } else {
- $data['name'] = $request->input('name');
- $data['description'] = $request->input('description');
- if ($request->has('geo')) {
- $data['geo'] = $request->input('geo');
- }
- if ($request->has('latitude')) {
- $data['latitude'] = $request->input('latitude');
- $data['longitude'] = $request->input('longitude');
- }
- }
- try {
- $place = $this->placeService->createPlace($data);
- } catch (\Exception $exception) {
- return response()->json(['error' => true], 400);
- }
-
- return response()->json([
- 'response' => 'created',
- 'location' => $place->longurl,
- ], 201)->header('Location', $place->longurl);
- }
- if ($request->input('action') == 'update') {
- if (stristr($tokenData->getClaim('scope'), 'update') === false) {
- return $this->returnInsufficientScopeResponse();
- }
- $urlPath = parse_url($request->input('url'), PHP_URL_PATH);
- //is it a note we are updating?
- if (mb_substr($urlPath, 1, 5) === 'notes') {
- try {
- $note = Note::nb60(basename($urlPath))->firstOrFail();
- } catch (ModelNotFoundException $exception) {
- return response()->json([
- 'error' => 'invalid_request',
- 'error_description' => 'No known note with given ID',
- ]);
- }
- //got the note, are we dealing with a “replace” request?
- if ($request->has('replace')) {
- foreach ($request->input('replace') as $property => $value) {
- if ($property == 'content') {
- $note->note = $value[0];
- }
- if ($property == 'syndication') {
- foreach ($value as $syndicationURL) {
- if (starts_with($syndicationURL, 'https://www.facebook.com')) {
- $note->facebook_url = $syndicationURL;
- }
- if (starts_with($syndicationURL, 'https://www.swarmapp.com')) {
- $note->swarm_url = $syndicationURL;
- }
- if (starts_with($syndicationURL, 'https://twitter.com')) {
- $note->tweet_id = basename(parse_url($syndicationURL, PHP_URL_PATH));
- }
- }
- }
- }
- $note->save();
-
- return response()->json([
- 'response' => 'updated',
- ]);
- }
- //how about “add”
- if ($request->has('add')) {
- foreach ($request->input('add') as $property => $value) {
- if ($property == 'syndication') {
- foreach ($value as $syndicationURL) {
- if (starts_with($syndicationURL, 'https://www.facebook.com')) {
- $note->facebook_url = $syndicationURL;
- }
- if (starts_with($syndicationURL, 'https://www.swarmapp.com')) {
- $note->swarm_url = $syndicationURL;
- }
- if (starts_with($syndicationURL, 'https://twitter.com')) {
- $note->tweet_id = basename(parse_url($syndicationURL, PHP_URL_PATH));
- }
- }
- }
- if ($property == 'photo') {
- foreach ($value as $photoURL) {
- if (start_with($photo, 'https://')) {
- $media = new Media();
- $media->path = $photoURL;
- $media->type = 'image';
- $media->save();
- $note->media()->save($media);
- }
- }
- }
- }
- $note->save();
-
- return response()->json([
- 'response' => 'updated',
- ]);
- }
- }
- }
+ 'response' => 'created',
+ 'location' => $location,
+ ], 201)->header('Location', $location);
}
- return response()->json([
- 'response' => 'error',
- 'error' => 'forbidden',
- 'error_description' => 'The token has no scopes',
- ], 403);
+ if ($request->input('h') == 'card' || $request->input('type')[0] == 'h-card') {
+ if (stristr($tokenData->getClaim('scope'), 'create') === false) {
+ return $this->insufficientScopeResponse();
+ }
+ $location = $this->hcardService->process($request);
+
+ return response()->json([
+ 'response' => 'created',
+ 'location' => $location,
+ ], 201)->header('Location', $location);
+ }
+
+ if ($request->input('action') == 'update') {
+ if (stristr($tokenData->getClaim('scope'), 'update') === false) {
+ return $this->returnInsufficientScopeResponse();
+ }
+
+ return $this->updateService->process($request);
+ }
}
/**
@@ -332,20 +110,15 @@ class MicropubController extends Controller
try {
$tokenData = $this->tokenService->validateToken($request->bearerToken());
} catch (InvalidTokenException $e) {
- return response()->json([
- 'response' => 'error',
- 'error' => 'invalid_token',
- 'error_description' => 'The provided token did not pass validation',
- ], 400);
+ return $this->invalidTokenResponse();
}
- //we have a valid token, is `syndicate-to` set?
+
if ($request->input('q') === 'syndicate-to') {
return response()->json([
'syndicate-to' => config('syndication.targets'),
]);
}
- //nope, how about a config query?
if ($request->input('q') == 'config') {
return response()->json([
'syndicate-to' => config('syndication.targets'),
@@ -353,7 +126,6 @@ class MicropubController extends Controller
]);
}
- //nope, how about a geo URL?
if (substr($request->input('q'), 0, 4) === 'geo:') {
preg_match_all(
'/([0-9\.\-]+)/',
@@ -362,9 +134,6 @@ class MicropubController extends Controller
);
$distance = (count($matches[0]) == 3) ? 100 * $matches[0][2] : 1000;
$places = Place::near(new Point($matches[0][0], $matches[0][1]))->get();
- foreach ($places as $place) {
- $place->uri = config('app.url') . '/places/' . $place->slug;
- }
return response()->json([
'response' => 'places',
@@ -372,7 +141,7 @@ class MicropubController extends Controller
]);
}
- //nope, just return the token
+ // default response is just to return the token data
return response()->json([
'response' => 'token',
'token' => [
@@ -394,69 +163,18 @@ class MicropubController extends Controller
try {
$tokenData = $this->tokenService->validateToken($request->bearerToken());
} catch (InvalidTokenException $e) {
- return response()->json([
- 'response' => 'error',
- 'error' => 'invalid_token',
- 'error_description' => 'The provided token did not pass validation',
- ], 400);
+ return $this->invalidTokenResponse();
}
- $logger = new Logger('micropub');
- $logger->pushHandler(new StreamHandler(storage_path('logs/micropub.log')), Logger::DEBUG);
- $logger->debug('MicropubMediaLog', $request->all());
- //check post scope
- if ($tokenData->hasClaim('scope')) {
- if (stristr($tokenData->getClaim('scope'), 'create') === false) {
- return $this->returnInsufficientScopeResponse();
- }
- //check media valid
- if ($request->hasFile('file') && $request->file('file')->isValid()) {
- try {
- $filename = Uuid::uuid4() . '.' . $request->file('file')->extension();
- } catch (UnsatisfiedDependencyException $e) {
- return response()->json([
- 'response' => 'error',
- 'error' => 'internal_server_error',
- 'error_description' => 'A problem occured handling your request',
- ], 500);
- }
+ if ($tokenData->hasClaim('scope') === false) {
+ return $this->tokenHasNoScopeResponse();
+ }
- $size = $request->file('file')->getClientSize();
- Storage::disk('local')->put($filename, $request->file('file')->openFile()->fread($size));
- try {
- Storage::disk('s3')->put('media/' . $filename, $request->file('file')->openFile()->fread($size));
- } catch (Exception $e) { // which exception?
- return response()->json([
- 'response' => 'error',
- 'error' => 'service_unavailable',
- 'error_description' => 'Unable to save media to S3',
- ], 503);
- }
-
- $manager = app()->make(ImageManager::class);
- try {
- $image = $manager->make($request->file('file'));
- $width = $image->width();
- } catch (\Intervention\Image\Exception\NotReadableException $exception) {
- // not an image
- $width = null;
- }
-
- $media = new Media();
- $media->token = $request->bearerToken();
- $media->path = 'media/' . $filename;
- $media->type = $this->getFileTypeFromMimeType($request->file('file')->getMimeType());
- $media->image_widths = $width;
- $media->save();
-
- dispatch(new ProcessImage($filename));
-
- return response()->json([
- 'response' => 'created',
- 'location' => $media->url,
- ], 201)->header('Location', $media->url);
- }
+ if (stristr($tokenData->getClaim('scope'), 'create') === false) {
+ return $this->insufficientScopeResponse();
+ }
+ if (($request->hasFile('file') && $request->file('file')->isValid()) === false) {
return response()->json([
'response' => 'error',
'error' => 'invalid_request',
@@ -464,11 +182,32 @@ class MicropubController extends Controller
], 400);
}
+ $this->logMicropubRequest($request);
+
+ $filename = $this->saveFile($request->file('file'));
+
+ $manager = resolve(ImageManager::class);
+ try {
+ $image = $manager->make($request->file('file'));
+ $width = $image->width();
+ } catch (NotReadableException $exception) {
+ // not an image
+ $width = null;
+ }
+
+ $media = Media::create([
+ 'token' => $request->bearerToken(),
+ 'path' => 'media/' . $filename,
+ 'type' => $this->getFileTypeFromMimeType($request->file('file')->getMimeType()),
+ 'image_widths' => $width,
+ ]);
+
+ ProcessMedia::dispatch($filename);
+
return response()->json([
- 'response' => 'error',
- 'error' => 'invalid_request',
- 'error_description' => 'The provided token has no scopes',
- ], 400);
+ 'response' => 'created',
+ 'location' => $media->url,
+ ], 201)->header('Location', $media->url);
}
/**
@@ -515,7 +254,23 @@ class MicropubController extends Controller
return 'download';
}
- private function returnInsufficientScopeResponse()
+ private function logMicropubRequest(Request $request)
+ {
+ $logger = new Logger('micropub');
+ $logger->pushHandler(new StreamHandler(storage_path('logs/micropub.log')), Logger::DEBUG);
+ $logger->debug('MicropubLog', $request->all());
+ }
+
+ private function saveFile(UploadedFile $file)
+ {
+ $filename = Uuid::uuid4() . '.' . $file->extension();
+ $size = $file->getClientSize();
+ Storage::disk('local')->put($filename, $file->openFile()->fread($size));
+
+ return $filename;
+ }
+
+ private function insufficientScopeResponse()
{
return response()->json([
'response' => 'error',
@@ -523,4 +278,22 @@ class MicropubController extends Controller
'error_description' => 'The token’s scope does not have the necessary requirements.',
], 401);
}
+
+ private function invalidTokenResponse()
+ {
+ return response()->json([
+ 'response' => 'error',
+ 'error' => 'invalid_token',
+ 'error_description' => 'The provided token did not pass validation',
+ ], 400);
+ }
+
+ private function tokenHasNoScopeResponse()
+ {
+ return response()->json([
+ 'response' => 'error',
+ 'error' => 'invalid_request',
+ 'error_description' => 'The provided token has no scopes',
+ ], 400);
+ }
}
diff --git a/app/Http/Controllers/PhotosController.php b/app/Http/Controllers/PhotosController.php
deleted file mode 100644
index 9eaeb769..00000000
--- a/app/Http/Controllers/PhotosController.php
+++ /dev/null
@@ -1,94 +0,0 @@
-imageResizeLimit = 800;
- }
-
- /**
- * Save an uploaded photo to the image folder.
- *
- * @param \Illuminate\Http\Request $request
- * @param string The associated note’s nb60 ID
- * @return bool
- */
- public function saveImage(Request $request, $nb60id)
- {
- if ($request->hasFile('photo') !== true) {
- return false;
- }
- $photoFilename = 'note-' . $nb60id;
- $path = public_path() . '/assets/img/notes/';
- $ext = $request->file('photo')->getClientOriginalExtension();
- $photoFilename .= '.' . $ext;
- $request->file('photo')->move($path, $photoFilename);
-
- return true;
- }
-
- /**
- * Prepare a photo for posting to twitter.
- *
- * @param string photo fileanme
- * @return string small photo filename, or null
- */
- public function makeSmallPhotoForTwitter($photoFilename)
- {
- $imagine = new Imagine();
- $orig = $imagine->open(public_path() . '/assets/img/notes/' . $photoFilename);
- $size = [$orig->getSize()->getWidth(), $orig->getSize()->getHeight()];
- if ($size[0] > $this->imageResizeLimit || $size[1] > $this->imageResizeLimit) {
- $filenameParts = explode('.', $photoFilename);
- $preExt = count($filenameParts) - 2;
- $filenameParts[$preExt] .= '-small';
- $photoFilenameSmall = implode('.', $filenameParts);
- $aspectRatio = $size[0] / $size[1];
- $box = ($aspectRatio >= 1) ?
- [$this->imageResizeLimit, (int) round($this->imageResizeLimit / $aspectRatio)]
- :
- [(int) round($this->imageResizeLimit * $aspectRatio), $this->imageResizeLimit];
- $orig->resize(new Box($box[0], $box[1]))
- ->save(public_path() . '/assets/img/notes/' . $photoFilenameSmall);
-
- return $photoFilenameSmall;
- }
- }
-
- /**
- * Get the image path for a note.
- *
- * @param string $nb60id
- * @return string | null
- */
- public function getPhotoPath($nb60id)
- {
- $filesystem = new Filesystem();
- $photoDir = public_path() . '/assets/img/notes';
- $files = $filesystem->files($photoDir);
- foreach ($files as $file) {
- $parts = explode('.', $file);
- $name = $parts[0];
- $dirs = explode('/', $name);
- $actualname = last($dirs);
- if ($actualname == 'note-' . $nb60id) {
- $ext = $parts[1];
- }
- }
- if (isset($ext)) {
- return '/assets/img/notes/note-' . $nb60id . '.' . $ext;
- }
- }
-}
diff --git a/app/Http/Controllers/SearchController.php b/app/Http/Controllers/SearchController.php
index 9f68227b..92b7e767 100644
--- a/app/Http/Controllers/SearchController.php
+++ b/app/Http/Controllers/SearchController.php
@@ -10,16 +10,6 @@ class SearchController extends Controller
public function search(Request $request)
{
$notes = Note::search($request->terms)->paginate(10);
- foreach ($notes as $note) {
- $note->iso8601_time = $note->updated_at->toISO8601String();
- $note->human_time = $note->updated_at->diffForHumans();
- $photoURLs = [];
- $photos = $note->getMedia();
- foreach ($photos as $photo) {
- $photoURLs[] = $photo->getUrl();
- }
- $note->photoURLs = $photoURLs;
- }
return view('search', compact('notes'));
}
diff --git a/app/Http/Controllers/ShortURLsController.php b/app/Http/Controllers/ShortURLsController.php
index 9c34ca0f..a4979ca0 100644
--- a/app/Http/Controllers/ShortURLsController.php
+++ b/app/Http/Controllers/ShortURLsController.php
@@ -2,9 +2,6 @@
namespace App\Http\Controllers;
-use App\ShortURL;
-use Jonnybanres\IndieWeb\Numbers;
-
class ShortURLsController extends Controller
{
/*
@@ -41,21 +38,11 @@ class ShortURLsController extends Controller
*
* @return \Illuminate\Routing\RedirectResponse redirect
*/
- public function googlePLus()
+ public function googlePlus()
{
return redirect('https://plus.google.com/u/0/117317270900655269082/about');
}
- /**
- * Redirect from '/α' to an App.net profile.
- *
- * @return \Illuminate\Routing\Redirector redirect
- */
- public function appNet()
- {
- return redirect('https://alpha.app.net/jonnybarnes');
- }
-
/**
* Redirect a short url of this site out to a long one based on post type.
* Further redirects may happen.
@@ -75,46 +62,4 @@ class ShortURLsController extends Controller
return redirect(config('app.url') . '/' . $type . '/' . $postId);
}
-
- /**
- * Redirect a saved short URL, this is generic.
- *
- * @param string The short URL id
- * @return \Illuminate\Routing\Redirector redirect
- */
- public function redirect($shortURLId)
- {
- $numbers = new Numbers();
- $num = $numbers->b60tonum($shortURLId);
- $shorturl = ShortURL::find($num);
- $redirect = $shorturl->redirect;
-
- return redirect($redirect);
- }
-
- /**
- * I had an old redirect systme breifly, but cool URLs should still work.
- *
- * @param string URL ID
- * @return \Illuminate\Routing\Redirector redirect
- */
- public function oldRedirect($shortURLId)
- {
- $filename = base_path() . '/public/assets/old-shorturls.json';
- $handle = fopen($filename, 'r');
- $contents = fread($handle, filesize($filename));
- $object = json_decode($contents);
-
- foreach ($object as $key => $val) {
- if ($shortURLId == $key) {
- return redirect($val);
- }
- }
-
- return 'This id was never used.
- Old redirects are located at
-
- old-shorturls.json
-
.';
- }
}
diff --git a/app/Http/Controllers/WebMentionsController.php b/app/Http/Controllers/WebMentionsController.php
index 41d8cc9b..281794eb 100644
--- a/app/Http/Controllers/WebMentionsController.php
+++ b/app/Http/Controllers/WebMentionsController.php
@@ -36,35 +36,32 @@ class WebMentionsController extends Controller
$path = parse_url($request->input('target'), PHP_URL_PATH);
$pathParts = explode('/', $path);
- switch ($pathParts[1]) {
- case 'notes':
- //we have a note
- $noteId = $pathParts[2];
- $numbers = new Numbers();
- try {
- $note = Note::findOrFail($numbers->b60tonum($noteId));
- dispatch(new ProcessWebMention($note, $request->input('source')));
- } catch (ModelNotFoundException $e) {
- return new Response('This note doesn’t exist.', 400);
- }
+ if ($pathParts[1] == 'notes') {
+ //we have a note
+ $noteId = $pathParts[2];
+ $numbers = new Numbers();
+ try {
+ $note = Note::findOrFail($numbers->b60tonum($noteId));
+ dispatch(new ProcessWebMention($note, $request->input('source')));
+ } catch (ModelNotFoundException $e) {
+ return new Response('This note doesn’t exist.', 400);
+ }
- return new Response(
- 'Webmention received, it will be processed shortly',
- 202
- );
- break;
- case 'blog':
- return new Response(
- 'I don’t accept webmentions for blog posts yet.',
- 501
- );
- break;
- default:
- return new Response(
- 'Invalid request',
- 400
- );
- break;
+ return new Response(
+ 'Webmention received, it will be processed shortly',
+ 202
+ );
}
+ if ($pathParts[1] == 'blog') {
+ return new Response(
+ 'I don’t accept webmentions for blog posts yet.',
+ 501
+ );
+ }
+
+ return new Response(
+ 'Invalid request',
+ 400
+ );
}
}
diff --git a/app/Http/Kernel.php b/app/Http/Kernel.php
index 1f67d385..005c0d69 100644
--- a/app/Http/Kernel.php
+++ b/app/Http/Kernel.php
@@ -36,7 +36,6 @@ class Kernel extends HttpKernel
\App\Http\Middleware\VerifyCsrfToken::class,
\Illuminate\Routing\Middleware\SubstituteBindings::class,
\App\Http\Middleware\LinkHeadersMiddleware::class,
- //\App\Http\Middleware\DevTokenMiddleware::class,
\App\Http\Middleware\LocalhostSessionMiddleware::class,
\App\Http\Middleware\ActivityStreamLinks::class,
],
diff --git a/app/Http/Middleware/DevTokenMiddleware.php b/app/Http/Middleware/DevTokenMiddleware.php
deleted file mode 100644
index dabc2ca2..00000000
--- a/app/Http/Middleware/DevTokenMiddleware.php
+++ /dev/null
@@ -1,36 +0,0 @@
- config('app.url')]);
- if (Storage::exists('dev-token')) {
- session(['token' => Storage::get('dev-token')]);
- } else {
- $data = [
- 'me' => config('app.url'),
- 'client_id' => route('micropub-client'),
- 'scope' => 'post',
- ];
- $tokenService = new \App\Services\TokenService();
- session(['token' => $tokenService->getNewToken($data)]);
- }
- }
-
- return $next($request);
- }
-}
diff --git a/app/Http/Middleware/RedirectIfAuthenticated.php b/app/Http/Middleware/RedirectIfAuthenticated.php
index e4cec9c8..92c2fff8 100644
--- a/app/Http/Middleware/RedirectIfAuthenticated.php
+++ b/app/Http/Middleware/RedirectIfAuthenticated.php
@@ -5,6 +5,9 @@ namespace App\Http\Middleware;
use Closure;
use Illuminate\Support\Facades\Auth;
+/**
+ * @codeCoverageIgnore
+ */
class RedirectIfAuthenticated
{
/**
diff --git a/app/Jobs/DownloadWebMention.php b/app/Jobs/DownloadWebMention.php
index c12a92d4..9fe80f7e 100644
--- a/app/Jobs/DownloadWebMention.php
+++ b/app/Jobs/DownloadWebMention.php
@@ -41,7 +41,7 @@ class DownloadWebMention implements ShouldQueue
//Laravel should catch and retry these automatically.
if ($response->getStatusCode() == '200') {
$filesystem = new \Illuminate\FileSystem\FileSystem();
- $filename = storage_path() . '/HTML/' . $this->createFilenameFromURL($this->source);
+ $filename = storage_path('HTML') . '/' . $this->createFilenameFromURL($this->source);
//backup file first
$filenameBackup = $filename . '.' . date('Y-m-d') . '.backup';
if ($filesystem->exists($filename)) {
diff --git a/app/Jobs/ProcessBookmark.php b/app/Jobs/ProcessBookmark.php
index 1ed51240..348564c0 100644
--- a/app/Jobs/ProcessBookmark.php
+++ b/app/Jobs/ProcessBookmark.php
@@ -9,7 +9,7 @@ use Illuminate\Queue\SerializesModels;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
-use App\Exceptions\InternetArchiveErrorSavingException;
+use App\Exceptions\InternetArchiveException;
class ProcessBookmark implements ShouldQueue
{
@@ -34,12 +34,12 @@ class ProcessBookmark implements ShouldQueue
*/
public function handle()
{
- $uuid = (new BookmarkService())->saveScreenshot($this->bookmark->url);
+ $uuid = (resolve(BookmarkService::class))->saveScreenshot($this->bookmark->url);
$this->bookmark->screenshot = $uuid;
try {
- $archiveLink = (new BookmarkService())->getArchiveLink($this->bookmark->url);
- } catch (InternetArchiveErrorSavingException $e) {
+ $archiveLink = (resolve(BookmarkService::class))->getArchiveLink($this->bookmark->url);
+ } catch (InternetArchiveException $e) {
$archiveLink = null;
}
$this->bookmark->archive = $archiveLink;
diff --git a/app/Jobs/ProcessLike.php b/app/Jobs/ProcessLike.php
index 84fffa7d..ef9f67c2 100644
--- a/app/Jobs/ProcessLike.php
+++ b/app/Jobs/ProcessLike.php
@@ -44,8 +44,8 @@ class ProcessLike implements ShouldQueue
try {
$author = $authorship->findAuthor($mf2);
if (is_array($author)) {
- $this->like->author_name = $author['name'];
- $this->like->author_url = $author['url'];
+ $this->like->author_name = array_get($author, 'properties.name.0');
+ $this->like->author_url = array_get($author, 'properties.url.0');
}
if (is_string($author) && $author !== '') {
$this->like->author_name = $author;
diff --git a/app/Jobs/ProcessImage.php b/app/Jobs/ProcessMedia.php
similarity index 90%
rename from app/Jobs/ProcessImage.php
rename to app/Jobs/ProcessMedia.php
index 4ba0060f..08985383 100644
--- a/app/Jobs/ProcessImage.php
+++ b/app/Jobs/ProcessMedia.php
@@ -2,16 +2,16 @@
namespace App\Jobs;
-use Storage;
use Illuminate\Bus\Queueable;
use Intervention\Image\ImageManager;
use Illuminate\Queue\SerializesModels;
+use Illuminate\Support\Facades\Storage;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Intervention\Image\Exception\NotReadableException;
-class ProcessImage implements ShouldQueue
+class ProcessMedia implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
@@ -34,6 +34,10 @@ class ProcessImage implements ShouldQueue
*/
public function handle(ImageManager $manager)
{
+ Storage::disk('s3')->put(
+ 'media/' . $this->filename,
+ storage_path('app') . '/' . $this->filename
+ );
//open file
try {
$image = $manager->make(storage_path('app') . '/' . $this->filename);
diff --git a/app/Jobs/ProcessWebMention.php b/app/Jobs/ProcessWebMention.php
index 5a24f003..392f36b0 100644
--- a/app/Jobs/ProcessWebMention.php
+++ b/app/Jobs/ProcessWebMention.php
@@ -41,23 +41,25 @@ class ProcessWebMention implements ShouldQueue
*/
public function handle(Parser $parser, Client $guzzle)
{
- $remoteContent = $this->getRemoteContent($this->source, $guzzle);
- if ($remoteContent === null) {
+ try {
+ $response = $guzzle->request('GET', $this->source);
+ } catch (RequestException $e) {
throw new RemoteContentNotFoundException;
}
- $microformats = Mf2\parse($remoteContent, $this->source);
+ $this->saveRemoteContent((string) $response->getBody(), $this->source);
+ $microformats = Mf2\parse((string) $response->getBody(), $this->source);
$webmentions = WebMention::where('source', $this->source)->get();
foreach ($webmentions as $webmention) {
- //check webmention still references target
- //we try each type of mention (reply/like/repost)
+ // check webmention still references target
+ // we try each type of mention (reply/like/repost)
if ($webmention->type == 'in-reply-to') {
if ($parser->checkInReplyTo($microformats, $this->note->longurl) == false) {
- //it doesn't so delete
+ // it doesn’t so delete
$webmention->delete();
return;
}
- //webmenion is still a reply, so update content
+ // webmenion is still a reply, so update content
dispatch(new SaveProfileImage($microformats));
$webmention->mf2 = json_encode($microformats);
$webmention->save();
@@ -66,25 +68,25 @@ class ProcessWebMention implements ShouldQueue
}
if ($webmention->type == 'like-of') {
if ($parser->checkLikeOf($microformats, $note->longurl) == false) {
- //it doesn't so delete
+ // it doesn’t so delete
$webmention->delete();
return;
- } //note we don't need to do anything if it still is a like
+ } // note we don’t need to do anything if it still is a like
}
if ($webmention->type == 'repost-of') {
if ($parser->checkRepostOf($microformats, $note->longurl) == false) {
- //it doesn't so delete
+ // it doesn’t so delete
$webmention->delete();
return;
- } //again, we don't need to do anything if it still is a repost
+ } // again, we don’t need to do anything if it still is a repost
}
- }//foreach
+ }// foreach
- //no wemention in db so create new one
+ // no webmention in the db so create new one
$webmention = new WebMention();
- $type = $parser->getMentionType($microformats); //throw error here?
+ $type = $parser->getMentionType($microformats); // throw error here?
dispatch(new SaveProfileImage($microformats));
$webmention->source = $this->source;
$webmention->target = $this->note->longurl;
@@ -96,21 +98,23 @@ class ProcessWebMention implements ShouldQueue
}
/**
- * Retreive the remote content from a URL, and caches the result.
+ * Save the HTML of a webmention for future use.
*
+ * @param string $html
* @param string $url
- * @param GuzzleHttp\client $guzzle
* @return string|null
*/
- private function getRemoteContent($url, Client $guzzle)
+ private function saveRemoteContent($html, $url)
{
- try {
- $response = $guzzle->request('GET', $url);
- } catch (RequestException $e) {
- return;
+ $filenameFromURL = str_replace(
+ ['https://', 'http://'],
+ ['https/', 'http/'],
+ $url
+ );
+ if (substr($url, -1) == '/') {
+ $filenameFromURL .= 'index.html';
}
- $html = (string) $response->getBody();
- $path = storage_path() . '/HTML/' . $this->createFilenameFromURL($url);
+ $path = storage_path() . '/HTML/' . $filenameFromURL;
$parts = explode('/', $path);
$name = array_pop($parts);
$dir = implode('/', $parts);
@@ -118,24 +122,5 @@ class ProcessWebMention implements ShouldQueue
mkdir($dir, 0755, true);
}
file_put_contents("$dir/$name", $html);
-
- return $html;
- }
-
- /**
- * Create a file path from a URL. This is used when caching the HTML
- * response.
- *
- * @param string The URL
- * @return string The path name
- */
- private function createFilenameFromURL($url)
- {
- $url = str_replace(['https://', 'http://'], ['https/', 'http/'], $url);
- if (substr($url, -1) == '/') {
- $url = $url . 'index.html';
- }
-
- return $url;
}
}
diff --git a/app/Jobs/SaveProfileImage.php b/app/Jobs/SaveProfileImage.php
index ffb0452a..2c657c14 100644
--- a/app/Jobs/SaveProfileImage.php
+++ b/app/Jobs/SaveProfileImage.php
@@ -44,7 +44,7 @@ class SaveProfileImage implements ShouldQueue
//dont save pbs.twimg.com links
if (parse_url($photo, PHP_URL_HOST) != 'pbs.twimg.com'
&& parse_url($photo, PHP_URL_HOST) != 'twitter.com') {
- $client = new Client();
+ $client = resolve(Client::class);
try {
$response = $client->get($photo);
$image = $response->getBody(true);
diff --git a/app/Jobs/SendWebMentions.php b/app/Jobs/SendWebMentions.php
index 5bcbda58..dd9d9a45 100644
--- a/app/Jobs/SendWebMentions.php
+++ b/app/Jobs/SendWebMentions.php
@@ -29,18 +29,18 @@ class SendWebMentions implements ShouldQueue
/**
* Execute the job.
*
- * @param \GuzzleHttp\Client $guzzle
* @return void
*/
- public function handle(Client $guzzle)
+ public function handle()
{
//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) {
+ $endpoint = $this->discoverWebmentionEndpoint($url);
+ if ($endpoint !== null) {
+ $guzzle = resolve(Client::class);
$guzzle->post($endpoint, [
'form_params' => [
'source' => $this->note->longurl,
@@ -55,21 +55,21 @@ class SendWebMentions implements ShouldQueue
* Discover if a URL has a webmention endpoint.
*
* @param string The URL
- * @param \GuzzleHttp\Client $guzzle
* @return string The webmention endpoint URL
*/
- public function discoverWebmentionEndpoint($url, $guzzle)
+ public function discoverWebmentionEndpoint($url)
{
//let’s not send webmentions to myself
if (parse_url($url, PHP_URL_HOST) == config('app.longurl')) {
- return false;
+ return;
}
if (starts_with($url, '/notes/tagged/')) {
- return false;
+ return;
}
$endpoint = null;
+ $guzzle = resolve(Client::class);
$response = $guzzle->get($url);
//check HTTP Headers for webmention endpoint
$links = \GuzzleHttp\Psr7\parse_header($response->getHeader('Link'));
@@ -92,8 +92,6 @@ class SendWebMentions implements ShouldQueue
if ($endpoint) {
return $this->resolveUri($endpoint, $url);
}
-
- return false;
}
/**
diff --git a/app/Jobs/SyndicateBookmarkToFacebook.php b/app/Jobs/SyndicateBookmarkToFacebook.php
index 9d24fbd9..3e09e432 100644
--- a/app/Jobs/SyndicateBookmarkToFacebook.php
+++ b/app/Jobs/SyndicateBookmarkToFacebook.php
@@ -8,10 +8,11 @@ use Illuminate\Bus\Queueable;
use Illuminate\Queue\SerializesModels;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldQueue;
+use Illuminate\Foundation\Bus\Dispatchable;
class SyndicateBookmarkToFacebook implements ShouldQueue
{
- use InteractsWithQueue, Queueable, SerializesModels;
+ use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
protected $bookmark;
diff --git a/app/Jobs/SyndicateBookmarkToTwitter.php b/app/Jobs/SyndicateBookmarkToTwitter.php
index 2e441bb6..e048186a 100644
--- a/app/Jobs/SyndicateBookmarkToTwitter.php
+++ b/app/Jobs/SyndicateBookmarkToTwitter.php
@@ -8,10 +8,11 @@ use Illuminate\Bus\Queueable;
use Illuminate\Queue\SerializesModels;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldQueue;
+use Illuminate\Foundation\Bus\Dispatchable;
class SyndicateBookmarkToTwitter implements ShouldQueue
{
- use InteractsWithQueue, Queueable, SerializesModels;
+ use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
protected $bookmark;
diff --git a/app/Like.php b/app/Like.php
index aae728e6..4fe353a9 100644
--- a/app/Like.php
+++ b/app/Like.php
@@ -24,7 +24,7 @@ class Like extends Model
public function getContentAttribute($value)
{
if ($value === null) {
- return $this->url;
+ return null;
}
$mf2 = Mf2\parse($value, $this->url);
diff --git a/app/Media.php b/app/Media.php
index 916fca2d..83f8af4d 100644
--- a/app/Media.php
+++ b/app/Media.php
@@ -18,7 +18,7 @@ class Media extends Model
*
* @var array
*/
- protected $fillable = ['path'];
+ protected $fillable = ['token', 'path', 'type', 'image_widths'];
/**
* Get the note that owns this media.
@@ -70,10 +70,10 @@ class Media extends Model
public function getBasename($path)
{
- $filenameParts = explode('.', $path);
-
// the following achieves this data flow
// foo.bar.png => ['foo', 'bar', 'png'] => ['foo', 'bar'] => foo.bar
+ $filenameParts = explode('.', $path);
+ array_pop($filenameParts);
$basename = ltrim(array_reduce($filenameParts, function ($carry, $item) {
return $carry . '.' . $item;
}, ''), '.');
diff --git a/app/Note.php b/app/Note.php
index ef94e327..ed9eda1a 100644
--- a/app/Note.php
+++ b/app/Note.php
@@ -146,9 +146,9 @@ class Note extends Model
$emoji = new EmojiModifier();
$hcards = $this->makeHCards($value);
- $html = $this->convertMarkdown($hcards);
- $hashtags = $this->autoLinkHashtag($html);
- $modified = $emoji->makeEmojiAccessible($hashtags);
+ $hashtags = $this->autoLinkHashtag($hcards);
+ $html = $this->convertMarkdown($hashtags);
+ $modified = $emoji->makeEmojiAccessible($html);
return $modified;
}
@@ -223,9 +223,7 @@ class Note extends Model
public function getLatitudeAttribute()
{
if ($this->place !== null) {
- $lnglat = explode(' ', $this->place->location);
-
- return $lnglat[1];
+ return $this->place->location->getLat();
}
if ($this->location !== null) {
$pieces = explode(':', $this->location);
@@ -243,9 +241,7 @@ class Note extends Model
public function getLongitudeAttribute()
{
if ($this->place !== null) {
- $lnglat = explode(' ', $this->place->location);
-
- return $lnglat[1];
+ return $this->place->location->getLng();
}
if ($this->location !== null) {
$pieces = explode(':', $this->location);
@@ -281,12 +277,13 @@ class Note extends Model
if (Cache::has($tweetId)) {
return Cache::get($tweetId);
}
+
try {
$oEmbed = Twitter::getOembed([
- 'id' => $tweetId,
+ 'url' => $this->in_reply_to,
'dnt' => true,
'align' => 'center',
- 'maxwidth' => 550,
+ 'maxwidth' => 512,
]);
} catch (\Exception $e) {
return;
@@ -408,10 +405,10 @@ class Note extends Model
$contact = $this->contacts[$matches[1]]; // easier to read the following code
$host = parse_url($contact->homepage, PHP_URL_HOST);
- $contact->photo = (file_exists(public_path() . '/assets/profile-images/' . $host . '/image')) ?
- '/assets/profile-images/' . $host . '/image'
- :
- '/assets/profile-images/default-image';
+ $contact->photo = '/assets/profile-images/default-image';
+ if (file_exists(public_path() . '/assets/profile-images/' . $host . '/image')) {
+ $contact->photo = '/assets/profile-images/' . $host . '/image';
+ }
return trim(view('templates.mini-hcard', ['contact' => $contact])->render());
},
@@ -450,31 +447,17 @@ class Note extends Model
* @param string The note
* @return string
*/
- private function autoLinkHashtag($text)
+ public function autoLinkHashtag($text)
{
- // $replacements = ["#tag" => "#tag]
- $replacements = [];
- $matches = [];
-
- if (preg_match_all('/(?<=^|\s)\#([a-zA-Z0-9\-\_]+)/i', $text, $matches, PREG_PATTERN_ORDER)) {
- // Look up #tags, get Full name and URL
- foreach ($matches[0] as $name) {
- $name = str_replace('#', '', $name);
- $replacements[$name] =
- '#'
- . $name
- . '';
- }
-
- // Replace #tags with valid microformat-enabled link
- foreach ($replacements as $name => $replacement) {
- $text = str_replace('#' . $name, $replacement, $text);
- }
- }
-
- return $text;
+ return preg_replace_callback(
+ '/#([^\s]*)\b/',
+ function ($matches) {
+ return '#'
+ . Tag::normalize($matches[1]) . '';
+ },
+ $text
+ );
}
private function convertMarkdown($text)
@@ -536,7 +519,7 @@ class Note extends Model
return $address;
}
- $adress = '' . $json->address->country . '';
+ $address = '' . $json->address->country . '';
Cache::forever($latlng, $address);
return $address;
diff --git a/app/Observers/NoteObserver.php b/app/Observers/NoteObserver.php
index 4b9dc1dd..7bc061e0 100644
--- a/app/Observers/NoteObserver.php
+++ b/app/Observers/NoteObserver.php
@@ -21,12 +21,10 @@ class NoteObserver
}
$tags->transform(function ($tag) {
- return Tag::firstOrCreate(['tag' => $tag]);
- });
+ return Tag::firstOrCreate(['tag' => $tag])->id;
+ })->toArray();
- $note->tags()->attach($tags->map(function ($tag) {
- return $tag->id;
- }));
+ $note->tags()->attach($tags);
}
/**
@@ -65,9 +63,6 @@ class NoteObserver
public function getTagsFromNote($note)
{
preg_match_all('/#([^\s<>]+)\b/', $note, $tags);
- if (array_get($tags, '1') === null) {
- return [];
- }
return collect($tags[1])->map(function ($tag) {
return Tag::normalize($tag);
diff --git a/app/Place.php b/app/Place.php
index 7093d194..74588148 100644
--- a/app/Place.php
+++ b/app/Place.php
@@ -2,7 +2,7 @@
namespace App;
-use DB;
+use Illuminate\Support\Facades\DB;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Builder;
use Cviebrock\EloquentSluggable\Sluggable;
@@ -79,15 +79,8 @@ class Place extends Model
public function scopeWhereExternalURL(Builder $query, string $url)
{
- $type = $this->getType($url);
- if ($type === null) {
- // we haven’t set a type, therefore result must be empty set
- // id can’t be null, so this will return empty set
- return $query->whereNull('id');
- }
-
return $query->where('external_urls', '@>', json_encode([
- $type => $url,
+ $this->getType($url) => $url,
]));
}
@@ -131,12 +124,19 @@ class Place extends Model
return config('app.shorturl') . '/places/' . $this->slug;
}
+ /**
+ * This method is an alternative for `longurl`.
+ *
+ * @return string
+ */
+ public function getUriAttribute()
+ {
+ return $this->longurl;
+ }
+
public function setExternalUrlsAttribute($url)
{
$type = $this->getType($url);
- if ($type === null) {
- throw new \Exception('Unkown external url type ' . $url);
- }
$already = [];
if (array_key_exists('external_urls', $this->attributes)) {
$already = json_decode($this->attributes['external_urls'], true);
@@ -155,6 +155,6 @@ class Place extends Model
return 'osm';
}
- return null;
+ return 'default';
}
}
diff --git a/app/Providers/BroadcastServiceProvider.php b/app/Providers/BroadcastServiceProvider.php
index 352cce44..ddd525d7 100644
--- a/app/Providers/BroadcastServiceProvider.php
+++ b/app/Providers/BroadcastServiceProvider.php
@@ -5,6 +5,9 @@ namespace App\Providers;
use Illuminate\Support\ServiceProvider;
use Illuminate\Support\Facades\Broadcast;
+/**
+ * @codeCoverageIgnore
+ */
class BroadcastServiceProvider extends ServiceProvider
{
/**
diff --git a/app/Providers/HorizonServiceProvider.php b/app/Providers/HorizonServiceProvider.php
index bca0414f..3a3503f2 100644
--- a/app/Providers/HorizonServiceProvider.php
+++ b/app/Providers/HorizonServiceProvider.php
@@ -6,6 +6,9 @@ use Illuminate\Http\Request;
use Laravel\Horizon\Horizon;
use Illuminate\Support\ServiceProvider;
+/**
+ * @codeCoverageIgnore
+ */
class HorizonServiceProvider extends ServiceProvider
{
/**
diff --git a/app/Services/BookmarkService.php b/app/Services/BookmarkService.php
index c8215f1a..0966a996 100644
--- a/app/Services/BookmarkService.php
+++ b/app/Services/BookmarkService.php
@@ -13,7 +13,8 @@ use App\Jobs\ProcessBookmark;
use Spatie\Browsershot\Browsershot;
use App\Jobs\SyndicateBookmarkToTwitter;
use App\Jobs\SyndicateBookmarkToFacebook;
-use App\Exceptions\InternetArchiveErrorSavingException;
+use GuzzleHttp\Exception\ClientException;
+use App\Exceptions\InternetArchiveException;
class BookmarkService
{
@@ -103,20 +104,20 @@ class BookmarkService
public function getArchiveLink(string $url): string
{
- $client = new Client();
-
- $response = $client->request('GET', 'https://web.archive.org/save/' . $url);
+ $client = resolve(Client::class);
+ try {
+ $response = $client->request('GET', 'https://web.archive.org/save/' . $url);
+ } catch (ClientException $e) {
+ //throw an exception to be caught
+ throw new InternetArchiveException;
+ }
if ($response->hasHeader('Content-Location')) {
- if (starts_with($response->getHeader('Content-Location')[0], '/web')) {
+ if (starts_with(array_get($response->getHeader('Content-Location'), 0), '/web')) {
return $response->getHeader('Content-Location')[0];
}
}
- if (starts_with(array_get($response->getHeader('Content-Location'), 0), '/web')) {
- return $response->getHeader('Content-Location')[0];
- }
-
//throw an exception to be caught
- throw new InternetArchiveErrorSavingException;
+ throw new InternetArchiveException;
}
}
diff --git a/app/Services/LikeService.php b/app/Services/LikeService.php
index a51fc509..855640da 100644
--- a/app/Services/LikeService.php
+++ b/app/Services/LikeService.php
@@ -21,7 +21,7 @@ class LikeService
//micropub request
$url = normalize_url($request->input('properties.like-of.0'));
}
- if (($request->header('Content-Type') == 'x-www-url-formencoded')
+ if (($request->header('Content-Type') == 'application/x-www-form-urlencoded')
||
($request->header('Content-Type') == 'multipart/form-data')
) {
diff --git a/app/Services/Micropub/HCardService.php b/app/Services/Micropub/HCardService.php
new file mode 100644
index 00000000..4488aaad
--- /dev/null
+++ b/app/Services/Micropub/HCardService.php
@@ -0,0 +1,34 @@
+header('Content-Type') == 'application/json') {
+ $data['name'] = $request->input('properties.name');
+ $data['description'] = $request->input('properties.description') ?? null;
+ if ($request->has('properties.geo')) {
+ $data['geo'] = $request->input('properties.geo');
+ }
+ } else {
+ $data['name'] = $request->input('name');
+ $data['description'] = $request->input('description');
+ if ($request->has('geo')) {
+ $data['geo'] = $request->input('geo');
+ }
+ if ($request->has('latitude')) {
+ $data['latitude'] = $request->input('latitude');
+ $data['longitude'] = $request->input('longitude');
+ }
+ }
+ $place = resolve(PlaceService::class)->createPlace($data);
+
+ return $place->longurl;
+ }
+}
diff --git a/app/Services/Micropub/HEntryService.php b/app/Services/Micropub/HEntryService.php
new file mode 100644
index 00000000..acff6e2a
--- /dev/null
+++ b/app/Services/Micropub/HEntryService.php
@@ -0,0 +1,28 @@
+has('properties.like-of') || $request->has('like-of')) {
+ $like = resolve(LikeService::class)->createLike($request);
+
+ return $like->longurl;
+ }
+
+ if ($request->has('properties.bookmark-of') || $request->has('bookmark-of')) {
+ $bookmark = resolve(BookmarkService::class)->createBookmark($request);
+
+ return $bookmark->longurl;
+ }
+
+ $note = resolve(NoteService::class)->createNote($request);
+
+ return $note->longurl;
+ }
+}
diff --git a/app/Services/Micropub/UpdateService.php b/app/Services/Micropub/UpdateService.php
new file mode 100644
index 00000000..d0138360
--- /dev/null
+++ b/app/Services/Micropub/UpdateService.php
@@ -0,0 +1,95 @@
+input('url'), PHP_URL_PATH);
+
+ //is it a note we are updating?
+ if (mb_substr($urlPath, 1, 5) !== 'notes') {
+ return response()->json([
+ 'error' => 'invalid',
+ 'error_description' => 'This implementation currently only support the updating of notes',
+ ], 500);
+ }
+
+ try {
+ $note = Note::nb60(basename($urlPath))->firstOrFail();
+ } catch (ModelNotFoundException $exception) {
+ return response()->json([
+ 'error' => 'invalid_request',
+ 'error_description' => 'No known note with given ID',
+ ], 404);
+ }
+
+ //got the note, are we dealing with a “replace” request?
+ if ($request->has('replace')) {
+ foreach ($request->input('replace') as $property => $value) {
+ if ($property == 'content') {
+ $note->note = $value[0];
+ }
+ if ($property == 'syndication') {
+ foreach ($value as $syndicationURL) {
+ if (starts_with($syndicationURL, 'https://www.facebook.com')) {
+ $note->facebook_url = $syndicationURL;
+ }
+ if (starts_with($syndicationURL, 'https://www.swarmapp.com')) {
+ $note->swarm_url = $syndicationURL;
+ }
+ if (starts_with($syndicationURL, 'https://twitter.com')) {
+ $note->tweet_id = basename(parse_url($syndicationURL, PHP_URL_PATH));
+ }
+ }
+ }
+ }
+ $note->save();
+
+ return response()->json([
+ 'response' => 'updated',
+ ]);
+ }
+
+ //how about “add”
+ if ($request->has('add')) {
+ foreach ($request->input('add') as $property => $value) {
+ if ($property == 'syndication') {
+ foreach ($value as $syndicationURL) {
+ if (starts_with($syndicationURL, 'https://www.facebook.com')) {
+ $note->facebook_url = $syndicationURL;
+ }
+ if (starts_with($syndicationURL, 'https://www.swarmapp.com')) {
+ $note->swarm_url = $syndicationURL;
+ }
+ if (starts_with($syndicationURL, 'https://twitter.com')) {
+ $note->tweet_id = basename(parse_url($syndicationURL, PHP_URL_PATH));
+ }
+ }
+ }
+ if ($property == 'photo') {
+ foreach ($value as $photoURL) {
+ if (start_with($photo, 'https://')) {
+ $media = new Media();
+ $media->path = $photoURL;
+ $media->type = 'image';
+ $media->save();
+ $note->media()->save($media);
+ }
+ }
+ }
+ }
+ $note->save();
+
+ return response()->json([
+ 'response' => 'updated',
+ ]);
+ }
+ }
+}
diff --git a/app/Services/NoteService.php b/app/Services/NoteService.php
index 4d3f4da0..dea0d6f3 100644
--- a/app/Services/NoteService.php
+++ b/app/Services/NoteService.php
@@ -4,6 +4,7 @@ declare(strict_types=1);
namespace App\Services;
+use Illuminate\Http\Request;
use App\{Media, Note, Place};
use App\Jobs\{SendWebMentions, SyndicateNoteToFacebook, SyndicateNoteToTwitter};
@@ -12,12 +13,111 @@ class NoteService
/**
* Create a new note.
*
- * @param array $data
+ * @param \Illuminate\Http\Request $request
* @return \App\Note $note
*/
- public function createNote(array $data): Note
+ public function createNote(Request $request): Note
{
-
+ //move the request to data code here before refactor
+ $data = [];
+ $data['client-id'] = resolve(TokenService::class)
+ ->validateToken($request->bearerToken())
+ ->getClaim('client_id');
+ if ($request->header('Content-Type') == 'application/json') {
+ if (is_string($request->input('properties.content.0'))) {
+ $data['content'] = $request->input('properties.content.0'); //plaintext content
+ }
+ if (is_array($request->input('properties.content.0'))
+ && array_key_exists('html', $request->input('properties.content.0'))
+ ) {
+ $data['content'] = $request->input('properties.content.0.html');
+ }
+ $data['in-reply-to'] = $request->input('properties.in-reply-to.0');
+ // check location is geo: string
+ if (is_string($request->input('properties.location.0'))) {
+ $data['location'] = $request->input('properties.location.0');
+ }
+ // check location is h-card
+ if (is_array($request->input('properties.location.0'))) {
+ if ($request->input('properties.location.0.type.0' === 'h-card')) {
+ try {
+ $place = resolve(PlaceService::class)->createPlaceFromCheckin(
+ $request->input('properties.location.0')
+ );
+ $data['checkin'] = $place->longurl;
+ } catch (\Exception $e) {
+ //
+ }
+ }
+ }
+ $data['published'] = $request->input('properties.published.0');
+ //create checkin place
+ if (array_key_exists('checkin', $request->input('properties'))) {
+ $data['swarm-url'] = $request->input('properties.syndication.0');
+ try {
+ $place = resolve(PlaceService::class)->createPlaceFromCheckin(
+ $request->input('properties.checkin.0')
+ );
+ $data['checkin'] = $place->longurl;
+ } catch (\Exception $e) {
+ $data['checkin'] = null;
+ $data['swarm-url'] = null;
+ }
+ }
+ } else {
+ $data['content'] = $request->input('content');
+ $data['in-reply-to'] = $request->input('in-reply-to');
+ $data['location'] = $request->input('location');
+ $data['published'] = $request->input('published');
+ }
+ $data['syndicate'] = [];
+ $targets = array_pluck(config('syndication.targets'), 'uid', 'service.name');
+ $mpSyndicateTo = null;
+ if ($request->has('mp-syndicate-to')) {
+ $mpSyndicateTo = $request->input('mp-syndicate-to');
+ }
+ if ($request->has('properties.mp-syndicate-to')) {
+ $mpSyndicateTo = $request->input('properties.mp-syndicate-to');
+ }
+ if (is_string($mpSyndicateTo)) {
+ $service = array_search($mpSyndicateTo, $targets);
+ if ($service == 'Twitter') {
+ $data['syndicate'][] = 'twitter';
+ }
+ if ($service == 'Facebook') {
+ $data['syndicate'][] = 'facebook';
+ }
+ }
+ if (is_array($mpSyndicateTo)) {
+ foreach ($mpSyndicateTo as $uid) {
+ $service = array_search($uid, $targets);
+ if ($service == 'Twitter') {
+ $data['syndicate'][] = 'twitter';
+ }
+ if ($service == 'Facebook') {
+ $data['syndicate'][] = 'facebook';
+ }
+ }
+ }
+ $data['photo'] = [];
+ $photos = null;
+ if ($request->has('photo')) {
+ $photos = $request->input('photo');
+ }
+ if ($request->has('properties.photo')) {
+ $photos = $request->input('properties.photo');
+ }
+ if ($photos !== null) {
+ foreach ($photos as $photo) {
+ if (is_string($photo)) {
+ //only supporting media URLs for now
+ $data['photo'][] = $photo;
+ }
+ }
+ if (starts_with($request->input('properties.syndication.0'), 'https://www.instagram.com')) {
+ $data['instagram-url'] = $request->input('properties.syndication.0');
+ }
+ }
//check the input
if (array_key_exists('content', $data) === false) {
$data['content'] = null;
@@ -37,8 +137,8 @@ class NoteService
);
if (array_key_exists('published', $data) && empty($data['published']) === false) {
- $carbon = carbon($data['published']);
- $note->created_at = $note->updated_at = $carbon->toDateTimeString();
+ $note->created_at = $note->updated_at = carbon($data['published'])
+ ->toDateTimeString();
}
if (array_key_exists('location', $data) && $data['location'] !== null && $data['location'] !== 'no-location') {
@@ -81,7 +181,7 @@ class NoteService
*/
//add support for media uploaded as URLs
if (array_key_exists('photo', $data)) {
- foreach ($data['photo'] as $photo) {
+ foreach ((array) $data['photo'] as $photo) {
// check the media was uploaded to my endpoint, and use path
if (starts_with($photo, config('filesystems.disks.s3.url'))) {
$path = substr($photo, strlen(config('filesystems.disks.s3.url')));
@@ -104,11 +204,13 @@ class NoteService
dispatch(new SendWebMentions($note));
//syndication targets
- if (in_array('twitter', $data['syndicate'])) {
- dispatch(new SyndicateNoteToTwitter($note));
- }
- if (in_array('facebook', $data['syndicate'])) {
- dispatch(new SyndicateNoteToFacebook($note));
+ if (array_key_exists('syndicate', $data)) {
+ if (in_array('twitter', $data['syndicate'])) {
+ dispatch(new SyndicateNoteToTwitter($note));
+ }
+ if (in_array('facebook', $data['syndicate'])) {
+ dispatch(new SyndicateNoteToFacebook($note));
+ }
}
return $note;
diff --git a/app/Services/PlaceService.php b/app/Services/PlaceService.php
index 2a823f33..7d397a5e 100644
--- a/app/Services/PlaceService.php
+++ b/app/Services/PlaceService.php
@@ -46,16 +46,16 @@ class PlaceService
public function createPlaceFromCheckin(array $checkin): Place
{
//check if the place exists if from swarm
- if (array_key_exists('url', $checkin['properties'])) {
+ if (array_has($checkin, 'properties.url')) {
$place = Place::whereExternalURL($checkin['properties']['url'][0])->get();
if (count($place) === 1) {
return $place->first();
}
}
- if (array_key_exists('name', $checkin['properties']) === false) {
+ if (array_has($checkin, 'properties.name') === false) {
throw new \InvalidArgumentException('Missing required name');
}
- if (array_key_exists('latitude', $checkin['properties']) === false) {
+ if (array_has($checkin, 'properties.latitude') === false) {
throw new \InvalidArgumentException('Missing required longitude/latitude');
}
$place = new Place();
diff --git a/app/Services/TokenService.php b/app/Services/TokenService.php
index a91c9dc9..acedba76 100644
--- a/app/Services/TokenService.php
+++ b/app/Services/TokenService.php
@@ -38,7 +38,7 @@ class TokenService
* @param string The token
* @return mixed
*/
- public function validateToken(string $bearerToken): ?Token
+ public function validateToken(string $bearerToken): Token
{
$signer = new Sha256();
try {
@@ -47,7 +47,7 @@ class TokenService
throw new InvalidTokenException('Token could not be parsed');
}
if (! $token->verify($signer, config('app.key'))) {
- throw new InvalidTokenException('Token failed verification');
+ throw new InvalidTokenException('Token failed validation');
}
return $token;
diff --git a/app/Tag.php b/app/Tag.php
index 8b876d2e..2168ed04 100644
--- a/app/Tag.php
+++ b/app/Tag.php
@@ -6,6 +6,13 @@ use Illuminate\Database\Eloquent\Model;
class Tag extends Model
{
+ /**
+ * We shall set a blacklist of non-modifiable model attributes.
+ *
+ * @var array
+ */
+ protected $guarded = ['id'];
+
/**
* Define the relationship with tags.
*
@@ -24,13 +31,6 @@ class Tag extends Model
return $this->belongsToMany('App\Bookmark');
}
- /**
- * We shall set a blacklist of non-modifiable model attributes.
- *
- * @var array
- */
- protected $guarded = ['id'];
-
/**
* Normalize tags so they’re lowercase and fancy diatrics are removed.
*
diff --git a/app/WebMention.php b/app/WebMention.php
index 5e3d570f..ca05bd73 100644
--- a/app/WebMention.php
+++ b/app/WebMention.php
@@ -19,6 +19,13 @@ class WebMention extends Model
*/
protected $table = 'webmentions';
+ /**
+ * We shall set a blacklist of non-modifiable model attributes.
+ *
+ * @var array
+ */
+ protected $guarded = ['id'];
+
/**
* Define the relationship.
*
@@ -29,13 +36,6 @@ class WebMention extends Model
return $this->morphTo();
}
- /**
- * We shall set a blacklist of non-modifiable model attributes.
- *
- * @var array
- */
- protected $guarded = ['id'];
-
/**
* Get the author of the webmention.
*
@@ -78,9 +78,9 @@ class WebMention extends Model
}
/**
- * Get the filteres HTML of a reply.
+ * Get the filtered HTML of a reply.
*
- * @return strin|null
+ * @return string|null
*/
public function getReplyAttribute()
{
@@ -108,14 +108,10 @@ class WebMention extends Model
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
- }
+ $username = ltrim(parse_url($url, PHP_URL_PATH), '/');
+ $info = Twitter::getUsers(['screen_name' => $username]);
+ $profile_image = $info->profile_image_url_https;
+ Cache::put($url, $profile_image, 10080); //1 week
return $profile_image;
}
diff --git a/composer.json b/composer.json
index c093a12b..285377d3 100644
--- a/composer.json
+++ b/composer.json
@@ -41,6 +41,7 @@
"laravel/dusk": "^2.0",
"mockery/mockery": "0.9.*",
"nunomaduro/collision": "^1.1",
+ "php-coveralls/php-coveralls": "^1.0",
"phpunit/phpunit": "~6.0",
"sebastian/phpcpd": "^3.0"
},
diff --git a/composer.lock b/composer.lock
index ca3d140d..014d0129 100644
--- a/composer.lock
+++ b/composer.lock
@@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
"This file is @generated automatically"
],
- "content-hash": "f669c85a04a86625c32349be0ef1fc16",
+ "content-hash": "5b3735b76d6821f7de296da60f7cceca",
"packages": [
{
"name": "aws/aws-sdk-php",
@@ -5019,6 +5019,99 @@
],
"time": "2017-08-15T16:48:10+00:00"
},
+ {
+ "name": "guzzle/guzzle",
+ "version": "v3.8.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/guzzle/guzzle.git",
+ "reference": "4de0618a01b34aa1c8c33a3f13f396dcd3882eba"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/guzzle/guzzle/zipball/4de0618a01b34aa1c8c33a3f13f396dcd3882eba",
+ "reference": "4de0618a01b34aa1c8c33a3f13f396dcd3882eba",
+ "shasum": ""
+ },
+ "require": {
+ "ext-curl": "*",
+ "php": ">=5.3.3",
+ "symfony/event-dispatcher": ">=2.1"
+ },
+ "replace": {
+ "guzzle/batch": "self.version",
+ "guzzle/cache": "self.version",
+ "guzzle/common": "self.version",
+ "guzzle/http": "self.version",
+ "guzzle/inflection": "self.version",
+ "guzzle/iterator": "self.version",
+ "guzzle/log": "self.version",
+ "guzzle/parser": "self.version",
+ "guzzle/plugin": "self.version",
+ "guzzle/plugin-async": "self.version",
+ "guzzle/plugin-backoff": "self.version",
+ "guzzle/plugin-cache": "self.version",
+ "guzzle/plugin-cookie": "self.version",
+ "guzzle/plugin-curlauth": "self.version",
+ "guzzle/plugin-error-response": "self.version",
+ "guzzle/plugin-history": "self.version",
+ "guzzle/plugin-log": "self.version",
+ "guzzle/plugin-md5": "self.version",
+ "guzzle/plugin-mock": "self.version",
+ "guzzle/plugin-oauth": "self.version",
+ "guzzle/service": "self.version",
+ "guzzle/stream": "self.version"
+ },
+ "require-dev": {
+ "doctrine/cache": "*",
+ "monolog/monolog": "1.*",
+ "phpunit/phpunit": "3.7.*",
+ "psr/log": "1.0.*",
+ "symfony/class-loader": "*",
+ "zendframework/zend-cache": "<2.3",
+ "zendframework/zend-log": "<2.3"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "3.8-dev"
+ }
+ },
+ "autoload": {
+ "psr-0": {
+ "Guzzle": "src/",
+ "Guzzle\\Tests": "tests/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Michael Dowling",
+ "email": "mtdowling@gmail.com",
+ "homepage": "https://github.com/mtdowling"
+ },
+ {
+ "name": "Guzzle Community",
+ "homepage": "https://github.com/guzzle/guzzle/contributors"
+ }
+ ],
+ "description": "Guzzle is a PHP HTTP client library and framework for building RESTful web service clients",
+ "homepage": "http://guzzlephp.org/",
+ "keywords": [
+ "client",
+ "curl",
+ "framework",
+ "http",
+ "http client",
+ "rest",
+ "web service"
+ ],
+ "abandoned": "guzzlehttp/guzzle",
+ "time": "2014-01-28T22:29:15+00:00"
+ },
{
"name": "hamcrest/hamcrest-php",
"version": "v1.2.2",
@@ -5502,6 +5595,67 @@
"description": "Library for handling version information and constraints",
"time": "2017-03-05T17:38:23+00:00"
},
+ {
+ "name": "php-coveralls/php-coveralls",
+ "version": "v1.0.2",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/php-coveralls/php-coveralls.git",
+ "reference": "9c07b63acbc9709344948b6fd4f63a32b2ef4127"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/php-coveralls/php-coveralls/zipball/9c07b63acbc9709344948b6fd4f63a32b2ef4127",
+ "reference": "9c07b63acbc9709344948b6fd4f63a32b2ef4127",
+ "shasum": ""
+ },
+ "require": {
+ "ext-json": "*",
+ "ext-simplexml": "*",
+ "guzzle/guzzle": "^2.8 || ^3.0",
+ "php": "^5.3.3 || ^7.0",
+ "psr/log": "^1.0",
+ "symfony/config": "^2.1 || ^3.0 || ^4.0",
+ "symfony/console": "^2.1 || ^3.0 || ^4.0",
+ "symfony/stopwatch": "^2.0 || ^3.0 || ^4.0",
+ "symfony/yaml": "^2.0 || ^3.0 || ^4.0"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^4.8.35 || ^5.4.3 || ^6.0"
+ },
+ "suggest": {
+ "symfony/http-kernel": "Allows Symfony integration"
+ },
+ "bin": [
+ "bin/coveralls"
+ ],
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "Satooshi\\": "src/Satooshi/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Kitamura Satoshi",
+ "email": "with.no.parachute@gmail.com",
+ "homepage": "https://www.facebook.com/satooshi.jp"
+ }
+ ],
+ "description": "PHP client library for Coveralls API",
+ "homepage": "https://github.com/php-coveralls/php-coveralls",
+ "keywords": [
+ "ci",
+ "coverage",
+ "github",
+ "test"
+ ],
+ "time": "2017-10-14T23:15:34+00:00"
+ },
{
"name": "phpdocumentor/reflection-common",
"version": "1.0.1",
@@ -6752,6 +6906,166 @@
"homepage": "https://github.com/sebastianbergmann/version",
"time": "2016-10-03T07:35:21+00:00"
},
+ {
+ "name": "symfony/config",
+ "version": "v3.4.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/config.git",
+ "reference": "1de51a6c76359897ab32c309934b93d036bccb60"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/config/zipball/1de51a6c76359897ab32c309934b93d036bccb60",
+ "reference": "1de51a6c76359897ab32c309934b93d036bccb60",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^5.5.9|>=7.0.8",
+ "symfony/filesystem": "~2.8|~3.0|~4.0"
+ },
+ "conflict": {
+ "symfony/dependency-injection": "<3.3",
+ "symfony/finder": "<3.3"
+ },
+ "require-dev": {
+ "symfony/dependency-injection": "~3.3|~4.0",
+ "symfony/finder": "~3.3|~4.0",
+ "symfony/yaml": "~3.0|~4.0"
+ },
+ "suggest": {
+ "symfony/yaml": "To use the yaml reference dumper"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "3.4-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Symfony\\Component\\Config\\": ""
+ },
+ "exclude-from-classmap": [
+ "/Tests/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Fabien Potencier",
+ "email": "fabien@symfony.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "description": "Symfony Config Component",
+ "homepage": "https://symfony.com",
+ "time": "2017-11-19T20:09:36+00:00"
+ },
+ {
+ "name": "symfony/filesystem",
+ "version": "v4.0.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/filesystem.git",
+ "reference": "c9d4a26759ff75a077e4e334315cb632739b661a"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/filesystem/zipball/c9d4a26759ff75a077e4e334315cb632739b661a",
+ "reference": "c9d4a26759ff75a077e4e334315cb632739b661a",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^7.1.3"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "4.0-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Symfony\\Component\\Filesystem\\": ""
+ },
+ "exclude-from-classmap": [
+ "/Tests/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Fabien Potencier",
+ "email": "fabien@symfony.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "description": "Symfony Filesystem Component",
+ "homepage": "https://symfony.com",
+ "time": "2017-11-21T14:14:53+00:00"
+ },
+ {
+ "name": "symfony/stopwatch",
+ "version": "v4.0.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/stopwatch.git",
+ "reference": "ac0e49150555c703fef6b696d8eaba1db7a3ca03"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/stopwatch/zipball/ac0e49150555c703fef6b696d8eaba1db7a3ca03",
+ "reference": "ac0e49150555c703fef6b696d8eaba1db7a3ca03",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^7.1.3"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "4.0-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Symfony\\Component\\Stopwatch\\": ""
+ },
+ "exclude-from-classmap": [
+ "/Tests/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Fabien Potencier",
+ "email": "fabien@symfony.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "description": "Symfony Stopwatch Component",
+ "homepage": "https://symfony.com",
+ "time": "2017-11-09T12:45:29+00:00"
+ },
{
"name": "symfony/yaml",
"version": "v3.3.13",
diff --git a/database/seeds/ContactsTableSeeder.php b/database/seeds/ContactsTableSeeder.php
index 28ac804d..1d7f3244 100644
--- a/database/seeds/ContactsTableSeeder.php
+++ b/database/seeds/ContactsTableSeeder.php
@@ -22,7 +22,6 @@ class ContactsTableSeeder extends Seeder
'nick' => 'aaron',
'name' => 'Aaron Parecki',
'homepage' => 'https://aaronparecki.com',
- 'twitter' => 'aaronpk',
'facebook' => '123456',
]);
}
diff --git a/database/seeds/LikesTableSeeder.php b/database/seeds/LikesTableSeeder.php
index 59c5af07..fed15569 100644
--- a/database/seeds/LikesTableSeeder.php
+++ b/database/seeds/LikesTableSeeder.php
@@ -12,5 +12,15 @@ class LikesTableSeeder extends Seeder
public function run()
{
factory(App\Like::class, 10)->create();
+
+ $faker = new \Faker\Generator();
+ $faker->addProvider(new \Faker\Provider\en_US\Person($faker));
+ $faker->addProvider(new \Faker\Provider\Lorem($faker));
+ $faker->addProvider(new \Faker\Provider\Internet($faker));
+ App\Like::create([
+ 'url' => $faker->url,
+ 'author_url' => $faker->url,
+ 'author_name' => $faker->name,
+ ]);
}
}
diff --git a/database/seeds/NotesTableSeeder.php b/database/seeds/NotesTableSeeder.php
index 55329626..ba478935 100644
--- a/database/seeds/NotesTableSeeder.php
+++ b/database/seeds/NotesTableSeeder.php
@@ -13,6 +13,11 @@ class NotesTableSeeder extends Seeder
{
factory(App\Note::class, 10)->create();
sleep(1);
+ $noteTwitterReply = App\Note::create([
+ 'note' => 'What does this even mean?',
+ 'in_reply_to' => 'https://twitter.com/realDonaldTrump/status/933662564587855877',
+ ]);
+ sleep(1);
$noteWithPlace = App\Note::create([
'note' => 'Having a #beer at the local. 🍺',
]);
@@ -42,11 +47,29 @@ class NotesTableSeeder extends Seeder
copy(base_path() . '/tests/aaron.png', public_path() . '/assets/profile-images/aaronparecki.com/image');
}
$noteWithCoords = App\Note::create([
- 'note' => 'Note from somehwere',
+ 'note' => 'Note from a town',
]);
$noteWithCoords->location = '53.499,-2.379';
$noteWithCoords->save();
sleep(1);
+ $noteWithCoords2 = App\Note::create([
+ 'note' => 'Note from a city',
+ ]);
+ $noteWithCoords2->location = '53.9026894,-2.42250444118781';
+ $noteWithCoords2->save();
+ sleep(1);
+ $noteWithCoords3 = App\Note::create([
+ 'note' => 'Note from a county',
+ ]);
+ $noteWithCoords3->location = '57.5066357,-5.0038367';
+ $noteWithCoords3->save();
+ sleep(1);
+ $noteWithCoords4 = App\Note::create([
+ 'note' => 'Note from a country',
+ ]);
+ $noteWithCoords4->location = '63.000147,-136.002502';
+ $noteWithCoords4->save();
+ sleep(1);
$noteSyndicated = App\Note::create([
'note' => 'This note has all the syndication targets',
]);
@@ -59,5 +82,26 @@ class NotesTableSeeder extends Seeder
$noteWithTextLinkandEmoji = App\Note::create([
'note' => 'I love https://duckduckgo.com 💕' // theres a two-heart emoji at the end of this
]);
+ sleep(1);
+ $media = new App\Media();
+ $media->path = 'media/f1bc8faa-1a8f-45b8-a9b1-57282fa73f87.jpg';
+ $media->type = 'image';
+ $media->image_widths = '3648';
+ $media->save();
+ $noteWithImage = App\Note::create([
+ 'note' => 'A lovely waterfall',
+ ]);
+ $noteWithImage->media()->save($media);
+ sleep(1);
+ $noteFromInstagram = App\Note::create([
+ 'note' => 'Lovely #wedding #weddingfavour',
+ ]);
+ $noteFromInstagram->instagram_url = 'https://www.instagram.com/p/Bbo22MHhE_0';
+ $noteFromInstagram->save();
+ $mediaInstagram = new App\Media();
+ $mediaInstagram->path = 'https://scontent-lhr3-1.cdninstagram.com/t51.2885-15/e35/23734479_149605352435937_400133507076063232_n.jpg';
+ $mediaInstagram->type = 'image';
+ $mediaInstagram->save();
+ $noteFromInstagram->media()->save($mediaInstagram);
}
}
diff --git a/database/seeds/WebMentionsTableSeeder.php b/database/seeds/WebMentionsTableSeeder.php
index c0da2809..72935206 100644
--- a/database/seeds/WebMentionsTableSeeder.php
+++ b/database/seeds/WebMentionsTableSeeder.php
@@ -12,13 +12,21 @@ class WebMentionsTableSeeder extends Seeder
*/
public function run()
{
- $webmention = WebMention::create([
- 'source' => 'https://aaornpk.localhost/reply/1',
- 'target' => 'https://jonnybarnes.localhost/notes/D',
+ $webmentionAaron = WebMention::create([
+ 'source' => 'https://aaronpk.localhost/reply/1',
+ 'target' => config('app.url') . '/notes/E',
+ 'commentable_id' => '14',
+ 'commentable_type' => 'App\Note',
+ 'type' => 'in-reply-to',
+ 'mf2' => '{"rels": [], "items": [{"type": ["h-entry"], "properties": {"url": ["https://aaronpk.localhost/reply/1"], "name": ["Hi too"], "author": [{"type": ["h-card"], "value": "Aaron Parecki", "properties": {"url": ["https://aaronpk.localhost"], "name": ["Aaron Parecki"], "photo": ["https://aaronparecki.com/images/profile.jpg"]}}], "content": [{"html": "Hi too", "value": "Hi too"}], "published": ["' . date(DATE_W3C) . '"], "in-reply-to": ["https://aaronpk.loclahost/reply/1", "' . config('app.url') .'/notes/E"]}}]}'
+ ]);
+ $webmentionTantek = WebMention::create([
+ 'source' => 'http://tantek.com/',
+ 'target' => config('app.url') . '/notes/D',
'commentable_id' => '13',
'commentable_type' => 'App\Note',
'type' => 'in-reply-to',
- 'mf2' => '{"rels": [], "items": [{"type": ["h-entry"], "properties": {"url": ["https://aaronpk.localhost/reply/1"], "name": ["Hi too"], "author": [{"type": ["h-card"], "value": "Aaron Parecki", "properties": {"url": ["https://aaronpk.localhost"], "name": ["Aaron Parecki"], "photo": ["https://aaronparecki.com/images/profile.jpg"]}}], "content": [{"html": "Hi too", "value": "Hi too"}], "published": ["' . date(DATE_W3C) . '"], "in-reply-to": ["https://aaronpk.loclahost/reply/1", "https://jonnybarnes.uk/notes/D"]}}]}'
+ 'mf2' => '{"rels": [], "items": [{"type": ["h-entry"], "properties": {"url": ["http://tantek.com/"], "name": ["KUTGW"], "author": [{"type": ["h-card"], "value": "Tantek Celik", "properties": {"url": ["http://tantek.com/"], "name": ["Tantek Celik"]}}], "content": [{"html": "kutgw", "value": "kutgw"}], "published": ["' . date(DATE_W3C) . '"], "in-reply-to": ["' . config('app.url') . '/notes/D"]}}]}'
]);
}
}
diff --git a/public/assets/old-shorturls.json b/public/assets/old-shorturls.json
deleted file mode 100644
index 26b0e4c4..00000000
--- a/public/assets/old-shorturls.json
+++ /dev/null
@@ -1,19 +0,0 @@
-{
- "RbrS": "https://jonnybarnes.net/note/1",
- "pfua": "https://jonnybarnes.net/note/2",
- "HQ8X": "https://jonnybarnes.net/note/3",
- "7Duc": "https://jonnybarnes.net/note/4",
- "m0vZ": "https://jonnybarnes.net/note/5",
- "uB95": "https://jonnybarnes.net/note/6",
- "yUx8": "https://jonnybarnes.net/note/7",
- "tMLB": "https://jonnybarnes.net/note/8",
- "a1HU": "https://jonnybarnes.net/note/9",
- "rx3e": "https://jonnybarnes.net/note/10",
- "dW3p": "https://jonnybarnes.net/note/11",
- "_6za": "https://jonnybarnes.net/note/12",
- "eTvB": "https://jonnybarnes.net/note/13",
- "6kMh": "https://jonnybarnes.net/note/14",
- "T72f": "https://jonnybarnes.net/note/15",
- "enot": "https://jonnybarnes.net/note/16",
- "QCDv": "https://jonnybarnes.net/note/17"
-}
\ No newline at end of file
diff --git a/resources/views/admin/notes/create.blade.php b/resources/views/admin/notes/create.blade.php
index 3512797d..72ad0566 100644
--- a/resources/views/admin/notes/create.blade.php
+++ b/resources/views/admin/notes/create.blade.php
@@ -12,12 +12,7 @@
@endif
-@include('templates.new-note-form', [
- 'micropub' => false,
- 'action' => '/admin/note',
- 'id' => 'newnote-admin'
-])
-