Merge branch 'feature/media-endpoint' into develop
This commit is contained in:
commit
0c604d6117
26 changed files with 735 additions and 791 deletions
|
|
@ -3,6 +3,7 @@ preset: laravel
|
|||
disabled:
|
||||
- concat_without_spaces
|
||||
- simplified_null_return
|
||||
- single_import_per_statement
|
||||
|
||||
finder:
|
||||
path: app/
|
||||
|
|
|
|||
|
|
@ -2,13 +2,12 @@
|
|||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Http\Response;
|
||||
use App\Services\IndieAuthService;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use IndieAuth\Client as IndieClient;
|
||||
use GuzzleHttp\Client as GuzzleClient;
|
||||
use GuzzleHttp\Exception\ClientException;
|
||||
use Illuminate\Http\{Request, Response};
|
||||
use GuzzleHttp\Exception\{ClientException, ServerException};
|
||||
|
||||
class MicropubClientController extends Controller
|
||||
{
|
||||
|
|
@ -40,8 +39,65 @@ class MicropubClientController extends Controller
|
|||
{
|
||||
$url = $request->session()->get('me');
|
||||
$syndication = $request->session()->get('syndication');
|
||||
$mediaEndpoint = $request->session()->get('media-endpoint');
|
||||
$mediaURLs = $request->session()->get('media-links');
|
||||
|
||||
return view('micropub.create', compact('url', 'syndication'));
|
||||
return view('micropub.create', compact('url', 'syndication', 'mediaEndpoint', 'mediaURLs'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Process an upload to the media endpoint.
|
||||
*
|
||||
* @param Illuminate\Http\Request $request
|
||||
* @return Illuminate\Http\Response
|
||||
*/
|
||||
public function processMedia(Request $request)
|
||||
{
|
||||
if ($request->hasFile('file') == false) {
|
||||
return back();
|
||||
}
|
||||
|
||||
$mediaEndpoint = $request->session()->get('media-endpoint');
|
||||
if ($mediaEndpoint == null) {
|
||||
return back();
|
||||
}
|
||||
|
||||
$token = $request->session()->get('token');
|
||||
|
||||
$mediaURLs = [];
|
||||
foreach ($request->file('file') as $file) {
|
||||
try {
|
||||
$response = $this->guzzleClient->request('POST', $mediaEndpoint, [
|
||||
'headers' => [
|
||||
'Authorization' => 'Bearer ' . $token,
|
||||
],
|
||||
'multipart' => [
|
||||
[
|
||||
'name' => 'file',
|
||||
'contents' => fopen($file->path(), 'r'),
|
||||
'filename' => $file->getClientOriginalName(),
|
||||
],
|
||||
],
|
||||
]);
|
||||
} catch (ClientException | ServerException $e) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$mediaURLs[] = $response->getHeader('Location')[0];
|
||||
}
|
||||
|
||||
$storedMediaURLs = $request->session()->get('media-links') ?? [];
|
||||
$mediaURLsToSave = array_merge($storedMediaURLs, $mediaURLs);
|
||||
$request->session()->put('media-links', $mediaURLsToSave);
|
||||
|
||||
return redirect(route('micropub-client'));
|
||||
}
|
||||
|
||||
public function clearLinks(Request $request)
|
||||
{
|
||||
$request->session()->forget('media-links');
|
||||
|
||||
return redirect(route('micropub-client'));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -68,6 +124,7 @@ class MicropubClientController extends Controller
|
|||
$response = $this->postNoteRequest($request, $micropubEndpoint, $token);
|
||||
|
||||
if ($response->getStatusCode() == 201) {
|
||||
$request->session()->forget('media-links');
|
||||
$location = $response->getHeader('Location');
|
||||
if (is_array($location)) {
|
||||
return redirect($location[0]);
|
||||
|
|
@ -79,6 +136,54 @@ class MicropubClientController extends Controller
|
|||
return redirect(route('micropub-client'))->with('error', 'Endpoint didn’t create the note.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Show currently stored configuration values.
|
||||
*
|
||||
* @param Illuminate\Http\Request $request
|
||||
* @return view
|
||||
*/
|
||||
public function config(Request $request)
|
||||
{
|
||||
$data['me'] = $request->session()->get('me');
|
||||
$data['token'] = $request->session()->get('token');
|
||||
$data['syndication'] = $request->session()->get('syndication') ?? 'none defined';
|
||||
$data['media-endpoint'] = $request->session()->get('media-endpoint') ?? 'none defined';
|
||||
|
||||
return view('micropub.config', compact('data'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Query the micropub endpoint and store response in the session.
|
||||
*
|
||||
* @param Illuminate\Http\Request $request
|
||||
* @return redirect
|
||||
*/
|
||||
public function queryEndpoint(Request $request)
|
||||
{
|
||||
$domain = $request->session()->get('me');
|
||||
$token = $request->session()->get('token');
|
||||
$micropubEndpoint = $this->indieAuthService->discoverMicropubEndpoint($domain);
|
||||
if ($micropubEndpoint !== null) {
|
||||
try {
|
||||
$response = $this->guzzleClient->get($micropubEndpoint, [
|
||||
'headers' => ['Authorization' => 'Bearer ' . $token],
|
||||
'query' => 'q=config',
|
||||
]);
|
||||
} catch (ClientException | ServerException $e) {
|
||||
return back();
|
||||
}
|
||||
$body = (string) $response->getBody();
|
||||
|
||||
$syndication = $this->parseSyndicationTargets($body);
|
||||
$request->session()->put('syndication', $syndication);
|
||||
|
||||
$mediaEndpoint = $this->parseMediaEndpoint($body);
|
||||
$request->session()->put('media-endpoint', $mediaEndpoint);
|
||||
|
||||
return back();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* We make a request to the micropub endpoint requesting syndication targets
|
||||
* and store them in the session.
|
||||
|
|
@ -172,6 +277,14 @@ class MicropubClientController extends Controller
|
|||
];
|
||||
}
|
||||
}
|
||||
if ($request->input('media')) {
|
||||
foreach ($request->input('media') as $media) {
|
||||
$multipart[] = [
|
||||
'name' => 'photo[]',
|
||||
'contents' => $media,
|
||||
];
|
||||
}
|
||||
}
|
||||
$headers = [
|
||||
'Authorization' => 'Bearer ' . $token,
|
||||
];
|
||||
|
|
@ -338,11 +451,27 @@ class MicropubClientController extends Controller
|
|||
'name' => $syn['name'],
|
||||
];
|
||||
}
|
||||
} else {
|
||||
$syndicateTo[] = ['target' => 'http://example.org', 'name' => 'Joe Bloggs on Example'];
|
||||
}
|
||||
if (count($syndicateTo) > 0) {
|
||||
return $syndicateTo;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse the media-endpoint retrieved from querying a micropub endpoint.
|
||||
*
|
||||
* @param string|null
|
||||
* @return string
|
||||
*/
|
||||
private function parseMediaEndpoint($queryResponse = null)
|
||||
{
|
||||
if ($queryResponse === null) {
|
||||
return;
|
||||
}
|
||||
|
||||
$data = json_decode($queryResponse, true);
|
||||
if (array_key_exists('media-endpoint', $data)) {
|
||||
return $data['media-endpoint'];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,12 +2,11 @@
|
|||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use App\Place;
|
||||
use Illuminate\Http\Request;
|
||||
use App\Services\NoteService;
|
||||
use Illuminate\Http\Response;
|
||||
use App\Services\PlaceService;
|
||||
use App\Services\TokenService;
|
||||
use Ramsey\Uuid\Uuid;
|
||||
use App\{Media, Place};
|
||||
use Illuminate\Http\{Request, Response};
|
||||
use Ramsey\Uuid\Exception\UnsatisfiedDependencyException;
|
||||
use App\Services\{NoteService, PlaceService, TokenService};
|
||||
|
||||
class MicropubController extends Controller
|
||||
{
|
||||
|
|
@ -95,6 +94,15 @@ class MicropubController extends Controller
|
|||
}
|
||||
}
|
||||
}
|
||||
$data['photo'] = [];
|
||||
if (is_array($request->input('photo'))) {
|
||||
foreach ($request->input('photo') as $photo) {
|
||||
if (is_string($photo)) {
|
||||
//only supporting media URLs for now
|
||||
$data['photo'][] = $photo;
|
||||
}
|
||||
}
|
||||
}
|
||||
try {
|
||||
$note = $this->noteService->createNote($data);
|
||||
} catch (Exception $exception) {
|
||||
|
|
@ -182,6 +190,15 @@ class MicropubController extends Controller
|
|||
'syndicate-to' => config('syndication.targets'),
|
||||
]);
|
||||
}
|
||||
|
||||
//nope, how about a config query?
|
||||
if ($request->input('q') == 'config') {
|
||||
return response()->json([
|
||||
'syndicate-to' => config('syndication.targets'),
|
||||
'media-endpoint' => route('media-endpoint'),
|
||||
]);
|
||||
}
|
||||
|
||||
//nope, how about a geo URL?
|
||||
if (substr($request->input('q'), 0, 4) === 'geo:') {
|
||||
preg_match_all(
|
||||
|
|
@ -200,13 +217,6 @@ class MicropubController extends Controller
|
|||
'places' => $places,
|
||||
]);
|
||||
}
|
||||
//nope, how about a config query?
|
||||
//this should have a media endpoint as well at some point
|
||||
if ($request->input('q') == 'config') {
|
||||
return response()->json([
|
||||
'syndicate-to' => config('syndication.targets'),
|
||||
]);
|
||||
}
|
||||
|
||||
//nope, just return the token
|
||||
return response()->json([
|
||||
|
|
@ -225,4 +235,135 @@ class MicropubController extends Controller
|
|||
'error_description' => 'No token provided with request',
|
||||
], 400);
|
||||
}
|
||||
|
||||
/**
|
||||
* Process a media item posted to the media endpoint.
|
||||
*
|
||||
* @param Illuminate\Http\Request $request
|
||||
* @return Illuminate\Http\Response
|
||||
*/
|
||||
public function media(Request $request)
|
||||
{
|
||||
//can this go in middleware
|
||||
$httpAuth = $request->header('Authorization');
|
||||
if (preg_match('/Bearer (.+)/', $httpAuth, $match)) {
|
||||
$token = $match[1];
|
||||
$tokenData = $this->tokenService->validateToken($token);
|
||||
|
||||
if ($tokenData === null) {
|
||||
return response()->json([
|
||||
'response' => 'error',
|
||||
'error' => 'invalid_token',
|
||||
'error_description' => 'The provided token did not pass validation',
|
||||
], 400);
|
||||
}
|
||||
|
||||
//check post scope
|
||||
if ($tokenData->hasClaim('scope')) {
|
||||
$scopes = explode(' ', $tokenData->getClaim('scope'));
|
||||
if (array_search('post', $scopes) !== false) {
|
||||
//check media valid
|
||||
if ($request->hasFile('file') && $request->file('file')->isValid()) {
|
||||
$type = $this->getFileTypeFromMimeType($request->file('file')->getMimeType());
|
||||
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);
|
||||
}
|
||||
try {
|
||||
$path = $request->file('file')->storeAs('media', $filename, 's3');
|
||||
} catch (Exception $e) { // which exception?
|
||||
return response()->json([
|
||||
'response' => 'error',
|
||||
'error' => 'service_unavailable',
|
||||
'error_description' => 'Unable to save media to S3',
|
||||
], 503);
|
||||
}
|
||||
$media = new Media();
|
||||
$media->token = $token;
|
||||
$media->path = $path;
|
||||
$media->type = $type;
|
||||
$media->save();
|
||||
|
||||
return response()->json([
|
||||
'response' => 'created',
|
||||
'location' => $media->url,
|
||||
], 201)->header('Location', $media->url);
|
||||
}
|
||||
|
||||
return response()->json([
|
||||
'response' => 'error',
|
||||
'error' => 'invalid_request',
|
||||
'error_description' => 'The uploaded file failed validation',
|
||||
], 400);
|
||||
}
|
||||
|
||||
return response()->json([
|
||||
'response' => 'error',
|
||||
'error' => 'insufficient_scope',
|
||||
'error_description' => 'The provided token has insufficient scopes',
|
||||
], 401);
|
||||
}
|
||||
|
||||
return response()->json([
|
||||
'response' => 'error',
|
||||
'error' => 'unauthorized',
|
||||
'error_description' => 'No token provided with request',
|
||||
], 401);
|
||||
}
|
||||
|
||||
return response()->json([
|
||||
'response' => 'error',
|
||||
'error' => 'no_token',
|
||||
'error_description' => 'There was no token provided with the request',
|
||||
], 400);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the file type from the mimetype of the uploaded file.
|
||||
*
|
||||
* @param string The mimetype
|
||||
* @return string The type
|
||||
*/
|
||||
private function getFileTypeFromMimeType($mimetype)
|
||||
{
|
||||
//try known images
|
||||
$imageMimeTypes = [
|
||||
'image/gif',
|
||||
'image/jpeg',
|
||||
'image/png',
|
||||
'image/svg+xml',
|
||||
'image/tiff',
|
||||
'image/webp',
|
||||
];
|
||||
if (in_array($mimetype, $imageMimeTypes)) {
|
||||
return 'image';
|
||||
}
|
||||
//try known video
|
||||
$videoMimeTypes = [
|
||||
'video/mp4',
|
||||
'video/mpeg',
|
||||
'video/quicktime',
|
||||
'video/webm',
|
||||
];
|
||||
if (in_array($mimetype, $videoMimeTypes)) {
|
||||
return 'video';
|
||||
}
|
||||
//try known audio types
|
||||
$audioMimeTypes = [
|
||||
'audio/midi',
|
||||
'audio/mpeg',
|
||||
'audio/ogg',
|
||||
'audio/x-m4a',
|
||||
];
|
||||
if (in_array($mimetype, $audioMimeTypes)) {
|
||||
return 'audio';
|
||||
}
|
||||
|
||||
return 'download';
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,10 +2,9 @@
|
|||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use App\Tag;
|
||||
use Twitter;
|
||||
use App\Note;
|
||||
use HTMLPurifier;
|
||||
use App\{Note, Tag};
|
||||
use GuzzleHttp\Client;
|
||||
use HTMLPurifier_Config;
|
||||
use Illuminate\Http\Request;
|
||||
|
|
@ -58,12 +57,10 @@ class NotesController extends Controller
|
|||
$note->place->icon
|
||||
);
|
||||
}
|
||||
$photoURLs = [];
|
||||
$photos = $note->getMedia();
|
||||
foreach ($photos as $photo) {
|
||||
$photoURLs[] = $photo->getUrl();
|
||||
}
|
||||
$note->photoURLs = $photoURLs;
|
||||
/*$mediaLinks = [];
|
||||
foreach ($note->media()->get() as $media) {
|
||||
$mediaLinks[] = $media->url;
|
||||
}*/
|
||||
}
|
||||
|
||||
$homepage = ($request->path() == '/');
|
||||
|
|
@ -164,13 +161,6 @@ class NotesController extends Controller
|
|||
);
|
||||
}
|
||||
|
||||
$photoURLs = [];
|
||||
$photos = $note->getMedia();
|
||||
foreach ($photos as $photo) {
|
||||
$photoURLs[] = $photo->getUrl();
|
||||
}
|
||||
$note->photoURLs = $photoURLs;
|
||||
|
||||
return view('notes.show', compact('note', 'replies', 'reposts', 'likes'));
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -12,9 +12,10 @@ class VerifyCsrfToken extends BaseVerifier
|
|||
* @var array
|
||||
*/
|
||||
protected $except = [
|
||||
'api/token',
|
||||
'api/media',
|
||||
'api/post',
|
||||
'webmention',
|
||||
'api/token',
|
||||
'places/new',
|
||||
'webmention',
|
||||
];
|
||||
}
|
||||
|
|
|
|||
33
app/Media.php
Normal file
33
app/Media.php
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
<?php
|
||||
|
||||
namespace App;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class Media extends Model
|
||||
{
|
||||
/**
|
||||
* The table associated with the model.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $table = 'media_endpoint';
|
||||
|
||||
/**
|
||||
* Get the note that owns this media.
|
||||
*/
|
||||
public function note()
|
||||
{
|
||||
return $this->belongsTo('App\Note');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the URL for an S3 media file.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getUrlAttribute()
|
||||
{
|
||||
return config('filesystems.disks.s3.url') . '/' . $this->path;
|
||||
}
|
||||
}
|
||||
15
app/Note.php
15
app/Note.php
|
|
@ -9,15 +9,12 @@ use Illuminate\Database\Eloquent\Model;
|
|||
use Jonnybarnes\EmojiA11y\EmojiModifier;
|
||||
use League\CommonMark\CommonMarkConverter;
|
||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
use Spatie\MediaLibrary\HasMedia\HasMediaTrait;
|
||||
use Spatie\MediaLibrary\HasMedia\Interfaces\HasMedia;
|
||||
use Illuminate\Database\Eloquent\ModelNotFoundException;
|
||||
|
||||
class Note extends Model implements HasMedia
|
||||
class Note extends Model
|
||||
{
|
||||
use Searchable;
|
||||
use SoftDeletes;
|
||||
use HasMediaTrait;
|
||||
|
||||
/**
|
||||
* The database table used by the model.
|
||||
|
|
@ -56,6 +53,16 @@ class Note extends Model implements HasMedia
|
|||
return $this->belongsTo('App\Place');
|
||||
}
|
||||
|
||||
/**
|
||||
* Define the relationship with media.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function media()
|
||||
{
|
||||
return $this->hasMany('App\Media');
|
||||
}
|
||||
|
||||
/**
|
||||
* We shall set a blacklist of non-modifiable model attributes.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -4,11 +4,8 @@ declare(strict_types=1);
|
|||
|
||||
namespace App\Services;
|
||||
|
||||
use App\Note;
|
||||
use App\Place;
|
||||
use App\Jobs\SendWebMentions;
|
||||
use App\Jobs\SyndicateToTwitter;
|
||||
use App\Jobs\SyndicateToFacebook;
|
||||
use App\{Media, Note, Place};
|
||||
use App\Jobs\{SendWebMentions, SyndicateToFacebook, SyndicateToTwitter};
|
||||
|
||||
class NoteService
|
||||
{
|
||||
|
|
@ -55,6 +52,15 @@ class NoteService
|
|||
}
|
||||
}
|
||||
*/
|
||||
//add support for media uploaded as URLs
|
||||
foreach ($data['photo'] as $photo) {
|
||||
// check the media was uploaded to my endpoint
|
||||
if (starts_with($photo, config('filesystems.disks.s3.url'))) {
|
||||
$path = substr($photo, strlen(config('filesystems.disks.s3.url')));
|
||||
$media = Media::where('path', ltrim($path, '/'))->firstOrFail();
|
||||
$note->media()->save($media);
|
||||
}
|
||||
}
|
||||
|
||||
$note->save();
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,8 @@
|
|||
# Changelog
|
||||
|
||||
## Version {next}
|
||||
- Media endpoint added
|
||||
|
||||
## Version 0.3.6 (2017-03-07)
|
||||
- Pull in Piwik’s own piwik.js manually, again for CSP
|
||||
|
||||
|
|
|
|||
|
|
@ -6,26 +6,26 @@
|
|||
"type": "project",
|
||||
"require": {
|
||||
"php": ">=7.1.0",
|
||||
"laravel/framework": "5.4.*",
|
||||
"ezyang/htmlpurifier": "~4.6",
|
||||
"guzzlehttp/guzzle": "~6.0",
|
||||
"indieauth/client": "~0.1",
|
||||
"jonnybarnes/emoji-a11y": "^0.2",
|
||||
"jonnybarnes/indieweb": "dev-master",
|
||||
"jonnybarnes/webmentions-parser": "0.4.*",
|
||||
"guzzlehttp/guzzle": "~6.0",
|
||||
"predis/predis": "~1.0",
|
||||
"thujohn/twitter": "~2.0",
|
||||
"mf2/mf2": "~0.3",
|
||||
"martinbean/laravel-sluggable-trait": "0.2.*",
|
||||
"indieauth/client": "~0.1",
|
||||
"ezyang/htmlpurifier": "~4.6",
|
||||
"league/commonmark": "^0.15.0",
|
||||
"spatie/laravel-medialibrary": "^4.0",
|
||||
"league/flysystem-aws-s3-v3": "^1.0",
|
||||
"phaza/laravel-postgis": "~3.1",
|
||||
"lcobucci/jwt": "^3.1",
|
||||
"sensiolabs/security-checker": "^4.0",
|
||||
"laravel/framework": "5.4.*",
|
||||
"laravel/scout": "^3.0",
|
||||
"laravel/tinker": "^1.0",
|
||||
"lcobucci/jwt": "^3.1",
|
||||
"league/commonmark": "^0.15.0",
|
||||
"league/flysystem-aws-s3-v3": "^1.0",
|
||||
"martinbean/laravel-sluggable-trait": "0.2.*",
|
||||
"mf2/mf2": "~0.3",
|
||||
"phaza/laravel-postgis": "~3.1",
|
||||
"pmatseykanets/laravel-scout-postgres": "^0.5.0",
|
||||
"jonnybarnes/emoji-a11y": "^0.2",
|
||||
"laravel/tinker": "^1.0"
|
||||
"predis/predis": "~1.0",
|
||||
"ramsey/uuid": "^3.5",
|
||||
"sensiolabs/security-checker": "^4.0",
|
||||
"thujohn/twitter": "~2.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"barryvdh/laravel-debugbar": "~2.0",
|
||||
|
|
|
|||
686
composer.lock
generated
686
composer.lock
generated
File diff suppressed because it is too large
Load diff
|
|
@ -215,11 +215,6 @@ return [
|
|||
*/
|
||||
Thujohn\Twitter\TwitterServiceProvider::class,
|
||||
|
||||
/*
|
||||
* Laravel Medialibrary
|
||||
*/
|
||||
Spatie\MediaLibrary\MediaLibraryServiceProvider::class,
|
||||
|
||||
/*
|
||||
* Phaza’s Postgis library
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -61,6 +61,7 @@ return [
|
|||
'secret' => env('AWS_S3_SECRET'),
|
||||
'region' => env('AWS_S3_REGION'),
|
||||
'bucket' => env('AWS_S3_BUCKET'),
|
||||
'url' => env('AWS_S3_URL'),
|
||||
],
|
||||
|
||||
'media' => [
|
||||
|
|
|
|||
|
|
@ -0,0 +1,41 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
|
||||
class CreateMediaEndpointTable extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::create('media_endpoint', function (Blueprint $table) {
|
||||
$table->increments('id');
|
||||
$table->text('token')->nullable();
|
||||
$table->string('path');
|
||||
$table->string('type');
|
||||
$table->unsignedInteger('note_id')->nullable();
|
||||
$table->timestamps();
|
||||
|
||||
$table->index('token');
|
||||
$table->foreign('note_id')->references('id')->on('notes');
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::table('media_endpoint', function (Blueprint $table) {
|
||||
$table->dropForeign(['note_id']);
|
||||
});
|
||||
Schema::dropIfExists('media_endpoint');
|
||||
}
|
||||
}
|
||||
4
public/assets/css/app.css
vendored
4
public/assets/css/app.css
vendored
File diff suppressed because one or more lines are too long
Binary file not shown.
Binary file not shown.
|
|
@ -12,5 +12,5 @@
|
|||
"../../../resources/assets/sass/emoji.scss"
|
||||
],
|
||||
"names": [],
|
||||
"mappings": "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"
|
||||
"mappings": "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"
|
||||
}
|
||||
9
resources/assets/sass/note-form.scss
vendored
9
resources/assets/sass/note-form.scss
vendored
|
|
@ -37,3 +37,12 @@
|
|||
#locate {
|
||||
margin-right: 0.4rem;
|
||||
}
|
||||
|
||||
.mp-media li {
|
||||
list-style-type: none;
|
||||
}
|
||||
|
||||
.mp-media img {
|
||||
height: 4em;
|
||||
width: 4em;
|
||||
}
|
||||
|
|
|
|||
16
resources/views/micropub/config.blade.php
Normal file
16
resources/views/micropub/config.blade.php
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
@extends('master')
|
||||
|
||||
@section('title')
|
||||
Micropub Config «
|
||||
@stop
|
||||
|
||||
@section('content')
|
||||
<p>The values for your micropub endpoint.</p>
|
||||
<dl>
|
||||
<dt>Me (your url)</dt><dd>{{ $data['me'] }}</dd>
|
||||
<dt>Token</dt><dd>{{ $data['token'] }}</dd>
|
||||
<dt>Syndication Targets</dt><dd>@if(is_array($data['syndication']))<ul>@foreach ($data['syndication'] as $syn)<li>{{ $syn['name'] }} ({{ $syn['target'] }})</li>@endforeach</ul>@else{{ $data['syndication'] }}@endif</dd>
|
||||
<dt>Media Endpoint</dt><dd>{{ $data['media-endpoint'] }}</dd>
|
||||
</dl>
|
||||
<p><a href="{{ route('micropub-query-action') }}">Re-query</a> the endpoint.</p>
|
||||
@stop
|
||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue