Compare commits
No commits in common. "main" and "v0.69.6" have entirely different histories.
134 changed files with 3960 additions and 3206 deletions
|
@ -12,9 +12,7 @@ APP_FALLBACK_LOCALE=en
|
||||||
APP_FAKER_LOCALE=en_US
|
APP_FAKER_LOCALE=en_US
|
||||||
|
|
||||||
APP_MAINTENANCE_DRIVER=file
|
APP_MAINTENANCE_DRIVER=file
|
||||||
# APP_MAINTENANCE_STORE=database
|
APP_MAINTENANCE_STORE=database
|
||||||
|
|
||||||
PHP_CLI_SERVER_WORKERS=4
|
|
||||||
|
|
||||||
BCRYPT_ROUNDS=12
|
BCRYPT_ROUNDS=12
|
||||||
|
|
||||||
|
@ -41,7 +39,7 @@ FILESYSTEM_DISK=local
|
||||||
QUEUE_CONNECTION=database
|
QUEUE_CONNECTION=database
|
||||||
|
|
||||||
CACHE_STORE=database
|
CACHE_STORE=database
|
||||||
# CACHE_PREFIX=
|
CACHE_PREFIX=
|
||||||
|
|
||||||
MEMCACHED_HOST=127.0.0.1
|
MEMCACHED_HOST=127.0.0.1
|
||||||
|
|
||||||
|
@ -51,7 +49,6 @@ REDIS_PASSWORD=null
|
||||||
REDIS_PORT=6379
|
REDIS_PORT=6379
|
||||||
|
|
||||||
MAIL_MAILER=log
|
MAIL_MAILER=log
|
||||||
MAIL_SCHEME=null
|
|
||||||
MAIL_HOST=127.0.0.1
|
MAIL_HOST=127.0.0.1
|
||||||
MAIL_PORT=2525
|
MAIL_PORT=2525
|
||||||
MAIL_USERNAME=null
|
MAIL_USERNAME=null
|
||||||
|
|
2
.gitignore
vendored
2
.gitignore
vendored
|
@ -21,5 +21,3 @@ yarn-error.log
|
||||||
/.idea
|
/.idea
|
||||||
/.vscode
|
/.vscode
|
||||||
ray.php
|
ray.php
|
||||||
/public/gpg.key
|
|
||||||
/public/assets/img/favicon.png
|
|
||||||
|
|
|
@ -1,5 +0,0 @@
|
||||||
{
|
|
||||||
"$schema": "/Users/jonny/git/phpactor/phpactor.schema.json",
|
|
||||||
"language_server_phpstan.enabled": false,
|
|
||||||
"language_server_psalm.enabled": true
|
|
||||||
}
|
|
|
@ -1,69 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Console\Commands;
|
|
||||||
|
|
||||||
use App\Models\Media;
|
|
||||||
use Illuminate\Console\Command;
|
|
||||||
use Illuminate\Support\Facades\Storage;
|
|
||||||
|
|
||||||
class CopyMediaToLocal extends Command
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* The name and signature of the console command.
|
|
||||||
*
|
|
||||||
* @var string
|
|
||||||
*/
|
|
||||||
protected $signature = 'app:copy-media-to-local';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The console command description.
|
|
||||||
*
|
|
||||||
* @var string
|
|
||||||
*/
|
|
||||||
protected $description = 'Copy any historic media saved to S3 to the local filesystem';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Execute the console command.
|
|
||||||
*/
|
|
||||||
public function handle()
|
|
||||||
{
|
|
||||||
// Load all the Media records
|
|
||||||
$media = Media::all();
|
|
||||||
|
|
||||||
// Loop through each media record and copy the file from S3 to the local filesystem
|
|
||||||
foreach ($media as $mediaItem) {
|
|
||||||
$filename = $mediaItem->path;
|
|
||||||
|
|
||||||
$this->info('Processing: ' . $filename);
|
|
||||||
|
|
||||||
// If the file is already saved locally skip to next one
|
|
||||||
if (Storage::disk('local')->exists('public/' . $filename)) {
|
|
||||||
$this->info('File already exists locally, skipping');
|
|
||||||
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Copy the file from S3 to the local filesystem
|
|
||||||
if (! Storage::disk('s3')->exists($filename)) {
|
|
||||||
$this->error('File does not exist on S3');
|
|
||||||
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
$contents = Storage::disk('s3')->get($filename);
|
|
||||||
Storage::disk('local')->put('public/' . $filename, $contents);
|
|
||||||
|
|
||||||
// Copy -medium and -small versions if they exist
|
|
||||||
$filenameParts = explode('.', $filename);
|
|
||||||
$extension = array_pop($filenameParts);
|
|
||||||
$basename = trim(implode('.', $filenameParts), '.');
|
|
||||||
$mediumFilename = $basename . '-medium.' . $extension;
|
|
||||||
$smallFilename = $basename . '-small.' . $extension;
|
|
||||||
if (Storage::disk('s3')->exists($mediumFilename)) {
|
|
||||||
Storage::disk('local')->put('public/' . $mediumFilename, Storage::disk('s3')->get($mediumFilename));
|
|
||||||
}
|
|
||||||
if (Storage::disk('s3')->exists($smallFilename)) {
|
|
||||||
Storage::disk('local')->put('public/' . $smallFilename, Storage::disk('s3')->get($smallFilename));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -37,7 +37,7 @@ class ParseCachedWebMentions extends Command
|
||||||
{
|
{
|
||||||
$htmlFiles = $filesystem->allFiles(storage_path() . '/HTML');
|
$htmlFiles = $filesystem->allFiles(storage_path() . '/HTML');
|
||||||
foreach ($htmlFiles as $file) {
|
foreach ($htmlFiles as $file) {
|
||||||
if ($file->getExtension() !== 'backup') { // we don’t want to parse `.backup` files
|
if ($file->getExtension() !== 'backup') { //we don’t want to parse `.backup` files
|
||||||
$filepath = $file->getPathname();
|
$filepath = $file->getPathname();
|
||||||
$this->info('Loading HTML from: ' . $filepath);
|
$this->info('Loading HTML from: ' . $filepath);
|
||||||
$html = $filesystem->get($filepath);
|
$html = $filesystem->get($filepath);
|
||||||
|
|
|
@ -6,5 +6,5 @@ use Exception;
|
||||||
|
|
||||||
class RemoteContentNotFoundException extends Exception
|
class RemoteContentNotFoundException extends Exception
|
||||||
{
|
{
|
||||||
// used when guzzle can’t find the remote content
|
//used when guzzle can’t find the remote content
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,7 +30,7 @@ class ArticlesController extends Controller
|
||||||
|
|
||||||
public function store(): RedirectResponse
|
public function store(): RedirectResponse
|
||||||
{
|
{
|
||||||
// if a `.md` is attached use that for the main content.
|
//if a `.md` is attached use that for the main content.
|
||||||
if (request()->hasFile('article')) {
|
if (request()->hasFile('article')) {
|
||||||
$file = request()->file('article')->openFile();
|
$file = request()->file('article')->openFile();
|
||||||
$content = $file->fread($file->getSize());
|
$content = $file->fread($file->getSize());
|
||||||
|
|
|
@ -40,7 +40,7 @@ class ContactsController extends Controller
|
||||||
*/
|
*/
|
||||||
public function store(): RedirectResponse
|
public function store(): RedirectResponse
|
||||||
{
|
{
|
||||||
$contact = new Contact;
|
$contact = new Contact();
|
||||||
$contact->name = request()->input('name');
|
$contact->name = request()->input('name');
|
||||||
$contact->nick = request()->input('nick');
|
$contact->nick = request()->input('nick');
|
||||||
$contact->homepage = request()->input('homepage');
|
$contact->homepage = request()->input('homepage');
|
||||||
|
@ -79,7 +79,7 @@ class ContactsController extends Controller
|
||||||
if (request()->hasFile('avatar') && (request()->input('homepage') != '')) {
|
if (request()->hasFile('avatar') && (request()->input('homepage') != '')) {
|
||||||
$dir = parse_url(request()->input('homepage'), PHP_URL_HOST);
|
$dir = parse_url(request()->input('homepage'), PHP_URL_HOST);
|
||||||
$destination = public_path() . '/assets/profile-images/' . $dir;
|
$destination = public_path() . '/assets/profile-images/' . $dir;
|
||||||
$filesystem = new Filesystem;
|
$filesystem = new Filesystem();
|
||||||
if ($filesystem->isDirectory($destination) === false) {
|
if ($filesystem->isDirectory($destination) === false) {
|
||||||
$filesystem->makeDirectory($destination);
|
$filesystem->makeDirectory($destination);
|
||||||
}
|
}
|
||||||
|
@ -139,7 +139,7 @@ class ContactsController extends Controller
|
||||||
}
|
}
|
||||||
if ($avatar !== null) {
|
if ($avatar !== null) {
|
||||||
$directory = public_path() . '/assets/profile-images/' . parse_url($contact->homepage, PHP_URL_HOST);
|
$directory = public_path() . '/assets/profile-images/' . parse_url($contact->homepage, PHP_URL_HOST);
|
||||||
$filesystem = new Filesystem;
|
$filesystem = new Filesystem();
|
||||||
if ($filesystem->isDirectory($directory) === false) {
|
if ($filesystem->isDirectory($directory) === false) {
|
||||||
$filesystem->makeDirectory($directory);
|
$filesystem->makeDirectory($directory);
|
||||||
}
|
}
|
||||||
|
|
|
@ -67,7 +67,7 @@ class NotesController extends Controller
|
||||||
*/
|
*/
|
||||||
public function update(int $noteId): RedirectResponse
|
public function update(int $noteId): RedirectResponse
|
||||||
{
|
{
|
||||||
// update note data
|
//update note data
|
||||||
$note = Note::findOrFail($noteId);
|
$note = Note::findOrFail($noteId);
|
||||||
$note->note = request()->input('content');
|
$note->note = request()->input('content');
|
||||||
$note->in_reply_to = request()->input('in-reply-to');
|
$note->in_reply_to = request()->input('in-reply-to');
|
||||||
|
|
|
@ -116,8 +116,8 @@ class PasskeysController extends Controller
|
||||||
throw new WebAuthnException('No public key credential request options found');
|
throw new WebAuthnException('No public key credential request options found');
|
||||||
}
|
}
|
||||||
|
|
||||||
$attestationStatementSupportManager = new AttestationStatementSupportManager;
|
$attestationStatementSupportManager = new AttestationStatementSupportManager();
|
||||||
$attestationStatementSupportManager->add(new NoneAttestationStatementSupport);
|
$attestationStatementSupportManager->add(new NoneAttestationStatementSupport());
|
||||||
|
|
||||||
$webauthnSerializer = (new WebauthnSerializerFactory(
|
$webauthnSerializer = (new WebauthnSerializerFactory(
|
||||||
$attestationStatementSupportManager
|
$attestationStatementSupportManager
|
||||||
|
@ -133,12 +133,12 @@ class PasskeysController extends Controller
|
||||||
throw new WebAuthnException('Invalid response type');
|
throw new WebAuthnException('Invalid response type');
|
||||||
}
|
}
|
||||||
|
|
||||||
$algorithmManager = new Manager;
|
$algorithmManager = new Manager();
|
||||||
$algorithmManager->add(new Ed25519);
|
$algorithmManager->add(new Ed25519());
|
||||||
$algorithmManager->add(new ES256);
|
$algorithmManager->add(new ES256());
|
||||||
$algorithmManager->add(new RS256);
|
$algorithmManager->add(new RS256());
|
||||||
|
|
||||||
$ceremonyStepManagerFactory = new CeremonyStepManagerFactory;
|
$ceremonyStepManagerFactory = new CeremonyStepManagerFactory();
|
||||||
$ceremonyStepManagerFactory->setAlgorithmManager($algorithmManager);
|
$ceremonyStepManagerFactory->setAlgorithmManager($algorithmManager);
|
||||||
$ceremonyStepManagerFactory->setAttestationStatementSupportManager(
|
$ceremonyStepManagerFactory->setAttestationStatementSupportManager(
|
||||||
$attestationStatementSupportManager
|
$attestationStatementSupportManager
|
||||||
|
@ -206,8 +206,8 @@ class PasskeysController extends Controller
|
||||||
], 400);
|
], 400);
|
||||||
}
|
}
|
||||||
|
|
||||||
$attestationStatementSupportManager = new AttestationStatementSupportManager;
|
$attestationStatementSupportManager = new AttestationStatementSupportManager();
|
||||||
$attestationStatementSupportManager->add(new NoneAttestationStatementSupport);
|
$attestationStatementSupportManager->add(new NoneAttestationStatementSupport());
|
||||||
|
|
||||||
$webauthnSerializer = (new WebauthnSerializerFactory(
|
$webauthnSerializer = (new WebauthnSerializerFactory(
|
||||||
$attestationStatementSupportManager
|
$attestationStatementSupportManager
|
||||||
|
@ -240,15 +240,15 @@ class PasskeysController extends Controller
|
||||||
'json'
|
'json'
|
||||||
);
|
);
|
||||||
|
|
||||||
$algorithmManager = new Manager;
|
$algorithmManager = new Manager();
|
||||||
$algorithmManager->add(new Ed25519);
|
$algorithmManager->add(new Ed25519());
|
||||||
$algorithmManager->add(new ES256);
|
$algorithmManager->add(new ES256());
|
||||||
$algorithmManager->add(new RS256);
|
$algorithmManager->add(new RS256());
|
||||||
|
|
||||||
$attestationStatementSupportManager = new AttestationStatementSupportManager;
|
$attestationStatementSupportManager = new AttestationStatementSupportManager();
|
||||||
$attestationStatementSupportManager->add(new NoneAttestationStatementSupport);
|
$attestationStatementSupportManager->add(new NoneAttestationStatementSupport());
|
||||||
|
|
||||||
$ceremonyStepManagerFactory = new CeremonyStepManagerFactory;
|
$ceremonyStepManagerFactory = new CeremonyStepManagerFactory();
|
||||||
$ceremonyStepManagerFactory->setAlgorithmManager($algorithmManager);
|
$ceremonyStepManagerFactory->setAlgorithmManager($algorithmManager);
|
||||||
$ceremonyStepManagerFactory->setAttestationStatementSupportManager(
|
$ceremonyStepManagerFactory->setAttestationStatementSupportManager(
|
||||||
$attestationStatementSupportManager
|
$attestationStatementSupportManager
|
||||||
|
|
|
@ -18,7 +18,7 @@ class ContactsController extends Controller
|
||||||
*/
|
*/
|
||||||
public function index(): View
|
public function index(): View
|
||||||
{
|
{
|
||||||
$filesystem = new Filesystem;
|
$filesystem = new Filesystem();
|
||||||
$contacts = Contact::all();
|
$contacts = Contact::all();
|
||||||
foreach ($contacts as $contact) {
|
foreach ($contacts as $contact) {
|
||||||
$contact->homepageHost = parse_url($contact->homepage, PHP_URL_HOST);
|
$contact->homepageHost = parse_url($contact->homepage, PHP_URL_HOST);
|
||||||
|
@ -40,7 +40,7 @@ class ContactsController extends Controller
|
||||||
$contact->homepageHost = parse_url($contact->homepage, PHP_URL_HOST);
|
$contact->homepageHost = parse_url($contact->homepage, PHP_URL_HOST);
|
||||||
$file = public_path() . '/assets/profile-images/' . $contact->homepageHost . '/image';
|
$file = public_path() . '/assets/profile-images/' . $contact->homepageHost . '/image';
|
||||||
|
|
||||||
$filesystem = new Filesystem;
|
$filesystem = new Filesystem();
|
||||||
$image = ($filesystem->exists($file)) ?
|
$image = ($filesystem->exists($file)) ?
|
||||||
'/assets/profile-images/' . $contact->homepageHost . '/image'
|
'/assets/profile-images/' . $contact->homepageHost . '/image'
|
||||||
:
|
:
|
||||||
|
|
|
@ -26,8 +26,8 @@ class IndieAuthController extends Controller
|
||||||
'authorization_endpoint' => route('indieauth.start'),
|
'authorization_endpoint' => route('indieauth.start'),
|
||||||
'token_endpoint' => route('indieauth.token'),
|
'token_endpoint' => route('indieauth.token'),
|
||||||
'code_challenge_methods_supported' => ['S256'],
|
'code_challenge_methods_supported' => ['S256'],
|
||||||
// 'introspection_endpoint' => route('indieauth.introspection'),
|
//'introspection_endpoint' => route('indieauth.introspection'),
|
||||||
// 'introspection_endpoint_auth_methods_supported' => ['none'],
|
//'introspection_endpoint_auth_methods_supported' => ['none'],
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -53,13 +53,13 @@ class MicropubController extends Controller
|
||||||
try {
|
try {
|
||||||
$tokenData = $this->tokenService->validateToken($request->input('access_token'));
|
$tokenData = $this->tokenService->validateToken($request->input('access_token'));
|
||||||
} catch (RequiredConstraintsViolated|InvalidTokenStructure|CannotDecodeContent) {
|
} catch (RequiredConstraintsViolated|InvalidTokenStructure|CannotDecodeContent) {
|
||||||
$micropubResponses = new MicropubResponses;
|
$micropubResponses = new MicropubResponses();
|
||||||
|
|
||||||
return $micropubResponses->invalidTokenResponse();
|
return $micropubResponses->invalidTokenResponse();
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($tokenData->claims()->has('scope') === false) {
|
if ($tokenData->claims()->has('scope') === false) {
|
||||||
$micropubResponses = new MicropubResponses;
|
$micropubResponses = new MicropubResponses();
|
||||||
|
|
||||||
return $micropubResponses->tokenHasNoScopeResponse();
|
return $micropubResponses->tokenHasNoScopeResponse();
|
||||||
}
|
}
|
||||||
|
@ -73,7 +73,7 @@ class MicropubController extends Controller
|
||||||
}
|
}
|
||||||
|
|
||||||
if (! in_array('create', $scopes)) {
|
if (! in_array('create', $scopes)) {
|
||||||
$micropubResponses = new MicropubResponses;
|
$micropubResponses = new MicropubResponses();
|
||||||
|
|
||||||
return $micropubResponses->insufficientScopeResponse();
|
return $micropubResponses->insufficientScopeResponse();
|
||||||
}
|
}
|
||||||
|
@ -91,7 +91,7 @@ class MicropubController extends Controller
|
||||||
$scopes = explode(' ', $scopes);
|
$scopes = explode(' ', $scopes);
|
||||||
}
|
}
|
||||||
if (! in_array('create', $scopes)) {
|
if (! in_array('create', $scopes)) {
|
||||||
$micropubResponses = new MicropubResponses;
|
$micropubResponses = new MicropubResponses();
|
||||||
|
|
||||||
return $micropubResponses->insufficientScopeResponse();
|
return $micropubResponses->insufficientScopeResponse();
|
||||||
}
|
}
|
||||||
|
@ -109,7 +109,7 @@ class MicropubController extends Controller
|
||||||
$scopes = explode(' ', $scopes);
|
$scopes = explode(' ', $scopes);
|
||||||
}
|
}
|
||||||
if (! in_array('update', $scopes)) {
|
if (! in_array('update', $scopes)) {
|
||||||
$micropubResponses = new MicropubResponses;
|
$micropubResponses = new MicropubResponses();
|
||||||
|
|
||||||
return $micropubResponses->insufficientScopeResponse();
|
return $micropubResponses->insufficientScopeResponse();
|
||||||
}
|
}
|
||||||
|
@ -136,7 +136,7 @@ class MicropubController extends Controller
|
||||||
try {
|
try {
|
||||||
$tokenData = $this->tokenService->validateToken($request->input('access_token'));
|
$tokenData = $this->tokenService->validateToken($request->input('access_token'));
|
||||||
} catch (RequiredConstraintsViolated|InvalidTokenStructure) {
|
} catch (RequiredConstraintsViolated|InvalidTokenStructure) {
|
||||||
return (new MicropubResponses)->invalidTokenResponse();
|
return (new MicropubResponses())->invalidTokenResponse();
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($request->input('q') === 'syndicate-to') {
|
if ($request->input('q') === 'syndicate-to') {
|
||||||
|
|
|
@ -39,13 +39,13 @@ class MicropubMediaController extends Controller
|
||||||
try {
|
try {
|
||||||
$tokenData = $this->tokenService->validateToken($request->input('access_token'));
|
$tokenData = $this->tokenService->validateToken($request->input('access_token'));
|
||||||
} catch (RequiredConstraintsViolated|InvalidTokenStructure) {
|
} catch (RequiredConstraintsViolated|InvalidTokenStructure) {
|
||||||
$micropubResponses = new MicropubResponses;
|
$micropubResponses = new MicropubResponses();
|
||||||
|
|
||||||
return $micropubResponses->invalidTokenResponse();
|
return $micropubResponses->invalidTokenResponse();
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($tokenData->claims()->has('scope') === false) {
|
if ($tokenData->claims()->has('scope') === false) {
|
||||||
$micropubResponses = new MicropubResponses;
|
$micropubResponses = new MicropubResponses();
|
||||||
|
|
||||||
return $micropubResponses->tokenHasNoScopeResponse();
|
return $micropubResponses->tokenHasNoScopeResponse();
|
||||||
}
|
}
|
||||||
|
@ -55,7 +55,7 @@ class MicropubMediaController extends Controller
|
||||||
$scopes = explode(' ', $scopes);
|
$scopes = explode(' ', $scopes);
|
||||||
}
|
}
|
||||||
if (! in_array('create', $scopes)) {
|
if (! in_array('create', $scopes)) {
|
||||||
$micropubResponses = new MicropubResponses;
|
$micropubResponses = new MicropubResponses();
|
||||||
|
|
||||||
return $micropubResponses->insufficientScopeResponse();
|
return $micropubResponses->insufficientScopeResponse();
|
||||||
}
|
}
|
||||||
|
@ -111,13 +111,13 @@ class MicropubMediaController extends Controller
|
||||||
try {
|
try {
|
||||||
$tokenData = $this->tokenService->validateToken($request->input('access_token'));
|
$tokenData = $this->tokenService->validateToken($request->input('access_token'));
|
||||||
} catch (RequiredConstraintsViolated|InvalidTokenStructure) {
|
} catch (RequiredConstraintsViolated|InvalidTokenStructure) {
|
||||||
$micropubResponses = new MicropubResponses;
|
$micropubResponses = new MicropubResponses();
|
||||||
|
|
||||||
return $micropubResponses->invalidTokenResponse();
|
return $micropubResponses->invalidTokenResponse();
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($tokenData->claims()->has('scope') === false) {
|
if ($tokenData->claims()->has('scope') === false) {
|
||||||
$micropubResponses = new MicropubResponses;
|
$micropubResponses = new MicropubResponses();
|
||||||
|
|
||||||
return $micropubResponses->tokenHasNoScopeResponse();
|
return $micropubResponses->tokenHasNoScopeResponse();
|
||||||
}
|
}
|
||||||
|
@ -127,7 +127,7 @@ class MicropubMediaController extends Controller
|
||||||
$scopes = explode(' ', $scopes);
|
$scopes = explode(' ', $scopes);
|
||||||
}
|
}
|
||||||
if (! in_array('create', $scopes)) {
|
if (! in_array('create', $scopes)) {
|
||||||
$micropubResponses = new MicropubResponses;
|
$micropubResponses = new MicropubResponses();
|
||||||
|
|
||||||
return $micropubResponses->insufficientScopeResponse();
|
return $micropubResponses->insufficientScopeResponse();
|
||||||
}
|
}
|
||||||
|
@ -140,10 +140,7 @@ class MicropubMediaController extends Controller
|
||||||
], 400);
|
], 400);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @var UploadedFile $file */
|
if ($request->file('file')->isValid() === false) {
|
||||||
$file = $request->file('file');
|
|
||||||
|
|
||||||
if ($file->isValid() === false) {
|
|
||||||
return response()->json([
|
return response()->json([
|
||||||
'response' => 'error',
|
'response' => 'error',
|
||||||
'error' => 'invalid_request',
|
'error' => 'invalid_request',
|
||||||
|
@ -151,7 +148,7 @@ class MicropubMediaController extends Controller
|
||||||
], 400);
|
], 400);
|
||||||
}
|
}
|
||||||
|
|
||||||
$filename = Storage::disk('local')->putFile('media', $file);
|
$filename = $this->saveFile($request->file('file'));
|
||||||
|
|
||||||
/** @var ImageManager $manager */
|
/** @var ImageManager $manager */
|
||||||
$manager = resolve(ImageManager::class);
|
$manager = resolve(ImageManager::class);
|
||||||
|
@ -165,11 +162,18 @@ class MicropubMediaController extends Controller
|
||||||
|
|
||||||
$media = Media::create([
|
$media = Media::create([
|
||||||
'token' => $request->bearerToken(),
|
'token' => $request->bearerToken(),
|
||||||
'path' => $filename,
|
'path' => 'media/' . $filename,
|
||||||
'type' => $this->getFileTypeFromMimeType($request->file('file')->getMimeType()),
|
'type' => $this->getFileTypeFromMimeType($request->file('file')->getMimeType()),
|
||||||
'image_widths' => $width,
|
'image_widths' => $width,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
// put the file on S3 initially, the ProcessMedia job may edit this
|
||||||
|
Storage::disk('s3')->putFileAs(
|
||||||
|
'media',
|
||||||
|
new File(storage_path('app') . '/' . $filename),
|
||||||
|
$filename
|
||||||
|
);
|
||||||
|
|
||||||
ProcessMedia::dispatch($filename);
|
ProcessMedia::dispatch($filename);
|
||||||
|
|
||||||
return response()->json([
|
return response()->json([
|
||||||
|
@ -191,7 +195,7 @@ class MicropubMediaController extends Controller
|
||||||
*/
|
*/
|
||||||
private function getFileTypeFromMimeType(string $mimeType): string
|
private function getFileTypeFromMimeType(string $mimeType): string
|
||||||
{
|
{
|
||||||
// try known images
|
//try known images
|
||||||
$imageMimeTypes = [
|
$imageMimeTypes = [
|
||||||
'image/gif',
|
'image/gif',
|
||||||
'image/jpeg',
|
'image/jpeg',
|
||||||
|
@ -203,7 +207,7 @@ class MicropubMediaController extends Controller
|
||||||
if (in_array($mimeType, $imageMimeTypes)) {
|
if (in_array($mimeType, $imageMimeTypes)) {
|
||||||
return 'image';
|
return 'image';
|
||||||
}
|
}
|
||||||
// try known video
|
//try known video
|
||||||
$videoMimeTypes = [
|
$videoMimeTypes = [
|
||||||
'video/mp4',
|
'video/mp4',
|
||||||
'video/mpeg',
|
'video/mpeg',
|
||||||
|
@ -214,7 +218,7 @@ class MicropubMediaController extends Controller
|
||||||
if (in_array($mimeType, $videoMimeTypes)) {
|
if (in_array($mimeType, $videoMimeTypes)) {
|
||||||
return 'video';
|
return 'video';
|
||||||
}
|
}
|
||||||
// try known audio types
|
//try known audio types
|
||||||
$audioMimeTypes = [
|
$audioMimeTypes = [
|
||||||
'audio/midi',
|
'audio/midi',
|
||||||
'audio/mpeg',
|
'audio/mpeg',
|
||||||
|
@ -233,7 +237,7 @@ class MicropubMediaController extends Controller
|
||||||
*
|
*
|
||||||
* @throws Exception
|
* @throws Exception
|
||||||
*/
|
*/
|
||||||
private function saveFileToLocal(UploadedFile $file): string
|
private function saveFile(UploadedFile $file): string
|
||||||
{
|
{
|
||||||
$filename = Uuid::uuid4()->toString() . '.' . $file->extension();
|
$filename = Uuid::uuid4()->toString() . '.' . $file->extension();
|
||||||
Storage::disk('local')->putFileAs('', $file, $filename);
|
Storage::disk('local')->putFileAs('', $file, $filename);
|
||||||
|
|
|
@ -67,7 +67,7 @@ class NotesController extends Controller
|
||||||
*/
|
*/
|
||||||
public function redirect(int $decId): RedirectResponse
|
public function redirect(int $decId): RedirectResponse
|
||||||
{
|
{
|
||||||
return redirect(config('app.url') . '/notes/' . (new Numbers)->numto60($decId));
|
return redirect(config('app.url') . '/notes/' . (new Numbers())->numto60($decId));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -33,7 +33,7 @@ class WebMentionsController extends Controller
|
||||||
*/
|
*/
|
||||||
public function receive(Request $request): Response
|
public function receive(Request $request): Response
|
||||||
{
|
{
|
||||||
// first we trivially reject requests that lack all required inputs
|
//first we trivially reject requests that lack all required inputs
|
||||||
if (($request->has('target') !== true) || ($request->has('source') !== true)) {
|
if (($request->has('target') !== true) || ($request->has('source') !== true)) {
|
||||||
return response(
|
return response(
|
||||||
'You need both the target and source parameters',
|
'You need both the target and source parameters',
|
||||||
|
@ -41,12 +41,12 @@ class WebMentionsController extends Controller
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// next check the $target is valid
|
//next check the $target is valid
|
||||||
$path = parse_url($request->input('target'), PHP_URL_PATH);
|
$path = parse_url($request->input('target'), PHP_URL_PATH);
|
||||||
$pathParts = explode('/', $path);
|
$pathParts = explode('/', $path);
|
||||||
|
|
||||||
if ($pathParts[1] === 'notes') {
|
if ($pathParts[1] === 'notes') {
|
||||||
// we have a note
|
//we have a note
|
||||||
$noteId = $pathParts[2];
|
$noteId = $pathParts[2];
|
||||||
try {
|
try {
|
||||||
$note = Note::findOrFail(resolve(Numbers::class)->b60tonum($noteId));
|
$note = Note::findOrFail(resolve(Numbers::class)->b60tonum($noteId));
|
||||||
|
|
|
@ -35,30 +35,30 @@ class DownloadWebMention implements ShouldQueue
|
||||||
public function handle(Client $guzzle): void
|
public function handle(Client $guzzle): void
|
||||||
{
|
{
|
||||||
$response = $guzzle->request('GET', $this->source);
|
$response = $guzzle->request('GET', $this->source);
|
||||||
// 4XX and 5XX responses should get Guzzle to throw an exception,
|
//4XX and 5XX responses should get Guzzle to throw an exception,
|
||||||
// Laravel should catch and retry these automatically.
|
//Laravel should catch and retry these automatically.
|
||||||
if ($response->getStatusCode() === 200) {
|
if ($response->getStatusCode() === 200) {
|
||||||
$filesystem = new FileSystem;
|
$filesystem = new FileSystem();
|
||||||
$filename = storage_path('HTML') . '/' . $this->createFilenameFromURL($this->source);
|
$filename = storage_path('HTML') . '/' . $this->createFilenameFromURL($this->source);
|
||||||
// backup file first
|
//backup file first
|
||||||
$filenameBackup = $filename . '.' . date('Y-m-d') . '.backup';
|
$filenameBackup = $filename . '.' . date('Y-m-d') . '.backup';
|
||||||
if ($filesystem->exists($filename)) {
|
if ($filesystem->exists($filename)) {
|
||||||
$filesystem->copy($filename, $filenameBackup);
|
$filesystem->copy($filename, $filenameBackup);
|
||||||
}
|
}
|
||||||
// check if base directory exists
|
//check if base directory exists
|
||||||
if (! $filesystem->exists($filesystem->dirname($filename))) {
|
if (! $filesystem->exists($filesystem->dirname($filename))) {
|
||||||
$filesystem->makeDirectory(
|
$filesystem->makeDirectory(
|
||||||
$filesystem->dirname($filename),
|
$filesystem->dirname($filename),
|
||||||
0755, // mode
|
0755, //mode
|
||||||
true // recursive
|
true //recursive
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
// save new HTML
|
//save new HTML
|
||||||
$filesystem->put(
|
$filesystem->put(
|
||||||
$filename,
|
$filename,
|
||||||
(string) $response->getBody()
|
(string) $response->getBody()
|
||||||
);
|
);
|
||||||
// remove backup if the same
|
//remove backup if the same
|
||||||
if ($filesystem->exists($filenameBackup)) {
|
if ($filesystem->exists($filenameBackup)) {
|
||||||
if ($filesystem->get($filename) === $filesystem->get($filenameBackup)) {
|
if ($filesystem->get($filename) === $filesystem->get($filenameBackup)) {
|
||||||
$filesystem->delete($filenameBackup);
|
$filesystem->delete($filenameBackup);
|
||||||
|
|
|
@ -49,7 +49,7 @@ class ProcessLike implements ShouldQueue
|
||||||
$this->like->content = $tweet->html;
|
$this->like->content = $tweet->html;
|
||||||
$this->like->save();
|
$this->like->save();
|
||||||
|
|
||||||
// POSSE like
|
//POSSE like
|
||||||
try {
|
try {
|
||||||
$client->request(
|
$client->request(
|
||||||
'POST',
|
'POST',
|
||||||
|
|
|
@ -32,38 +32,35 @@ class ProcessMedia implements ShouldQueue
|
||||||
*/
|
*/
|
||||||
public function handle(ImageManager $manager): void
|
public function handle(ImageManager $manager): void
|
||||||
{
|
{
|
||||||
// Load file
|
//open file
|
||||||
$file = Storage::disk('local')->get('media/' . $this->filename);
|
|
||||||
|
|
||||||
// Open file
|
|
||||||
try {
|
try {
|
||||||
$image = $manager->read($file);
|
$image = $manager->read(storage_path('app') . '/' . $this->filename);
|
||||||
} catch (DecoderException) {
|
} catch (DecoderException) {
|
||||||
// not an image; delete file and end job
|
// not an image; delete file and end job
|
||||||
Storage::disk('local')->delete('media/' . $this->filename);
|
unlink(storage_path('app') . '/' . $this->filename);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
//create smaller versions if necessary
|
||||||
// Save the file publicly
|
|
||||||
Storage::disk('public')->put('media/' . $this->filename, $file);
|
|
||||||
|
|
||||||
// Create smaller versions if necessary
|
|
||||||
if ($image->width() > 1000) {
|
if ($image->width() > 1000) {
|
||||||
$filenameParts = explode('.', $this->filename);
|
$filenameParts = explode('.', $this->filename);
|
||||||
$extension = array_pop($filenameParts);
|
$extension = array_pop($filenameParts);
|
||||||
// the following achieves this data flow
|
// the following achieves this data flow
|
||||||
// foo.bar.png => ['foo', 'bar', 'png'] => ['foo', 'bar'] => foo.bar
|
// foo.bar.png => ['foo', 'bar', 'png'] => ['foo', 'bar'] => foo.bar
|
||||||
$basename = trim(implode('.', $filenameParts), '.');
|
$basename = ltrim(array_reduce($filenameParts, function ($carry, $item) {
|
||||||
|
return $carry . '.' . $item;
|
||||||
$medium = $image->resize(width: 1000);
|
}, ''), '.');
|
||||||
Storage::disk('public')->put('media/' . $basename . '-medium.' . $extension, (string) $medium->encode());
|
$medium = $image->resize(1000, null, function ($constraint) {
|
||||||
|
$constraint->aspectRatio();
|
||||||
$small = $image->resize(width: 500);
|
});
|
||||||
Storage::disk('public')->put('media/' . $basename . '-small.' . $extension, (string) $small->encode());
|
Storage::disk('s3')->put('media/' . $basename . '-medium.' . $extension, (string) $medium->encode());
|
||||||
|
$small = $image->resize(500, null, function ($constraint) {
|
||||||
|
$constraint->aspectRatio();
|
||||||
|
});
|
||||||
|
Storage::disk('s3')->put('media/' . $basename . '-small.' . $extension, (string) $small->encode());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Now we can delete the locally saved image
|
// now we can delete the locally saved image
|
||||||
Storage::disk('local')->delete('media/' . $this->filename);
|
unlink(storage_path('app') . '/' . $this->filename);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -44,7 +44,7 @@ class ProcessWebMention implements ShouldQueue
|
||||||
try {
|
try {
|
||||||
$response = $guzzle->request('GET', $this->source);
|
$response = $guzzle->request('GET', $this->source);
|
||||||
} catch (RequestException $e) {
|
} catch (RequestException $e) {
|
||||||
throw new RemoteContentNotFoundException;
|
throw new RemoteContentNotFoundException();
|
||||||
}
|
}
|
||||||
$this->saveRemoteContent((string) $response->getBody(), $this->source);
|
$this->saveRemoteContent((string) $response->getBody(), $this->source);
|
||||||
$microformats = Mf2\parse((string) $response->getBody(), $this->source);
|
$microformats = Mf2\parse((string) $response->getBody(), $this->source);
|
||||||
|
@ -85,7 +85,7 @@ class ProcessWebMention implements ShouldQueue
|
||||||
}// foreach
|
}// foreach
|
||||||
|
|
||||||
// no webmention in the db so create new one
|
// no webmention in the db so create new one
|
||||||
$webmention = new WebMention;
|
$webmention = new WebMention();
|
||||||
$type = $parser->getMentionType($microformats); // throw error here?
|
$type = $parser->getMentionType($microformats); // throw error here?
|
||||||
dispatch(new SaveProfileImage($microformats));
|
dispatch(new SaveProfileImage($microformats));
|
||||||
$webmention->source = $this->source;
|
$webmention->source = $this->source;
|
||||||
|
|
|
@ -49,7 +49,7 @@ class SaveProfileImage implements ShouldQueue
|
||||||
$home = array_shift($home);
|
$home = array_shift($home);
|
||||||
}
|
}
|
||||||
|
|
||||||
// dont save pbs.twimg.com links
|
//dont save pbs.twimg.com links
|
||||||
if (
|
if (
|
||||||
$photo
|
$photo
|
||||||
&& parse_url($photo, PHP_URL_HOST) !== 'pbs.twimg.com'
|
&& parse_url($photo, PHP_URL_HOST) !== 'pbs.twimg.com'
|
||||||
|
|
|
@ -72,7 +72,7 @@ class SendWebMentions implements ShouldQueue
|
||||||
|
|
||||||
$guzzle = resolve(Client::class);
|
$guzzle = resolve(Client::class);
|
||||||
$response = $guzzle->get($url);
|
$response = $guzzle->get($url);
|
||||||
// check HTTP Headers for webmention endpoint
|
//check HTTP Headers for webmention endpoint
|
||||||
$links = Header::parse($response->getHeader('Link'));
|
$links = Header::parse($response->getHeader('Link'));
|
||||||
foreach ($links as $link) {
|
foreach ($links as $link) {
|
||||||
if (array_key_exists('rel', $link) && mb_stristr($link['rel'], 'webmention')) {
|
if (array_key_exists('rel', $link) && mb_stristr($link['rel'], 'webmention')) {
|
||||||
|
@ -80,7 +80,7 @@ class SendWebMentions implements ShouldQueue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// failed to find a header so parse HTML
|
//failed to find a header so parse HTML
|
||||||
$html = (string) $response->getBody();
|
$html = (string) $response->getBody();
|
||||||
|
|
||||||
$mf2 = new \Mf2\Parser($html, $url);
|
$mf2 = new \Mf2\Parser($html, $url);
|
||||||
|
@ -108,7 +108,7 @@ class SendWebMentions implements ShouldQueue
|
||||||
}
|
}
|
||||||
|
|
||||||
$urls = [];
|
$urls = [];
|
||||||
$dom = new \DOMDocument;
|
$dom = new \DOMDocument();
|
||||||
$dom->loadHTML($html);
|
$dom->loadHTML($html);
|
||||||
$anchors = $dom->getElementsByTagName('a');
|
$anchors = $dom->getElementsByTagName('a');
|
||||||
foreach ($anchors as $anchor) {
|
foreach ($anchors as $anchor) {
|
||||||
|
|
|
@ -58,10 +58,10 @@ class Article extends Model
|
||||||
{
|
{
|
||||||
return Attribute::get(
|
return Attribute::get(
|
||||||
get: function () {
|
get: function () {
|
||||||
$environment = new Environment;
|
$environment = new Environment();
|
||||||
$environment->addExtension(new CommonMarkCoreExtension);
|
$environment->addExtension(new CommonMarkCoreExtension());
|
||||||
$environment->addRenderer(FencedCode::class, new FencedCodeRenderer);
|
$environment->addRenderer(FencedCode::class, new FencedCodeRenderer());
|
||||||
$environment->addRenderer(IndentedCode::class, new IndentedCodeRenderer);
|
$environment->addRenderer(IndentedCode::class, new IndentedCodeRenderer());
|
||||||
$markdownConverter = new MarkdownConverter($environment);
|
$markdownConverter = new MarkdownConverter($environment);
|
||||||
|
|
||||||
return $markdownConverter->convert($this->main)->getContent();
|
return $markdownConverter->convert($this->main)->getContent();
|
||||||
|
|
|
@ -33,7 +33,7 @@ class Media extends Model
|
||||||
return $attributes['path'];
|
return $attributes['path'];
|
||||||
}
|
}
|
||||||
|
|
||||||
return config('app.url') . '/storage/' . $attributes['path'];
|
return config('filesystems.disks.s3.url') . '/' . $attributes['path'];
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -78,7 +78,7 @@ class Media extends Model
|
||||||
$basename = $this->getBasename($path);
|
$basename = $this->getBasename($path);
|
||||||
$extension = $this->getExtension($path);
|
$extension = $this->getExtension($path);
|
||||||
|
|
||||||
return config('app.url') . '/storage/' . $basename . '-' . $size . '.' . $extension;
|
return config('filesystems.disks.s3.url') . '/' . $basename . '-' . $size . '.' . $extension;
|
||||||
}
|
}
|
||||||
|
|
||||||
private function getBasename(string $path): string
|
private function getBasename(string $path): string
|
||||||
|
|
|
@ -111,7 +111,7 @@ class Note extends Model
|
||||||
{
|
{
|
||||||
if ($value !== null) {
|
if ($value !== null) {
|
||||||
$normalized = normalizer_normalize($value, Normalizer::FORM_C);
|
$normalized = normalizer_normalize($value, Normalizer::FORM_C);
|
||||||
if ($normalized === '') { // we don’t want to save empty strings to the db
|
if ($normalized === '') { //we don’t want to save empty strings to the db
|
||||||
$normalized = null;
|
$normalized = null;
|
||||||
}
|
}
|
||||||
$this->attributes['note'] = $normalized;
|
$this->attributes['note'] = $normalized;
|
||||||
|
@ -271,7 +271,7 @@ class Note extends Model
|
||||||
]);
|
]);
|
||||||
|
|
||||||
if ($oEmbed->httpstatus >= 400) {
|
if ($oEmbed->httpstatus >= 400) {
|
||||||
throw new Exception;
|
throw new Exception();
|
||||||
}
|
}
|
||||||
} catch (Exception $e) {
|
} catch (Exception $e) {
|
||||||
return null;
|
return null;
|
||||||
|
@ -388,18 +388,18 @@ class Note extends Model
|
||||||
'mentions_handle' => [
|
'mentions_handle' => [
|
||||||
'prefix' => '@',
|
'prefix' => '@',
|
||||||
'pattern' => '([\w@.])+(\b)',
|
'pattern' => '([\w@.])+(\b)',
|
||||||
'generator' => new MentionGenerator,
|
'generator' => new MentionGenerator(),
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
];
|
];
|
||||||
|
|
||||||
$environment = new Environment($config);
|
$environment = new Environment($config);
|
||||||
$environment->addExtension(new CommonMarkCoreExtension);
|
$environment->addExtension(new CommonMarkCoreExtension());
|
||||||
$environment->addExtension(new AutolinkExtension);
|
$environment->addExtension(new AutolinkExtension());
|
||||||
$environment->addExtension(new MentionExtension);
|
$environment->addExtension(new MentionExtension());
|
||||||
$environment->addRenderer(Mention::class, new MentionRenderer);
|
$environment->addRenderer(Mention::class, new MentionRenderer());
|
||||||
$environment->addRenderer(FencedCode::class, new FencedCodeRenderer);
|
$environment->addRenderer(FencedCode::class, new FencedCodeRenderer());
|
||||||
$environment->addRenderer(IndentedCode::class, new IndentedCodeRenderer);
|
$environment->addRenderer(IndentedCode::class, new IndentedCodeRenderer());
|
||||||
$markdownConverter = new MarkdownConverter($environment);
|
$markdownConverter = new MarkdownConverter($environment);
|
||||||
|
|
||||||
return $markdownConverter->convert($note)->getContent();
|
return $markdownConverter->convert($note)->getContent();
|
||||||
|
|
|
@ -59,7 +59,7 @@ class Place extends Model
|
||||||
* sin(radians(places.latitude))))";
|
* sin(radians(places.latitude))))";
|
||||||
|
|
||||||
return $query
|
return $query
|
||||||
->select() // pick the columns you want here.
|
->select() //pick the columns you want here.
|
||||||
->selectRaw("{$haversine} AS distance")
|
->selectRaw("{$haversine} AS distance")
|
||||||
->whereRaw("{$haversine} < ?", [$distance]);
|
->whereRaw("{$haversine} < ?", [$distance]);
|
||||||
}
|
}
|
||||||
|
|
|
@ -42,7 +42,7 @@ class WebMention extends Model
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
$authorship = new Authorship;
|
$authorship = new Authorship();
|
||||||
$hCard = $authorship->findAuthor(json_decode($attributes['mf2'], true));
|
$hCard = $authorship->findAuthor(json_decode($attributes['mf2'], true));
|
||||||
|
|
||||||
if ($hCard === false) {
|
if ($hCard === false) {
|
||||||
|
@ -123,7 +123,7 @@ class WebMention extends Model
|
||||||
$host = parse_url($url, PHP_URL_HOST);
|
$host = parse_url($url, PHP_URL_HOST);
|
||||||
|
|
||||||
if ($host === 'pbs.twimg.com') {
|
if ($host === 'pbs.twimg.com') {
|
||||||
// make sure we use HTTPS, we know twitter supports it
|
//make sure we use HTTPS, we know twitter supports it
|
||||||
return str_replace('http://', 'https://', $url);
|
return str_replace('http://', 'https://', $url);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -135,12 +135,12 @@ class WebMention extends Model
|
||||||
$codebird = resolve(Codebird::class);
|
$codebird = resolve(Codebird::class);
|
||||||
$info = $codebird->users_show(['screen_name' => $username]);
|
$info = $codebird->users_show(['screen_name' => $username]);
|
||||||
$profile_image = $info->profile_image_url_https;
|
$profile_image = $info->profile_image_url_https;
|
||||||
Cache::put($url, $profile_image, 10080); // 1 week
|
Cache::put($url, $profile_image, 10080); //1 week
|
||||||
|
|
||||||
return $profile_image;
|
return $profile_image;
|
||||||
}
|
}
|
||||||
|
|
||||||
$filesystem = new Filesystem;
|
$filesystem = new Filesystem();
|
||||||
if ($filesystem->exists(public_path() . '/assets/profile-images/' . $host . '/image')) {
|
if ($filesystem->exists(public_path() . '/assets/profile-images/' . $host . '/image')) {
|
||||||
return '/assets/profile-images/' . $host . '/image';
|
return '/assets/profile-images/' . $host . '/image';
|
||||||
}
|
}
|
||||||
|
|
|
@ -88,9 +88,9 @@ class AppServiceProvider extends ServiceProvider
|
||||||
$this->app->bind('Lcobucci\JWT\Configuration', function () {
|
$this->app->bind('Lcobucci\JWT\Configuration', function () {
|
||||||
$key = InMemory::plainText(config('app.key'));
|
$key = InMemory::plainText(config('app.key'));
|
||||||
|
|
||||||
$config = Configuration::forSymmetricSigner(new Sha256, $key);
|
$config = Configuration::forSymmetricSigner(new Sha256(), $key);
|
||||||
|
|
||||||
$config->setValidationConstraints(new SignedWith(new Sha256, $key));
|
$config->setValidationConstraints(new SignedWith(new Sha256(), $key));
|
||||||
|
|
||||||
return $config;
|
return $config;
|
||||||
});
|
});
|
||||||
|
@ -98,7 +98,7 @@ class AppServiceProvider extends ServiceProvider
|
||||||
// Configure HtmlSanitizer
|
// Configure HtmlSanitizer
|
||||||
$this->app->bind(HtmlSanitizer::class, function () {
|
$this->app->bind(HtmlSanitizer::class, function () {
|
||||||
return new HtmlSanitizer(
|
return new HtmlSanitizer(
|
||||||
(new HtmlSanitizerConfig)
|
(new HtmlSanitizerConfig())
|
||||||
->allowSafeElements()
|
->allowSafeElements()
|
||||||
->forceAttribute('a', 'rel', 'noopener nofollow')
|
->forceAttribute('a', 'rel', 'noopener nofollow')
|
||||||
);
|
);
|
||||||
|
|
|
@ -21,7 +21,7 @@ class BookmarkService extends Service
|
||||||
public function create(array $request, ?string $client = null): Bookmark
|
public function create(array $request, ?string $client = null): Bookmark
|
||||||
{
|
{
|
||||||
if (Arr::get($request, 'properties.bookmark-of.0')) {
|
if (Arr::get($request, 'properties.bookmark-of.0')) {
|
||||||
// micropub request
|
//micropub request
|
||||||
$url = normalize_url(Arr::get($request, 'properties.bookmark-of.0'));
|
$url = normalize_url(Arr::get($request, 'properties.bookmark-of.0'));
|
||||||
$name = Arr::get($request, 'properties.name.0');
|
$name = Arr::get($request, 'properties.name.0');
|
||||||
$content = Arr::get($request, 'properties.content.0');
|
$content = Arr::get($request, 'properties.content.0');
|
||||||
|
@ -61,8 +61,8 @@ class BookmarkService extends Service
|
||||||
try {
|
try {
|
||||||
$response = $client->request('GET', 'https://web.archive.org/save/' . $url);
|
$response = $client->request('GET', 'https://web.archive.org/save/' . $url);
|
||||||
} catch (ClientException $e) {
|
} catch (ClientException $e) {
|
||||||
// throw an exception to be caught
|
//throw an exception to be caught
|
||||||
throw new InternetArchiveException;
|
throw new InternetArchiveException();
|
||||||
}
|
}
|
||||||
if ($response->hasHeader('Content-Location')) {
|
if ($response->hasHeader('Content-Location')) {
|
||||||
if (Str::startsWith(Arr::get($response->getHeader('Content-Location'), 0), '/web')) {
|
if (Str::startsWith(Arr::get($response->getHeader('Content-Location'), 0), '/web')) {
|
||||||
|
@ -70,7 +70,7 @@ class BookmarkService extends Service
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// throw an exception to be caught
|
//throw an exception to be caught
|
||||||
throw new InternetArchiveException;
|
throw new InternetArchiveException();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,7 +16,7 @@ class LikeService extends Service
|
||||||
public function create(array $request, ?string $client = null): Like
|
public function create(array $request, ?string $client = null): Like
|
||||||
{
|
{
|
||||||
if (Arr::get($request, 'properties.like-of.0')) {
|
if (Arr::get($request, 'properties.like-of.0')) {
|
||||||
// micropub request
|
//micropub request
|
||||||
$url = normalize_url(Arr::get($request, 'properties.like-of.0'));
|
$url = normalize_url(Arr::get($request, 'properties.like-of.0'));
|
||||||
}
|
}
|
||||||
if (Arr::get($request, 'like-of')) {
|
if (Arr::get($request, 'like-of')) {
|
||||||
|
|
|
@ -20,7 +20,7 @@ class UpdateService
|
||||||
{
|
{
|
||||||
$urlPath = parse_url(Arr::get($request, 'url'), PHP_URL_PATH);
|
$urlPath = parse_url(Arr::get($request, 'url'), PHP_URL_PATH);
|
||||||
|
|
||||||
// is it a note we are updating?
|
//is it a note we are updating?
|
||||||
if (mb_substr($urlPath, 1, 5) !== 'notes') {
|
if (mb_substr($urlPath, 1, 5) !== 'notes') {
|
||||||
return response()->json([
|
return response()->json([
|
||||||
'error' => 'invalid',
|
'error' => 'invalid',
|
||||||
|
@ -37,7 +37,7 @@ class UpdateService
|
||||||
], 404);
|
], 404);
|
||||||
}
|
}
|
||||||
|
|
||||||
// got the note, are we dealing with a “replace” request?
|
//got the note, are we dealing with a “replace” request?
|
||||||
if (Arr::get($request, 'replace')) {
|
if (Arr::get($request, 'replace')) {
|
||||||
foreach (Arr::get($request, 'replace') as $property => $value) {
|
foreach (Arr::get($request, 'replace') as $property => $value) {
|
||||||
if ($property === 'content') {
|
if ($property === 'content') {
|
||||||
|
@ -64,7 +64,7 @@ class UpdateService
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// how about “add”
|
//how about “add”
|
||||||
if (Arr::get($request, 'add')) {
|
if (Arr::get($request, 'add')) {
|
||||||
foreach (Arr::get($request, 'add') as $property => $value) {
|
foreach (Arr::get($request, 'add') as $property => $value) {
|
||||||
if ($property === 'syndication') {
|
if ($property === 'syndication') {
|
||||||
|
@ -83,7 +83,7 @@ class UpdateService
|
||||||
if ($property === 'photo') {
|
if ($property === 'photo') {
|
||||||
foreach ($value as $photoURL) {
|
foreach ($value as $photoURL) {
|
||||||
if (Str::startsWith($photoURL, 'https://')) {
|
if (Str::startsWith($photoURL, 'https://')) {
|
||||||
$media = new Media;
|
$media = new Media();
|
||||||
$media->path = $photoURL;
|
$media->path = $photoURL;
|
||||||
$media->type = 'image';
|
$media->type = 'image';
|
||||||
$media->save();
|
$media->save();
|
||||||
|
|
|
@ -14,8 +14,8 @@ class PlaceService
|
||||||
*/
|
*/
|
||||||
public function createPlace(array $data): Place
|
public function createPlace(array $data): Place
|
||||||
{
|
{
|
||||||
// obviously a place needs a lat/lng, but this could be sent in a geo-url
|
//obviously a place needs a lat/lng, but this could be sent in a geo-url
|
||||||
// if no geo array key, we assume the array already has lat/lng values
|
//if no geo array key, we assume the array already has lat/lng values
|
||||||
if (array_key_exists('geo', $data) && $data['geo'] !== null) {
|
if (array_key_exists('geo', $data) && $data['geo'] !== null) {
|
||||||
preg_match_all(
|
preg_match_all(
|
||||||
'/([0-9\.\-]+)/',
|
'/([0-9\.\-]+)/',
|
||||||
|
@ -25,7 +25,7 @@ class PlaceService
|
||||||
$data['latitude'] = $matches[0][0];
|
$data['latitude'] = $matches[0][0];
|
||||||
$data['longitude'] = $matches[0][1];
|
$data['longitude'] = $matches[0][1];
|
||||||
}
|
}
|
||||||
$place = new Place;
|
$place = new Place();
|
||||||
$place->name = $data['name'];
|
$place->name = $data['name'];
|
||||||
$place->description = $data['description'];
|
$place->description = $data['description'];
|
||||||
$place->latitude = $data['latitude'];
|
$place->latitude = $data['latitude'];
|
||||||
|
@ -40,7 +40,7 @@ class PlaceService
|
||||||
*/
|
*/
|
||||||
public function createPlaceFromCheckin(array $checkin): Place
|
public function createPlaceFromCheckin(array $checkin): Place
|
||||||
{
|
{
|
||||||
// check if the place exists if from swarm
|
//check if the place exists if from swarm
|
||||||
if (Arr::has($checkin, 'properties.url')) {
|
if (Arr::has($checkin, 'properties.url')) {
|
||||||
$place = Place::whereExternalURL(Arr::get($checkin, 'properties.url.0'))->get();
|
$place = Place::whereExternalURL(Arr::get($checkin, 'properties.url.0'))->get();
|
||||||
if (count($place) === 1) {
|
if (count($place) === 1) {
|
||||||
|
@ -53,7 +53,7 @@ class PlaceService
|
||||||
if (Arr::has($checkin, 'properties.latitude') === false) {
|
if (Arr::has($checkin, 'properties.latitude') === false) {
|
||||||
throw new \InvalidArgumentException('Missing required longitude/latitude');
|
throw new \InvalidArgumentException('Missing required longitude/latitude');
|
||||||
}
|
}
|
||||||
$place = new Place;
|
$place = new Place();
|
||||||
$place->name = Arr::get($checkin, 'properties.name.0');
|
$place->name = Arr::get($checkin, 'properties.name.0');
|
||||||
$place->external_urls = Arr::get($checkin, 'properties.url.0');
|
$place->external_urls = Arr::get($checkin, 'properties.url.0');
|
||||||
$place->latitude = Arr::get($checkin, 'properties.latitude.0');
|
$place->latitude = Arr::get($checkin, 'properties.latitude.0');
|
||||||
|
|
|
@ -19,7 +19,7 @@ class TokenService
|
||||||
$config = resolve(Configuration::class);
|
$config = resolve(Configuration::class);
|
||||||
|
|
||||||
$token = $config->builder()
|
$token = $config->builder()
|
||||||
->issuedAt(new DateTimeImmutable)
|
->issuedAt(new DateTimeImmutable())
|
||||||
->withClaim('client_id', $data['client_id'])
|
->withClaim('client_id', $data['client_id'])
|
||||||
->withClaim('me', $data['me'])
|
->withClaim('me', $data['me'])
|
||||||
->withClaim('scope', $data['scope'])
|
->withClaim('scope', $data['scope'])
|
||||||
|
|
|
@ -1,8 +1,7 @@
|
||||||
{
|
{
|
||||||
"$schema": "https://getcomposer.org/schema.json",
|
|
||||||
"name": "jonnybarnes/jonnybarnes.uk",
|
"name": "jonnybarnes/jonnybarnes.uk",
|
||||||
"type": "project",
|
"type": "project",
|
||||||
"description": "The code for jonnybarnes.uk, based on Laravel 11",
|
"description": "The code for jonnybarnes.uk, based on Laravel 10",
|
||||||
"keywords": ["laravel", "framework", "indieweb"],
|
"keywords": ["laravel", "framework", "indieweb"],
|
||||||
"license": "CC0-1.0",
|
"license": "CC0-1.0",
|
||||||
"require": {
|
"require": {
|
||||||
|
@ -12,14 +11,14 @@
|
||||||
"ext-json": "*",
|
"ext-json": "*",
|
||||||
"ext-pgsql": "*",
|
"ext-pgsql": "*",
|
||||||
"ext-sodium": "*",
|
"ext-sodium": "*",
|
||||||
"cviebrock/eloquent-sluggable": "^12.0",
|
"cviebrock/eloquent-sluggable": "^11.0",
|
||||||
"guzzlehttp/guzzle": "^7.2",
|
"guzzlehttp/guzzle": "^7.2",
|
||||||
"indieauth/client": "^1.1",
|
"indieauth/client": "^1.1",
|
||||||
"intervention/image": "^3",
|
"intervention/image": "^3",
|
||||||
"jonnybarnes/indieweb": "~0.2",
|
"jonnybarnes/indieweb": "~0.2",
|
||||||
"jonnybarnes/webmentions-parser": "~0.5",
|
"jonnybarnes/webmentions-parser": "~0.5",
|
||||||
"jublonet/codebird-php": "4.0.0-beta.1",
|
"jublonet/codebird-php": "4.0.0-beta.1",
|
||||||
"laravel/framework": "^12.0",
|
"laravel/framework": "^11.0",
|
||||||
"laravel/horizon": "^5.0",
|
"laravel/horizon": "^5.0",
|
||||||
"laravel/sanctum": "^4.0",
|
"laravel/sanctum": "^4.0",
|
||||||
"laravel/scout": "^10.1",
|
"laravel/scout": "^10.1",
|
||||||
|
@ -41,15 +40,16 @@
|
||||||
"barryvdh/laravel-ide-helper": "^3.0",
|
"barryvdh/laravel-ide-helper": "^3.0",
|
||||||
"fakerphp/faker": "^1.9.2",
|
"fakerphp/faker": "^1.9.2",
|
||||||
"laravel/dusk": "^8.0",
|
"laravel/dusk": "^8.0",
|
||||||
"laravel/pail": "^1.2",
|
|
||||||
"laravel/pint": "^1.0",
|
"laravel/pint": "^1.0",
|
||||||
"laravel/sail": "^1.18",
|
"laravel/sail": "^1.18",
|
||||||
"mockery/mockery": "^1.4.4",
|
"mockery/mockery": "^1.4.4",
|
||||||
"nunomaduro/collision": "^8.1",
|
"nunomaduro/collision": "^8.1",
|
||||||
"openai-php/client": "^0.10.1",
|
"openai-php/client": "^0.10.1",
|
||||||
"phpunit/php-code-coverage": "^11.0",
|
"phpunit/php-code-coverage": "^10.0",
|
||||||
"phpunit/phpunit": "^11.0",
|
"phpunit/phpunit": "^10.1",
|
||||||
"spatie/laravel-ray": "^1.12"
|
"psalm/plugin-laravel": "^2.8",
|
||||||
|
"spatie/laravel-ray": "^1.12",
|
||||||
|
"vimeo/psalm": "^5.0"
|
||||||
},
|
},
|
||||||
"autoload": {
|
"autoload": {
|
||||||
"psr-4": {
|
"psr-4": {
|
||||||
|
@ -78,13 +78,7 @@
|
||||||
"@php -r \"file_exists('.env') || copy('.env.example', '.env');\""
|
"@php -r \"file_exists('.env') || copy('.env.example', '.env');\""
|
||||||
],
|
],
|
||||||
"post-create-project-cmd": [
|
"post-create-project-cmd": [
|
||||||
"@php artisan key:generate --ansi",
|
"@php artisan key:generate --ansi"
|
||||||
"@php -r \"file_exists('database/database.sqlite') || touch('database/database.sqlite');\"",
|
|
||||||
"@php artisan migrate --graceful --ansi"
|
|
||||||
],
|
|
||||||
"dev": [
|
|
||||||
"Composer\\Config::disableProcessTimeout",
|
|
||||||
"npx concurrently -c \"#93c5fd,#c4b5fd,#fb7185,#fdba74\" \"php artisan serve\" \"php artisan queue:listen --tries=1\" \"php artisan pail --timeout=0\" \"npm run dev\" --names=server,queue,logs,vite"
|
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"extra": {
|
"extra": {
|
||||||
|
|
4144
composer.lock
generated
4144
composer.lock
generated
File diff suppressed because it is too large
Load diff
|
@ -65,7 +65,7 @@ return [
|
||||||
|
|
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
'timezone' => 'UTC',
|
'timezone' => env('APP_TIMEZONE', 'UTC'),
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|--------------------------------------------------------------------------
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
@ -37,9 +37,6 @@ return [
|
||||||
'database' => env('DB_DATABASE', database_path('database.sqlite')),
|
'database' => env('DB_DATABASE', database_path('database.sqlite')),
|
||||||
'prefix' => '',
|
'prefix' => '',
|
||||||
'foreign_key_constraints' => env('DB_FOREIGN_KEYS', true),
|
'foreign_key_constraints' => env('DB_FOREIGN_KEYS', true),
|
||||||
'busy_timeout' => null,
|
|
||||||
'journal_mode' => null,
|
|
||||||
'synchronous' => null,
|
|
||||||
],
|
],
|
||||||
|
|
||||||
'mysql' => [
|
'mysql' => [
|
||||||
|
@ -148,7 +145,6 @@ return [
|
||||||
'options' => [
|
'options' => [
|
||||||
'cluster' => env('REDIS_CLUSTER', 'redis'),
|
'cluster' => env('REDIS_CLUSTER', 'redis'),
|
||||||
'prefix' => env('REDIS_PREFIX', Str::slug(env('APP_NAME', 'laravel'), '_').'_database_'),
|
'prefix' => env('REDIS_PREFIX', Str::slug(env('APP_NAME', 'laravel'), '_').'_database_'),
|
||||||
'persistent' => env('REDIS_PERSISTENT', false),
|
|
||||||
],
|
],
|
||||||
|
|
||||||
'default' => [
|
'default' => [
|
||||||
|
|
|
@ -119,7 +119,7 @@ return [
|
||||||
'full_log' => false,
|
'full_log' => false,
|
||||||
],
|
],
|
||||||
'views' => [
|
'views' => [
|
||||||
'data' => false, // Note: Can slow down the application, because the data can be quite large..
|
'data' => false, //Note: Can slow down the application, because the data can be quite large..
|
||||||
],
|
],
|
||||||
'route' => [
|
'route' => [
|
||||||
'label' => true, // show complete route on bar
|
'label' => true, // show complete route on bar
|
||||||
|
|
|
@ -32,10 +32,8 @@ return [
|
||||||
|
|
||||||
'local' => [
|
'local' => [
|
||||||
'driver' => 'local',
|
'driver' => 'local',
|
||||||
'root' => storage_path('app/private'),
|
'root' => storage_path('app'),
|
||||||
'serve' => true,
|
|
||||||
'throw' => false,
|
'throw' => false,
|
||||||
'report' => false,
|
|
||||||
],
|
],
|
||||||
|
|
||||||
'public' => [
|
'public' => [
|
||||||
|
@ -44,7 +42,6 @@ return [
|
||||||
'url' => env('APP_URL').'/storage',
|
'url' => env('APP_URL').'/storage',
|
||||||
'visibility' => 'public',
|
'visibility' => 'public',
|
||||||
'throw' => false,
|
'throw' => false,
|
||||||
'report' => false,
|
|
||||||
],
|
],
|
||||||
|
|
||||||
's3' => [
|
's3' => [
|
||||||
|
@ -57,7 +54,6 @@ return [
|
||||||
'endpoint' => env('AWS_ENDPOINT'),
|
'endpoint' => env('AWS_ENDPOINT'),
|
||||||
'use_path_style_endpoint' => env('AWS_USE_PATH_STYLE_ENDPOINT', false),
|
'use_path_style_endpoint' => env('AWS_USE_PATH_STYLE_ENDPOINT', false),
|
||||||
'throw' => false,
|
'throw' => false,
|
||||||
'report' => false,
|
|
||||||
],
|
],
|
||||||
|
|
||||||
],
|
],
|
||||||
|
|
|
@ -38,14 +38,14 @@ return [
|
||||||
|
|
||||||
'smtp' => [
|
'smtp' => [
|
||||||
'transport' => 'smtp',
|
'transport' => 'smtp',
|
||||||
'scheme' => env('MAIL_SCHEME'),
|
|
||||||
'url' => env('MAIL_URL'),
|
'url' => env('MAIL_URL'),
|
||||||
'host' => env('MAIL_HOST', '127.0.0.1'),
|
'host' => env('MAIL_HOST', '127.0.0.1'),
|
||||||
'port' => env('MAIL_PORT', 2525),
|
'port' => env('MAIL_PORT', 2525),
|
||||||
|
'encryption' => env('MAIL_ENCRYPTION', 'tls'),
|
||||||
'username' => env('MAIL_USERNAME'),
|
'username' => env('MAIL_USERNAME'),
|
||||||
'password' => env('MAIL_PASSWORD'),
|
'password' => env('MAIL_PASSWORD'),
|
||||||
'timeout' => null,
|
'timeout' => null,
|
||||||
'local_domain' => env('MAIL_EHLO_DOMAIN', parse_url(env('APP_URL', 'http://localhost'), PHP_URL_HOST)),
|
'local_domain' => env('MAIL_EHLO_DOMAIN'),
|
||||||
],
|
],
|
||||||
|
|
||||||
'ses' => [
|
'ses' => [
|
||||||
|
|
|
@ -32,7 +32,7 @@ return [
|
||||||
|
|
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
'lifetime' => (int) env('SESSION_LIFETIME', 120),
|
'lifetime' => env('SESSION_LIFETIME', 120),
|
||||||
|
|
||||||
'expire_on_close' => env('SESSION_EXPIRE_ON_CLOSE', false),
|
'expire_on_close' => env('SESSION_EXPIRE_ON_CLOSE', false),
|
||||||
|
|
||||||
|
|
|
@ -27,7 +27,7 @@ class ContactsTableSeeder extends Seeder
|
||||||
'homepage' => 'https://aaronparecki.com',
|
'homepage' => 'https://aaronparecki.com',
|
||||||
'facebook' => '123456',
|
'facebook' => '123456',
|
||||||
]);
|
]);
|
||||||
$fs = new FileSystem;
|
$fs = new FileSystem();
|
||||||
if (! $fs->exists(public_path('assets/profile-images/aaronparecki.com'))) {
|
if (! $fs->exists(public_path('assets/profile-images/aaronparecki.com'))) {
|
||||||
$fs->makeDirectory(public_path('assets/profile-images/aaronparecki.com'));
|
$fs->makeDirectory(public_path('assets/profile-images/aaronparecki.com'));
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,7 +20,7 @@ class LikesTableSeeder extends Seeder
|
||||||
Like::factory(10)->create();
|
Like::factory(10)->create();
|
||||||
|
|
||||||
$now = Carbon::now()->subDays(rand(3, 6));
|
$now = Carbon::now()->subDays(rand(3, 6));
|
||||||
$faker = new Generator;
|
$faker = new Generator();
|
||||||
$faker->addProvider(new \Faker\Provider\en_US\Person($faker));
|
$faker->addProvider(new \Faker\Provider\en_US\Person($faker));
|
||||||
$faker->addProvider(new \Faker\Provider\Lorem($faker));
|
$faker->addProvider(new \Faker\Provider\Lorem($faker));
|
||||||
$faker->addProvider(new \Faker\Provider\Internet($faker));
|
$faker->addProvider(new \Faker\Provider\Internet($faker));
|
||||||
|
|
|
@ -83,7 +83,7 @@ class NotesTableSeeder extends Seeder
|
||||||
->where('id', $noteWithoutContact->id)
|
->where('id', $noteWithoutContact->id)
|
||||||
->update(['updated_at' => $now->toDateTimeString()]);
|
->update(['updated_at' => $now->toDateTimeString()]);
|
||||||
|
|
||||||
// copy aaron’s profile pic in place
|
//copy aaron’s profile pic in place
|
||||||
$spl = new SplFileInfo(public_path() . '/assets/profile-images/aaronparecki.com');
|
$spl = new SplFileInfo(public_path() . '/assets/profile-images/aaronparecki.com');
|
||||||
if ($spl->isDir() === false) {
|
if ($spl->isDir() === false) {
|
||||||
mkdir(public_path() . '/assets/profile-images/aaronparecki.com', 0755);
|
mkdir(public_path() . '/assets/profile-images/aaronparecki.com', 0755);
|
||||||
|
@ -154,7 +154,7 @@ class NotesTableSeeder extends Seeder
|
||||||
->update(['updated_at' => $now->toDateTimeString()]);
|
->update(['updated_at' => $now->toDateTimeString()]);
|
||||||
|
|
||||||
$now = Carbon::now()->subHours(5);
|
$now = Carbon::now()->subHours(5);
|
||||||
$noteJustCheckin = new Note;
|
$noteJustCheckin = new Note();
|
||||||
$noteJustCheckin->setCreatedAt($now);
|
$noteJustCheckin->setCreatedAt($now);
|
||||||
$place = Place::find(1);
|
$place = Place::find(1);
|
||||||
$noteJustCheckin->place()->associate($place);
|
$noteJustCheckin->place()->associate($place);
|
||||||
|
@ -164,12 +164,12 @@ class NotesTableSeeder extends Seeder
|
||||||
->update(['updated_at' => $now->toDateTimeString()]);
|
->update(['updated_at' => $now->toDateTimeString()]);
|
||||||
|
|
||||||
$now = Carbon::now()->subHours(4);
|
$now = Carbon::now()->subHours(4);
|
||||||
$media = new Media;
|
$media = new Media();
|
||||||
$media->path = 'media/f1bc8faa-1a8f-45b8-a9b1-57282fa73f87.jpg';
|
$media->path = 'media/f1bc8faa-1a8f-45b8-a9b1-57282fa73f87.jpg';
|
||||||
$media->type = 'image';
|
$media->type = 'image';
|
||||||
$media->image_widths = '3648';
|
$media->image_widths = '3648';
|
||||||
$media->save();
|
$media->save();
|
||||||
$noteWithOnlyImage = new Note;
|
$noteWithOnlyImage = new Note();
|
||||||
$noteWithOnlyImage->setCreatedAt($now);
|
$noteWithOnlyImage->setCreatedAt($now);
|
||||||
$noteWithOnlyImage->setUpdatedAt($now);
|
$noteWithOnlyImage->setUpdatedAt($now);
|
||||||
$noteWithOnlyImage->save();
|
$noteWithOnlyImage->save();
|
||||||
|
|
|
@ -14,7 +14,7 @@ class PlacesTableSeeder extends Seeder
|
||||||
*/
|
*/
|
||||||
public function run(): void
|
public function run(): void
|
||||||
{
|
{
|
||||||
$place = new Place;
|
$place = new Place();
|
||||||
$place->name = 'The Bridgewater Pub';
|
$place->name = 'The Bridgewater Pub';
|
||||||
$place->description = 'A lovely local pub with a decent selection of cask ales';
|
$place->description = 'A lovely local pub with a decent selection of cask ales';
|
||||||
$place->latitude = 53.4983;
|
$place->latitude = 53.4983;
|
||||||
|
|
|
@ -41,14 +41,5 @@ class WebMentionsTableSeeder extends Seeder
|
||||||
'type' => 'repost-of',
|
'type' => 'repost-of',
|
||||||
'mf2' => '{"rels": [], "items": [{"type": ["h-entry"], "properties": {"url": ["https://barryfrost.com/reposts/1"], "name": ["Kagi is the best"], "author": [{"type": ["h-card"], "value": "Barry Frost", "properties": {"url": ["https://barryfrost.com/"], "name": ["Barry Frost"], "photo": ["https://barryfrost.com/barryfrost.jpg"]}}], "content": [{"html": "Kagi is the Best", "value": "Kagi is the Best"}], "published": ["' . date(DATE_W3C) . '"], "u-repost-of": ["' . config('app.url') . '/notes/C"]}}]}',
|
'mf2' => '{"rels": [], "items": [{"type": ["h-entry"], "properties": {"url": ["https://barryfrost.com/reposts/1"], "name": ["Kagi is the best"], "author": [{"type": ["h-card"], "value": "Barry Frost", "properties": {"url": ["https://barryfrost.com/"], "name": ["Barry Frost"], "photo": ["https://barryfrost.com/barryfrost.jpg"]}}], "content": [{"html": "Kagi is the Best", "value": "Kagi is the Best"}], "published": ["' . date(DATE_W3C) . '"], "u-repost-of": ["' . config('app.url') . '/notes/C"]}}]}',
|
||||||
]);
|
]);
|
||||||
// WebMention like from Bluesky
|
|
||||||
WebMention::create([
|
|
||||||
'source' => 'https://brid.gy/like/bluesky/did:plc:n3jhgiq2ykctnpgzlm6p6b25/at%253A%252F%252Fdid%253Aplc%253An3jhgiq2ykctnpgzlm6p6b25%252Fapp.bsky.feed.post%252F3lalppbcyuc2w/did%253Aplc%253Aia23nh3t37r2lydmmqsixrps',
|
|
||||||
'target' => config('app.url') . '/notes/B',
|
|
||||||
'commentable_id' => '11',
|
|
||||||
'commentable_type' => 'App\Models\Note',
|
|
||||||
'type' => 'like-of',
|
|
||||||
'mf2' => '{"rels": [], "items": [{"type": ["h-entry"], "properties": {"uid": ["tag:bsky.app,2013:at://did:plc:n3jhgiq2ykctnpgzlm6p6b25/app.bsky.feed.post/3lalppbcyuc2w_liked_by_did:plc:ia23nh3t37r2lydmmqsixrps"], "url": ["https://bsky.app/profile/jonnybarnes.uk/post/3lalppbcyuc2w#liked_by_did:plc:ia23nh3t37r2lydmmqsixrps"], "name": [""], "author": [{"type": ["h-card"], "value": "bsky.app/profile/little... littledawg13.bsky.social", "properties": {"uid": ["tag:bsky.app,2013:did:plc:ia23nh3t37r2lydmmqsixrps"], "url": ["https://bsky.app/profile/littledawg13.bsky.social", "https://bsky.app/profile/did:plc:ia23nh3t37r2lydmmqsixrps"], "photo": [{"alt": "", "value": "https://cdn.bsky.app/img/avatar/plain/did:plc:ia23nh3t37r2lydmmqsixrps/bafkreifh7ydbyq7qe4maorornocksfnahijxqgx2i5zvvyq6y4i4mydfau@jpeg"}], "nickname": ["littledawg13.bsky.social"]}}], "like-of": ["https://bsky.app/profile/jonnybarnes.uk/post/3lalppbcyuc2w", "http://jonnybarnes.localhost/notes/B"]}}], "rel-urls": []}',
|
|
||||||
]);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -138,7 +138,7 @@ if (! function_exists('normalize_url')) {
|
||||||
$url['query'] = '';
|
$url['query'] = '';
|
||||||
sort($queries);
|
sort($queries);
|
||||||
foreach ($queries as $query) {
|
foreach ($queries as $query) {
|
||||||
// lets drop query params we don’t want
|
//lets drop query params we don’t want
|
||||||
$key = stristr($query, '=', true);
|
$key = stristr($query, '=', true);
|
||||||
if (queryKeyIsBanned($key) === false) {
|
if (queryKeyIsBanned($key) === false) {
|
||||||
$url['query'] .= "{$query}&";
|
$url['query'] .= "{$query}&";
|
||||||
|
@ -197,7 +197,7 @@ if (! function_exists('prettyPrintJson')) {
|
||||||
case '{':
|
case '{':
|
||||||
case '[':
|
case '[':
|
||||||
$level++;
|
$level++;
|
||||||
// no break
|
//no break
|
||||||
case ',':
|
case ',':
|
||||||
$ends_line_level = $level;
|
$ends_line_level = $level;
|
||||||
break;
|
break;
|
||||||
|
|
1525
package-lock.json
generated
1525
package-lock.json
generated
File diff suppressed because it is too large
Load diff
|
@ -7,11 +7,11 @@
|
||||||
"license": "CC0-1.0",
|
"license": "CC0-1.0",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@eslint/js": "^9.6.0",
|
"@eslint/js": "^9.6.0",
|
||||||
"@stylistic/eslint-plugin": "^3.0.0",
|
"@stylistic/eslint-plugin": "^2.3.0",
|
||||||
"eslint": "^9.7.0",
|
"eslint": "^9.7.0",
|
||||||
"globals": "^15.8.0",
|
"globals": "^15.8.0",
|
||||||
"stylelint": "^16.7.0",
|
"stylelint": "^16.7.0",
|
||||||
"stylelint-config-standard": "^37.0.0"
|
"stylelint-config-standard": "^36.0.1"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"eslint": "eslint public/assets/js/*.js",
|
"eslint": "eslint public/assets/js/*.js",
|
||||||
|
|
|
@ -24,7 +24,7 @@
|
||||||
<env name="CACHE_STORE" value="array"/>
|
<env name="CACHE_STORE" value="array"/>
|
||||||
<!-- <env name="DB_CONNECTION" value="sqlite"/> -->
|
<!-- <env name="DB_CONNECTION" value="sqlite"/> -->
|
||||||
<!-- <env name="DB_DATABASE" value=":memory:"/> -->
|
<!-- <env name="DB_DATABASE" value=":memory:"/> -->
|
||||||
<env name="DB_DATABASE" value="jbuk_dev_testing"/>
|
<env name="DB_DATABASE" value="jbukdev_testing"/>
|
||||||
<env name="MAIL_MAILER" value="array"/>
|
<env name="MAIL_MAILER" value="array"/>
|
||||||
<env name="PULSE_ENABLED" value="false"/>
|
<env name="PULSE_ENABLED" value="false"/>
|
||||||
<env name="QUEUE_CONNECTION" value="sync"/>
|
<env name="QUEUE_CONNECTION" value="sync"/>
|
||||||
|
|
Binary file not shown.
BIN
public/assets/css/code.css.br
Normal file
BIN
public/assets/css/code.css.br
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
public/assets/img/escheresque.png
Normal file
BIN
public/assets/img/escheresque.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 395 B |
BIN
public/assets/img/escheresque@2x.png
Normal file
BIN
public/assets/img/escheresque@2x.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 3.9 KiB |
BIN
public/assets/img/iwc.png
Normal file
BIN
public/assets/img/iwc.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 3.8 KiB |
BIN
public/assets/img/jmb-bw.png
Normal file
BIN
public/assets/img/jmb-bw.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 30 KiB |
BIN
public/assets/img/memoji-orange-bg-small-fs8.png
Normal file
BIN
public/assets/img/memoji-orange-bg-small-fs8.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 33 KiB |
21
public/assets/jonnybarnes-public-key-ecc.asc
Normal file
21
public/assets/jonnybarnes-public-key-ecc.asc
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
-----BEGIN PGP PUBLIC KEY BLOCK-----
|
||||||
|
|
||||||
|
mG8EV0W04xMFK4EEACIDAwSZOjA8NdI6UvbI/Sqw8LfpckfDXMuiowrVgcANjhDr
|
||||||
|
vQtvr0bYm7RnNlbiuwTQHQ064H3pwjJJYC12I5B6q1Is7h4PYzU4/ahtisb03U/Q
|
||||||
|
ThDDuWxDKQq2hcyfrNI02KO0I0pvbm55IEJhcm5lcyA8am9ubnlAam9ubnliYXJu
|
||||||
|
ZXMudWs+iLYEExMKAD4CGwMFCwkIBwMFFQoJCAsFFgMCAQACHgECF4AWIQSEGbWh
|
||||||
|
2ITK9LCvj7MbLHavsWyFmwUCWSgPSgUJA8ON5wAKCRAbLHavsWyFm9hAAX9ymfnT
|
||||||
|
CUQDBqHmSR+YJ7RkNNFRdq4J1ABsvaRnpRynIE60dde1WqX62CvOkQDyY3sBgLJp
|
||||||
|
3KCNjB9VRoHHL3Gk1X78gxntU01wP+oYotA7tJescf34oM4CfzHoz4UdUTPK3Iif
|
||||||
|
BBMTCgAnBQJXRbTjAhsDBQkB4TOABQsJCAcDBRUKCQgLBRYDAgEAAh4BAheAAAoJ
|
||||||
|
EBssdq+xbIWb0qwBfijJLkE/QUH7iAASLDtD3pUGs13TUynrzl2n8NdOnwmJTDdB
|
||||||
|
6eFT5+XxAgmuw+o28wF+MMEqzf+ELqjEyk/DZaZ3Kg9cJQAm3ybc0wFKy/kqQ2HY
|
||||||
|
TaFwEG3dAyfFDddkuaDEuHMEV0W04xIFK4EEACIDAwR0mRtrTq604CFiA8OdQR77
|
||||||
|
AVc8lRrNxFPwo7uJWsIEPBNVTHasC4OCXAvGgm9bPggQUNoOQ4fUCNmAgsVeGpYQ
|
||||||
|
/b67m0ydqjcrHpd0fIRbK5kyWYvYPRsZ6mTgiKosrZIDAQkJiJ4EGBMKACYCGwwW
|
||||||
|
IQSEGbWh2ITK9LCvj7MbLHavsWyFmwUCWSgPZQUJA8OOAgAKCRAbLHavsWyFm1fN
|
||||||
|
AYDMf1p4GegE1FHiUZo4m4Y5iQfbxT9Nmlgaopbmq+BxJRwPMxVzJOvKXo4DiUd0
|
||||||
|
nncBgOJUJ8esy6WGw+lUfkfvRNkhPw9CVt1GifjG4axGHGaDyDQdFdRcIeFyu0Fs
|
||||||
|
7HsLmg==
|
||||||
|
=sdL6
|
||||||
|
-----END PGP PUBLIC KEY BLOCK-----
|
Binary file not shown.
Binary file not shown.
|
@ -1,20 +1,55 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
use Illuminate\Foundation\Application;
|
use Illuminate\Contracts\Http\Kernel;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
|
|
||||||
define('LARAVEL_START', microtime(true));
|
define('LARAVEL_START', microtime(true));
|
||||||
|
|
||||||
// Determine if the application is in maintenance mode...
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Check If The Application Is Under Maintenance
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| If the application is in maintenance / demo mode via the "down" command
|
||||||
|
| we will load this file so that any pre-rendered content can be shown
|
||||||
|
| instead of starting the framework, which could cause an exception.
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
|
||||||
if (file_exists($maintenance = __DIR__.'/../storage/framework/maintenance.php')) {
|
if (file_exists($maintenance = __DIR__.'/../storage/framework/maintenance.php')) {
|
||||||
require $maintenance;
|
require $maintenance;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Register the Composer autoloader...
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Register The Auto Loader
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| Composer provides a convenient, automatically generated class loader for
|
||||||
|
| this application. We just need to utilize it! We'll simply require it
|
||||||
|
| into the script here so we don't need to manually load our classes.
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
|
||||||
require __DIR__.'/../vendor/autoload.php';
|
require __DIR__.'/../vendor/autoload.php';
|
||||||
|
|
||||||
// Bootstrap Laravel and handle the request...
|
/*
|
||||||
/** @var Application $app */
|
|--------------------------------------------------------------------------
|
||||||
|
| Run The Application
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| Once we have the application, we can handle the incoming request using
|
||||||
|
| the application's HTTP kernel. Then, we will send the response back
|
||||||
|
| to this client's browser, allowing them to enjoy our application.
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
|
||||||
$app = require_once __DIR__.'/../bootstrap/app.php';
|
$app = require_once __DIR__.'/../bootstrap/app.php';
|
||||||
|
|
||||||
$app->handleRequest(Request::capture());
|
$kernel = $app->make(Kernel::class);
|
||||||
|
|
||||||
|
$response = $kernel->handle(
|
||||||
|
$request = Request::capture()
|
||||||
|
)->send();
|
||||||
|
|
||||||
|
$kernel->terminate($request, $response);
|
||||||
|
|
|
@ -19,12 +19,8 @@
|
||||||
<link rel="token_endpoint" href="{{ route('indieauth.token') }}">
|
<link rel="token_endpoint" href="{{ route('indieauth.token') }}">
|
||||||
<link rel="micropub" href="{{ route('micropub-endpoint') }}">
|
<link rel="micropub" href="{{ route('micropub-endpoint') }}">
|
||||||
<link rel="webmention" href="{{ config('app.url') }}/webmention">
|
<link rel="webmention" href="{{ config('app.url') }}/webmention">
|
||||||
@if (File::exists(public_path('assets/img/favicon.png')))
|
<link rel="shortcut icon" href="{{ config('app.url') }}/assets/img/memoji-orange-bg-small-fs8.png">
|
||||||
<link rel="icon" href="{{ config('app.url') }}/assets/img/favicon.png">
|
<link rel="pgpkey" href="/assets/jonnybarnes-public-key-ecc.asc">
|
||||||
@endif
|
|
||||||
@if (File::exists(public_path('gpg.key')))
|
|
||||||
<link rel="pgpkey" href="{{ config('app.url')}}/gpg.key">
|
|
||||||
@endif
|
|
||||||
</head>
|
</head>
|
||||||
<body class="grid">
|
<body class="grid">
|
||||||
<header id="site-header">
|
<header id="site-header">
|
||||||
|
@ -72,16 +68,6 @@
|
||||||
<!--scripts go here when needed-->
|
<!--scripts go here when needed-->
|
||||||
@section('scripts')
|
@section('scripts')
|
||||||
<script type="module" src="/assets/js/app.js"></script>
|
<script type="module" src="/assets/js/app.js"></script>
|
||||||
|
|
||||||
<!-- Snow fall -->
|
|
||||||
<script type="module" src="/assets/frontend/is-land.js"></script>
|
|
||||||
<script type="module" src="/assets/frontend/snow-fall.js"></script>
|
|
||||||
<is-land on:media="(prefers-reduced-motion: no-preference)">
|
|
||||||
<snow-fall
|
|
||||||
count="240"
|
|
||||||
style="--snow-fall-color: rebeccapurple; --snow-fall-size: 8px"
|
|
||||||
></snow-fall>
|
|
||||||
</is-land>
|
|
||||||
@show
|
@show
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
@ -13,7 +13,7 @@
|
||||||
@if (array_key_exists('photo', $reply['author']['properties']))
|
@if (array_key_exists('photo', $reply['author']['properties']))
|
||||||
<img src="{{ $reply['author']['properties']['photo'][0] }}" alt="" class="photo u-photo logo">
|
<img src="{{ $reply['author']['properties']['photo'][0] }}" alt="" class="photo u-photo logo">
|
||||||
@endif
|
@endif
|
||||||
<span class="fn">{{ $reply['author']['properties']['name'][0] ?? $reply['author']['properties']['nickname'][0] ?? 'unknown' }}</span>
|
<span class="fn">{{ $reply['author']['properties']['name'][0] }}</span>
|
||||||
</a>
|
</a>
|
||||||
@else
|
@else
|
||||||
Unknown author
|
Unknown author
|
||||||
|
@ -33,7 +33,7 @@
|
||||||
return ($webmention->type === 'like-of');
|
return ($webmention->type === 'like-of');
|
||||||
}) as $like)
|
}) as $like)
|
||||||
<a href="{{ $like['author']['properties']['url'][0] }}">
|
<a href="{{ $like['author']['properties']['url'][0] }}">
|
||||||
<img src="{{ $like['author']['properties']['photo'][0] }}" alt="profile picture of {{ $like['author']['properties']['name'][0] ?? $like['author']['properties']['nickname'][0] ?? 'unknown' }}" class="like-photo">
|
<img src="{{ $like['author']['properties']['photo'][0] }}" alt="profile picture of {{ $like['author']['properties']['name'][0] }}" class="like-photo">
|
||||||
</a>
|
</a>
|
||||||
@endforeach
|
@endforeach
|
||||||
</div>
|
</div>
|
||||||
|
@ -47,7 +47,7 @@
|
||||||
return ($webmention->type == 'repost-of');
|
return ($webmention->type == 'repost-of');
|
||||||
}) as $repost)
|
}) as $repost)
|
||||||
<a href="{{ $repost['source'] }}">
|
<a href="{{ $repost['source'] }}">
|
||||||
<img src="{{ $repost['author']['properties']['photo'][0] }}" alt="{{ $repost['author']['properties']['name'][0] ?? $repost['author']['properties']['nickname'][0] ?? 'unknown' }} reposted this at {{ $repost['published'] }}">
|
<img src="{{ $repost['author']['properties']['photo'][0] }}" alt="{{ $repost['author']['properties']['name'][0] }} reposted this at {{ $repost['published'] }}">
|
||||||
</a>
|
</a>
|
||||||
@endforeach
|
@endforeach
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -64,7 +64,7 @@ Route::domain(config('url.longurl'))->group(function () {
|
||||||
Route::middleware(MyAuthMiddleware::class)->prefix('admin')->group(function () {
|
Route::middleware(MyAuthMiddleware::class)->prefix('admin')->group(function () {
|
||||||
Route::get('/', [HomeController::class, 'welcome']);
|
Route::get('/', [HomeController::class, 'welcome']);
|
||||||
|
|
||||||
// Articles
|
//Articles
|
||||||
Route::prefix('blog')->group(function () {
|
Route::prefix('blog')->group(function () {
|
||||||
Route::get('/', [AdminArticlesController::class, 'index']);
|
Route::get('/', [AdminArticlesController::class, 'index']);
|
||||||
Route::get('/create', [AdminArticlesController::class, 'create']);
|
Route::get('/create', [AdminArticlesController::class, 'create']);
|
||||||
|
|
|
@ -1,41 +1,16 @@
|
||||||
#!/usr/bin/env zsh
|
#!/usr/bin/env zsh
|
||||||
|
|
||||||
if ! (( $+commands[fd] )) &> /dev/null; then
|
if ! type brotli &> /dev/null; then
|
||||||
echo "fd not installed"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
if ! (( $+commands[brotli] )) &> /dev/null; then
|
|
||||||
echo "brotli not installed"
|
echo "brotli not installed"
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if ! (( $+commands[zstd] )) &> /dev/null; then
|
for file in ./public/assets/css/*.css
|
||||||
echo "zstd not installed"
|
do
|
||||||
exit 1
|
brotli --force --quality=11 --output=$file.br -- $file
|
||||||
fi
|
done
|
||||||
|
|
||||||
# Make .br files
|
for file in ./public/assets/js/*.js
|
||||||
fd --extension css --extension js --search-path ./public/assets --type f --exec brotli --force --best --output={}.br {}
|
do
|
||||||
# Make .zst files
|
brotli --force --quality=11 --output=$file.br -- $file
|
||||||
fd --extension css --extension js --search-path ./public/assets --type f --exec zstd --quiet --force --ultra -22 --exclude-compressed {} -o {}.zst
|
|
||||||
|
|
||||||
# Remove files that actually got bigger!
|
|
||||||
fd --extension br --extension zst --search-path ./public/assets --type f --exec sh -c '
|
|
||||||
for file; do
|
|
||||||
src="${file%.br}"
|
|
||||||
src="${src%.zst}"
|
|
||||||
if [ -f "$src" ]; then
|
|
||||||
# Get file sizes using stat with cross-platform compatibility
|
|
||||||
if [ "$(uname)" = "Darwin" ]; then
|
|
||||||
file_size=$(stat -f%z "$file")
|
|
||||||
src_size=$(stat -f%z "$src")
|
|
||||||
else
|
|
||||||
file_size=$(stat -c%s "$file")
|
|
||||||
src_size=$(stat -c%s "$src")
|
|
||||||
fi
|
|
||||||
# Compare sizes and rm compressed file if larger than the source
|
|
||||||
[ "$file_size" -ge "$src_size" ] && rm "$file"
|
|
||||||
fi
|
|
||||||
done
|
done
|
||||||
' _ {}
|
|
||||||
|
|
1
storage/app/.gitignore
vendored
1
storage/app/.gitignore
vendored
|
@ -1,4 +1,3 @@
|
||||||
*
|
*
|
||||||
!private/
|
|
||||||
!public/
|
!public/
|
||||||
!.gitignore
|
!.gitignore
|
||||||
|
|
2
storage/app/private/.gitignore
vendored
2
storage/app/private/.gitignore
vendored
|
@ -1,2 +0,0 @@
|
||||||
*
|
|
||||||
!.gitignore
|
|
|
@ -12,7 +12,7 @@ class ExampleTest extends DuskTestCase
|
||||||
*
|
*
|
||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function test_basic_example()
|
public function testBasicExample()
|
||||||
{
|
{
|
||||||
$this->browse(function (Browser $browser) {
|
$this->browse(function (Browser $browser) {
|
||||||
$browser->visit('/')
|
$browser->visit('/')
|
||||||
|
|
|
@ -32,7 +32,7 @@ abstract class DuskTestCase extends BaseTestCase
|
||||||
{
|
{
|
||||||
$desiredCapabilities = DesiredCapabilities::chrome();
|
$desiredCapabilities = DesiredCapabilities::chrome();
|
||||||
|
|
||||||
$options = new ChromeOptions;
|
$options = new ChromeOptions();
|
||||||
$options->addArguments([
|
$options->addArguments([
|
||||||
'headless',
|
'headless',
|
||||||
'disable-gpu',
|
'disable-gpu',
|
||||||
|
|
|
@ -6,14 +6,13 @@ namespace Tests\Feature\Admin;
|
||||||
|
|
||||||
use App\Models\User;
|
use App\Models\User;
|
||||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||||
use PHPUnit\Framework\Attributes\Test;
|
|
||||||
use Tests\TestCase;
|
use Tests\TestCase;
|
||||||
|
|
||||||
class AdminHomeControllerTest extends TestCase
|
class AdminHomeControllerTest extends TestCase
|
||||||
{
|
{
|
||||||
use RefreshDatabase;
|
use RefreshDatabase;
|
||||||
|
|
||||||
#[Test]
|
/** @test */
|
||||||
public function adminHomepageLoads(): void
|
public function adminHomepageLoads(): void
|
||||||
{
|
{
|
||||||
$user = User::factory()->make();
|
$user = User::factory()->make();
|
||||||
|
|
|
@ -5,26 +5,25 @@ declare(strict_types=1);
|
||||||
namespace Tests\Feature\Admin;
|
namespace Tests\Feature\Admin;
|
||||||
|
|
||||||
use App\Models\User;
|
use App\Models\User;
|
||||||
use PHPUnit\Framework\Attributes\Test;
|
|
||||||
use Tests\TestCase;
|
use Tests\TestCase;
|
||||||
|
|
||||||
class AdminTest extends TestCase
|
class AdminTest extends TestCase
|
||||||
{
|
{
|
||||||
#[Test]
|
/** @test */
|
||||||
public function adminPageRedirectsUnauthorisedUsersToLoginPage(): void
|
public function adminPageRedirectsUnauthorisedUsersToLoginPage(): void
|
||||||
{
|
{
|
||||||
$response = $this->get('/admin');
|
$response = $this->get('/admin');
|
||||||
$response->assertRedirect('/login');
|
$response->assertRedirect('/login');
|
||||||
}
|
}
|
||||||
|
|
||||||
#[Test]
|
/** @test */
|
||||||
public function loginPageLoads(): void
|
public function loginPageLoads(): void
|
||||||
{
|
{
|
||||||
$response = $this->get('/login');
|
$response = $this->get('/login');
|
||||||
$response->assertViewIs('login');
|
$response->assertViewIs('login');
|
||||||
}
|
}
|
||||||
|
|
||||||
#[Test]
|
/** @test */
|
||||||
public function loginAttemptWithBadCredentialsFails(): void
|
public function loginAttemptWithBadCredentialsFails(): void
|
||||||
{
|
{
|
||||||
$response = $this->post('/login', [
|
$response = $this->post('/login', [
|
||||||
|
@ -34,7 +33,7 @@ class AdminTest extends TestCase
|
||||||
$response->assertRedirect('/login');
|
$response->assertRedirect('/login');
|
||||||
}
|
}
|
||||||
|
|
||||||
#[Test]
|
/** @test */
|
||||||
public function loginSucceeds(): void
|
public function loginSucceeds(): void
|
||||||
{
|
{
|
||||||
User::factory([
|
User::factory([
|
||||||
|
@ -50,7 +49,7 @@ class AdminTest extends TestCase
|
||||||
$response->assertRedirect('/admin');
|
$response->assertRedirect('/admin');
|
||||||
}
|
}
|
||||||
|
|
||||||
#[Test]
|
/** @test */
|
||||||
public function whenLoggedInRedirectsToAdminPage(): void
|
public function whenLoggedInRedirectsToAdminPage(): void
|
||||||
{
|
{
|
||||||
$user = User::factory()->create();
|
$user = User::factory()->create();
|
||||||
|
@ -58,14 +57,14 @@ class AdminTest extends TestCase
|
||||||
$response->assertRedirect('/');
|
$response->assertRedirect('/');
|
||||||
}
|
}
|
||||||
|
|
||||||
#[Test]
|
/** @test */
|
||||||
public function loggedOutUsersSimplyRedirected(): void
|
public function loggedOutUsersSimplyRedirected(): void
|
||||||
{
|
{
|
||||||
$response = $this->get('/logout');
|
$response = $this->get('/logout');
|
||||||
$response->assertRedirect('/');
|
$response->assertRedirect('/');
|
||||||
}
|
}
|
||||||
|
|
||||||
#[Test]
|
/** @test */
|
||||||
public function loggedInUsersShownLogoutForm(): void
|
public function loggedInUsersShownLogoutForm(): void
|
||||||
{
|
{
|
||||||
$user = User::factory()->create();
|
$user = User::factory()->create();
|
||||||
|
@ -73,7 +72,7 @@ class AdminTest extends TestCase
|
||||||
$response->assertViewIs('logout');
|
$response->assertViewIs('logout');
|
||||||
}
|
}
|
||||||
|
|
||||||
#[Test]
|
/** @test */
|
||||||
public function loggedInUsersCanLogout(): void
|
public function loggedInUsersCanLogout(): void
|
||||||
{
|
{
|
||||||
$user = User::factory()->create();
|
$user = User::factory()->create();
|
||||||
|
|
|
@ -9,14 +9,13 @@ use App\Models\User;
|
||||||
use Faker\Factory;
|
use Faker\Factory;
|
||||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||||
use Illuminate\Http\UploadedFile;
|
use Illuminate\Http\UploadedFile;
|
||||||
use PHPUnit\Framework\Attributes\Test;
|
|
||||||
use Tests\TestCase;
|
use Tests\TestCase;
|
||||||
|
|
||||||
class ArticlesTest extends TestCase
|
class ArticlesTest extends TestCase
|
||||||
{
|
{
|
||||||
use RefreshDatabase;
|
use RefreshDatabase;
|
||||||
|
|
||||||
#[Test]
|
/** @test */
|
||||||
public function adminArticlesPageLoads(): void
|
public function adminArticlesPageLoads(): void
|
||||||
{
|
{
|
||||||
$user = User::factory()->make();
|
$user = User::factory()->make();
|
||||||
|
@ -26,7 +25,7 @@ class ArticlesTest extends TestCase
|
||||||
$response->assertSeeText('Select article to edit:');
|
$response->assertSeeText('Select article to edit:');
|
||||||
}
|
}
|
||||||
|
|
||||||
#[Test]
|
/** @test */
|
||||||
public function adminCanLoadFormToCreateArticle(): void
|
public function adminCanLoadFormToCreateArticle(): void
|
||||||
{
|
{
|
||||||
$user = User::factory()->make();
|
$user = User::factory()->make();
|
||||||
|
@ -36,7 +35,7 @@ class ArticlesTest extends TestCase
|
||||||
$response->assertSeeText('Title (URL)');
|
$response->assertSeeText('Title (URL)');
|
||||||
}
|
}
|
||||||
|
|
||||||
#[Test]
|
/** @test */
|
||||||
public function admiNCanCreateNewArticle(): void
|
public function admiNCanCreateNewArticle(): void
|
||||||
{
|
{
|
||||||
$user = User::factory()->make();
|
$user = User::factory()->make();
|
||||||
|
@ -49,7 +48,7 @@ class ArticlesTest extends TestCase
|
||||||
$this->assertDatabaseHas('articles', ['title' => 'Test Title']);
|
$this->assertDatabaseHas('articles', ['title' => 'Test Title']);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[Test]
|
/** @test */
|
||||||
public function adminCanCreateNewArticleWithFile(): void
|
public function adminCanCreateNewArticleWithFile(): void
|
||||||
{
|
{
|
||||||
$user = User::factory()->make();
|
$user = User::factory()->make();
|
||||||
|
@ -74,7 +73,7 @@ class ArticlesTest extends TestCase
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[Test]
|
/** @test */
|
||||||
public function articleCanLoadFormToEditArticle(): void
|
public function articleCanLoadFormToEditArticle(): void
|
||||||
{
|
{
|
||||||
$user = User::factory()->make();
|
$user = User::factory()->make();
|
||||||
|
@ -87,7 +86,7 @@ class ArticlesTest extends TestCase
|
||||||
$response->assertSeeText('This is *my* new blog. It uses `Markdown`.');
|
$response->assertSeeText('This is *my* new blog. It uses `Markdown`.');
|
||||||
}
|
}
|
||||||
|
|
||||||
#[Test]
|
/** @test */
|
||||||
public function adminCanEditArticle(): void
|
public function adminCanEditArticle(): void
|
||||||
{
|
{
|
||||||
$user = User::factory()->make();
|
$user = User::factory()->make();
|
||||||
|
@ -105,7 +104,7 @@ class ArticlesTest extends TestCase
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[Test]
|
/** @test */
|
||||||
public function adminCanDeleteArticle(): void
|
public function adminCanDeleteArticle(): void
|
||||||
{
|
{
|
||||||
$user = User::factory()->make();
|
$user = User::factory()->make();
|
||||||
|
|
|
@ -7,14 +7,13 @@ namespace Tests\Feature\Admin;
|
||||||
use App\Models\Bio;
|
use App\Models\Bio;
|
||||||
use App\Models\User;
|
use App\Models\User;
|
||||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||||
use PHPUnit\Framework\Attributes\Test;
|
|
||||||
use Tests\TestCase;
|
use Tests\TestCase;
|
||||||
|
|
||||||
class BioTest extends TestCase
|
class BioTest extends TestCase
|
||||||
{
|
{
|
||||||
use RefreshDatabase;
|
use RefreshDatabase;
|
||||||
|
|
||||||
#[Test]
|
/** @test */
|
||||||
public function adminBiosPageLoads(): void
|
public function adminBiosPageLoads(): void
|
||||||
{
|
{
|
||||||
$user = User::factory()->make();
|
$user = User::factory()->make();
|
||||||
|
@ -24,7 +23,7 @@ class BioTest extends TestCase
|
||||||
$response->assertSeeText('Edit bio');
|
$response->assertSeeText('Edit bio');
|
||||||
}
|
}
|
||||||
|
|
||||||
#[Test]
|
/** @test */
|
||||||
public function adminCanCreateBio(): void
|
public function adminCanCreateBio(): void
|
||||||
{
|
{
|
||||||
$user = User::factory()->make();
|
$user = User::factory()->make();
|
||||||
|
@ -37,7 +36,7 @@ class BioTest extends TestCase
|
||||||
$this->assertDatabaseHas('bios', ['content' => 'Bio content']);
|
$this->assertDatabaseHas('bios', ['content' => 'Bio content']);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[Test]
|
/** @test */
|
||||||
public function adminCanLoadExistingBio(): void
|
public function adminCanLoadExistingBio(): void
|
||||||
{
|
{
|
||||||
$user = User::factory()->make();
|
$user = User::factory()->make();
|
||||||
|
@ -50,7 +49,7 @@ class BioTest extends TestCase
|
||||||
$response->assertSeeText('This is <em>my</em> bio. It uses <strong>HTML</strong>.');
|
$response->assertSeeText('This is <em>my</em> bio. It uses <strong>HTML</strong>.');
|
||||||
}
|
}
|
||||||
|
|
||||||
#[Test]
|
/** @test */
|
||||||
public function adminCanEditBio(): void
|
public function adminCanEditBio(): void
|
||||||
{
|
{
|
||||||
$user = User::factory()->make();
|
$user = User::factory()->make();
|
||||||
|
|
|
@ -7,14 +7,13 @@ namespace Tests\Feature\Admin;
|
||||||
use App\Models\MicropubClient;
|
use App\Models\MicropubClient;
|
||||||
use App\Models\User;
|
use App\Models\User;
|
||||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||||
use PHPUnit\Framework\Attributes\Test;
|
|
||||||
use Tests\TestCase;
|
use Tests\TestCase;
|
||||||
|
|
||||||
class ClientsTest extends TestCase
|
class ClientsTest extends TestCase
|
||||||
{
|
{
|
||||||
use RefreshDatabase;
|
use RefreshDatabase;
|
||||||
|
|
||||||
#[Test]
|
/** @test */
|
||||||
public function clientsPageLoads(): void
|
public function clientsPageLoads(): void
|
||||||
{
|
{
|
||||||
$user = User::factory()->make();
|
$user = User::factory()->make();
|
||||||
|
@ -24,7 +23,7 @@ class ClientsTest extends TestCase
|
||||||
$response->assertSeeText('Clients');
|
$response->assertSeeText('Clients');
|
||||||
}
|
}
|
||||||
|
|
||||||
#[Test]
|
/** @test */
|
||||||
public function adminCanLoadFormToCreateClient(): void
|
public function adminCanLoadFormToCreateClient(): void
|
||||||
{
|
{
|
||||||
$user = User::factory()->make();
|
$user = User::factory()->make();
|
||||||
|
@ -34,7 +33,7 @@ class ClientsTest extends TestCase
|
||||||
$response->assertSeeText('New Client');
|
$response->assertSeeText('New Client');
|
||||||
}
|
}
|
||||||
|
|
||||||
#[Test]
|
/** @test */
|
||||||
public function adminCanCreateNewClient(): void
|
public function adminCanCreateNewClient(): void
|
||||||
{
|
{
|
||||||
$user = User::factory()->make();
|
$user = User::factory()->make();
|
||||||
|
@ -50,7 +49,7 @@ class ClientsTest extends TestCase
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[Test]
|
/** @test */
|
||||||
public function adminCanLoadEditFormForClient(): void
|
public function adminCanLoadEditFormForClient(): void
|
||||||
{
|
{
|
||||||
$user = User::factory()->make();
|
$user = User::factory()->make();
|
||||||
|
@ -63,7 +62,7 @@ class ClientsTest extends TestCase
|
||||||
$response->assertSee('https://jbl5.dev/notes/new');
|
$response->assertSee('https://jbl5.dev/notes/new');
|
||||||
}
|
}
|
||||||
|
|
||||||
#[Test]
|
/** @test */
|
||||||
public function adminCanEditClient(): void
|
public function adminCanEditClient(): void
|
||||||
{
|
{
|
||||||
$user = User::factory()->make();
|
$user = User::factory()->make();
|
||||||
|
@ -81,7 +80,7 @@ class ClientsTest extends TestCase
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[Test]
|
/** @test */
|
||||||
public function adminCanDeleteClient(): void
|
public function adminCanDeleteClient(): void
|
||||||
{
|
{
|
||||||
$user = User::factory()->make();
|
$user = User::factory()->make();
|
||||||
|
|
|
@ -12,7 +12,6 @@ use GuzzleHttp\HandlerStack;
|
||||||
use GuzzleHttp\Psr7\Response;
|
use GuzzleHttp\Psr7\Response;
|
||||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||||
use Illuminate\Http\UploadedFile;
|
use Illuminate\Http\UploadedFile;
|
||||||
use PHPUnit\Framework\Attributes\Test;
|
|
||||||
use Tests\TestCase;
|
use Tests\TestCase;
|
||||||
|
|
||||||
class ContactsTest extends TestCase
|
class ContactsTest extends TestCase
|
||||||
|
@ -28,7 +27,7 @@ class ContactsTest extends TestCase
|
||||||
parent::tearDown();
|
parent::tearDown();
|
||||||
}
|
}
|
||||||
|
|
||||||
#[Test]
|
/** @test */
|
||||||
public function contactIndexPageLoads(): void
|
public function contactIndexPageLoads(): void
|
||||||
{
|
{
|
||||||
$user = User::factory()->make();
|
$user = User::factory()->make();
|
||||||
|
@ -37,7 +36,7 @@ class ContactsTest extends TestCase
|
||||||
$response->assertViewIs('admin.contacts.index');
|
$response->assertViewIs('admin.contacts.index');
|
||||||
}
|
}
|
||||||
|
|
||||||
#[Test]
|
/** @test */
|
||||||
public function contactCreatePageLoads(): void
|
public function contactCreatePageLoads(): void
|
||||||
{
|
{
|
||||||
$user = User::factory()->make();
|
$user = User::factory()->make();
|
||||||
|
@ -46,7 +45,7 @@ class ContactsTest extends TestCase
|
||||||
$response->assertViewIs('admin.contacts.create');
|
$response->assertViewIs('admin.contacts.create');
|
||||||
}
|
}
|
||||||
|
|
||||||
#[Test]
|
/** @test */
|
||||||
public function adminCanCreateNewContact(): void
|
public function adminCanCreateNewContact(): void
|
||||||
{
|
{
|
||||||
$user = User::factory()->make();
|
$user = User::factory()->make();
|
||||||
|
@ -63,7 +62,7 @@ class ContactsTest extends TestCase
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[Test]
|
/** @test */
|
||||||
public function adminCanSeeFormToEditContact(): void
|
public function adminCanSeeFormToEditContact(): void
|
||||||
{
|
{
|
||||||
$user = User::factory()->make();
|
$user = User::factory()->make();
|
||||||
|
@ -73,7 +72,7 @@ class ContactsTest extends TestCase
|
||||||
$response->assertViewIs('admin.contacts.edit');
|
$response->assertViewIs('admin.contacts.edit');
|
||||||
}
|
}
|
||||||
|
|
||||||
#[Test]
|
/** @test */
|
||||||
public function adminCanUpdateContact(): void
|
public function adminCanUpdateContact(): void
|
||||||
{
|
{
|
||||||
$user = User::factory()->make();
|
$user = User::factory()->make();
|
||||||
|
@ -92,7 +91,7 @@ class ContactsTest extends TestCase
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[Test]
|
/** @test */
|
||||||
public function adminCanEditContactAndUploadAvatar(): void
|
public function adminCanEditContactAndUploadAvatar(): void
|
||||||
{
|
{
|
||||||
copy(__DIR__ . '/../../aaron.png', sys_get_temp_dir() . '/tantek.png');
|
copy(__DIR__ . '/../../aaron.png', sys_get_temp_dir() . '/tantek.png');
|
||||||
|
@ -115,7 +114,7 @@ class ContactsTest extends TestCase
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[Test]
|
/** @test */
|
||||||
public function adminCanDeleteContact(): void
|
public function adminCanDeleteContact(): void
|
||||||
{
|
{
|
||||||
$user = User::factory()->make();
|
$user = User::factory()->make();
|
||||||
|
@ -133,7 +132,7 @@ class ContactsTest extends TestCase
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[Test]
|
/** @test */
|
||||||
public function adminCanTriggerRetrievalOfRemoteAvatar(): void
|
public function adminCanTriggerRetrievalOfRemoteAvatar(): void
|
||||||
{
|
{
|
||||||
$html = <<<'HTML'
|
$html = <<<'HTML'
|
||||||
|
@ -162,7 +161,7 @@ class ContactsTest extends TestCase
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[Test]
|
/** @test */
|
||||||
public function gettingRemoteAvatarFailsGracefullyWithRemoteNotFound(): void
|
public function gettingRemoteAvatarFailsGracefullyWithRemoteNotFound(): void
|
||||||
{
|
{
|
||||||
$mock = new MockHandler([
|
$mock = new MockHandler([
|
||||||
|
@ -179,7 +178,7 @@ class ContactsTest extends TestCase
|
||||||
$response->assertRedirect('/admin/contacts/' . $contact->id . '/edit');
|
$response->assertRedirect('/admin/contacts/' . $contact->id . '/edit');
|
||||||
}
|
}
|
||||||
|
|
||||||
#[Test]
|
/** @test */
|
||||||
public function gettingRemoteAvatarFailsGracefullyWithRemoteError(): void
|
public function gettingRemoteAvatarFailsGracefullyWithRemoteError(): void
|
||||||
{
|
{
|
||||||
$html = <<<'HTML'
|
$html = <<<'HTML'
|
||||||
|
@ -202,7 +201,7 @@ class ContactsTest extends TestCase
|
||||||
$response->assertRedirect('/admin/contacts/' . $contact->id . '/edit');
|
$response->assertRedirect('/admin/contacts/' . $contact->id . '/edit');
|
||||||
}
|
}
|
||||||
|
|
||||||
#[Test]
|
/** @test */
|
||||||
public function gettingRemoteAvatarFailsGracefullyForContactWithNoHompage(): void
|
public function gettingRemoteAvatarFailsGracefullyForContactWithNoHompage(): void
|
||||||
{
|
{
|
||||||
$contact = Contact::create([
|
$contact = Contact::create([
|
||||||
|
|
|
@ -9,14 +9,13 @@ use App\Models\Like;
|
||||||
use App\Models\User;
|
use App\Models\User;
|
||||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||||
use Illuminate\Support\Facades\Queue;
|
use Illuminate\Support\Facades\Queue;
|
||||||
use PHPUnit\Framework\Attributes\Test;
|
|
||||||
use Tests\TestCase;
|
use Tests\TestCase;
|
||||||
|
|
||||||
class LikesTest extends TestCase
|
class LikesTest extends TestCase
|
||||||
{
|
{
|
||||||
use RefreshDatabase;
|
use RefreshDatabase;
|
||||||
|
|
||||||
#[Test]
|
/** @test */
|
||||||
public function likesPageLoads(): void
|
public function likesPageLoads(): void
|
||||||
{
|
{
|
||||||
$user = User::factory()->make();
|
$user = User::factory()->make();
|
||||||
|
@ -26,7 +25,7 @@ class LikesTest extends TestCase
|
||||||
$response->assertSeeText('Likes');
|
$response->assertSeeText('Likes');
|
||||||
}
|
}
|
||||||
|
|
||||||
#[Test]
|
/** @test */
|
||||||
public function likeCreateFormLoads(): void
|
public function likeCreateFormLoads(): void
|
||||||
{
|
{
|
||||||
$user = User::factory()->make();
|
$user = User::factory()->make();
|
||||||
|
@ -36,7 +35,7 @@ class LikesTest extends TestCase
|
||||||
$response->assertSeeText('New Like');
|
$response->assertSeeText('New Like');
|
||||||
}
|
}
|
||||||
|
|
||||||
#[Test]
|
/** @test */
|
||||||
public function adminCanCreateLike(): void
|
public function adminCanCreateLike(): void
|
||||||
{
|
{
|
||||||
Queue::fake();
|
Queue::fake();
|
||||||
|
@ -52,7 +51,7 @@ class LikesTest extends TestCase
|
||||||
Queue::assertPushed(ProcessLike::class);
|
Queue::assertPushed(ProcessLike::class);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[Test]
|
/** @test */
|
||||||
public function likeEditFormLoads(): void
|
public function likeEditFormLoads(): void
|
||||||
{
|
{
|
||||||
$user = User::factory()->make();
|
$user = User::factory()->make();
|
||||||
|
@ -63,7 +62,7 @@ class LikesTest extends TestCase
|
||||||
$response->assertSee('Edit Like');
|
$response->assertSee('Edit Like');
|
||||||
}
|
}
|
||||||
|
|
||||||
#[Test]
|
/** @test */
|
||||||
public function adminCanEditLike(): void
|
public function adminCanEditLike(): void
|
||||||
{
|
{
|
||||||
Queue::fake();
|
Queue::fake();
|
||||||
|
@ -81,7 +80,7 @@ class LikesTest extends TestCase
|
||||||
Queue::assertPushed(ProcessLike::class);
|
Queue::assertPushed(ProcessLike::class);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[Test]
|
/** @test */
|
||||||
public function adminCanDeleteLike(): void
|
public function adminCanDeleteLike(): void
|
||||||
{
|
{
|
||||||
$like = Like::factory()->create();
|
$like = Like::factory()->create();
|
||||||
|
|
|
@ -9,14 +9,13 @@ use App\Models\Note;
|
||||||
use App\Models\User;
|
use App\Models\User;
|
||||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||||
use Illuminate\Support\Facades\Queue;
|
use Illuminate\Support\Facades\Queue;
|
||||||
use PHPUnit\Framework\Attributes\Test;
|
|
||||||
use Tests\TestCase;
|
use Tests\TestCase;
|
||||||
|
|
||||||
class NotesTest extends TestCase
|
class NotesTest extends TestCase
|
||||||
{
|
{
|
||||||
use RefreshDatabase;
|
use RefreshDatabase;
|
||||||
|
|
||||||
#[Test]
|
/** @test */
|
||||||
public function notesPageLoads(): void
|
public function notesPageLoads(): void
|
||||||
{
|
{
|
||||||
$user = User::factory()->make();
|
$user = User::factory()->make();
|
||||||
|
@ -25,7 +24,7 @@ class NotesTest extends TestCase
|
||||||
$response->assertViewIs('admin.notes.index');
|
$response->assertViewIs('admin.notes.index');
|
||||||
}
|
}
|
||||||
|
|
||||||
#[Test]
|
/** @test */
|
||||||
public function noteCreatePageLoads(): void
|
public function noteCreatePageLoads(): void
|
||||||
{
|
{
|
||||||
$user = User::factory()->make();
|
$user = User::factory()->make();
|
||||||
|
@ -34,7 +33,7 @@ class NotesTest extends TestCase
|
||||||
$response->assertViewIs('admin.notes.create');
|
$response->assertViewIs('admin.notes.create');
|
||||||
}
|
}
|
||||||
|
|
||||||
#[Test]
|
/** @test */
|
||||||
public function adminCanCreateNewNote(): void
|
public function adminCanCreateNewNote(): void
|
||||||
{
|
{
|
||||||
$user = User::factory()->make();
|
$user = User::factory()->make();
|
||||||
|
@ -48,7 +47,7 @@ class NotesTest extends TestCase
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[Test]
|
/** @test */
|
||||||
public function noteEditFormLoads(): void
|
public function noteEditFormLoads(): void
|
||||||
{
|
{
|
||||||
$user = User::factory()->make();
|
$user = User::factory()->make();
|
||||||
|
@ -58,7 +57,7 @@ class NotesTest extends TestCase
|
||||||
$response->assertViewIs('admin.notes.edit');
|
$response->assertViewIs('admin.notes.edit');
|
||||||
}
|
}
|
||||||
|
|
||||||
#[Test]
|
/** @test */
|
||||||
public function adminCanEditNote(): void
|
public function adminCanEditNote(): void
|
||||||
{
|
{
|
||||||
Queue::fake();
|
Queue::fake();
|
||||||
|
@ -77,7 +76,7 @@ class NotesTest extends TestCase
|
||||||
Queue::assertPushed(SendWebMentions::class);
|
Queue::assertPushed(SendWebMentions::class);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[Test]
|
/** @test */
|
||||||
public function adminCanDeleteNote(): void
|
public function adminCanDeleteNote(): void
|
||||||
{
|
{
|
||||||
$user = User::factory()->make();
|
$user = User::factory()->make();
|
||||||
|
|
|
@ -7,14 +7,13 @@ namespace Tests\Feature\Admin;
|
||||||
use App\Models\Place;
|
use App\Models\Place;
|
||||||
use App\Models\User;
|
use App\Models\User;
|
||||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||||
use PHPUnit\Framework\Attributes\Test;
|
|
||||||
use Tests\TestCase;
|
use Tests\TestCase;
|
||||||
|
|
||||||
class PlacesTest extends TestCase
|
class PlacesTest extends TestCase
|
||||||
{
|
{
|
||||||
use RefreshDatabase;
|
use RefreshDatabase;
|
||||||
|
|
||||||
#[Test]
|
/** @test */
|
||||||
public function placesPageLoads(): void
|
public function placesPageLoads(): void
|
||||||
{
|
{
|
||||||
$user = User::factory()->make();
|
$user = User::factory()->make();
|
||||||
|
@ -23,7 +22,7 @@ class PlacesTest extends TestCase
|
||||||
$response->assertViewIs('admin.places.index');
|
$response->assertViewIs('admin.places.index');
|
||||||
}
|
}
|
||||||
|
|
||||||
#[Test]
|
/** @test */
|
||||||
public function createPlacePageLoads(): void
|
public function createPlacePageLoads(): void
|
||||||
{
|
{
|
||||||
$user = User::factory()->make();
|
$user = User::factory()->make();
|
||||||
|
@ -32,7 +31,7 @@ class PlacesTest extends TestCase
|
||||||
$response->assertViewIs('admin.places.create');
|
$response->assertViewIs('admin.places.create');
|
||||||
}
|
}
|
||||||
|
|
||||||
#[Test]
|
/** @test */
|
||||||
public function adminCanCreateNewPlace(): void
|
public function adminCanCreateNewPlace(): void
|
||||||
{
|
{
|
||||||
$user = User::factory()->make();
|
$user = User::factory()->make();
|
||||||
|
@ -49,7 +48,7 @@ class PlacesTest extends TestCase
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[Test]
|
/** @test */
|
||||||
public function editPlacePageLoads(): void
|
public function editPlacePageLoads(): void
|
||||||
{
|
{
|
||||||
$user = User::factory()->make();
|
$user = User::factory()->make();
|
||||||
|
@ -59,7 +58,7 @@ class PlacesTest extends TestCase
|
||||||
$response->assertViewIs('admin.places.edit');
|
$response->assertViewIs('admin.places.edit');
|
||||||
}
|
}
|
||||||
|
|
||||||
#[Test]
|
/** @test */
|
||||||
public function adminCanUpdatePlace(): void
|
public function adminCanUpdatePlace(): void
|
||||||
{
|
{
|
||||||
$user = User::factory()->make();
|
$user = User::factory()->make();
|
||||||
|
|
|
@ -7,21 +7,20 @@ namespace Tests\Feature;
|
||||||
use App\Models\Article;
|
use App\Models\Article;
|
||||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||||
use Jonnybarnes\IndieWeb\Numbers;
|
use Jonnybarnes\IndieWeb\Numbers;
|
||||||
use PHPUnit\Framework\Attributes\Test;
|
|
||||||
use Tests\TestCase;
|
use Tests\TestCase;
|
||||||
|
|
||||||
class ArticlesTest extends TestCase
|
class ArticlesTest extends TestCase
|
||||||
{
|
{
|
||||||
use RefreshDatabase;
|
use RefreshDatabase;
|
||||||
|
|
||||||
#[Test]
|
/** @test */
|
||||||
public function articlesPageLoads(): void
|
public function articlesPageLoads(): void
|
||||||
{
|
{
|
||||||
$response = $this->get('/blog');
|
$response = $this->get('/blog');
|
||||||
$response->assertViewIs('articles.index');
|
$response->assertViewIs('articles.index');
|
||||||
}
|
}
|
||||||
|
|
||||||
#[Test]
|
/** @test */
|
||||||
public function singleArticlePageLoads()
|
public function singleArticlePageLoads()
|
||||||
{
|
{
|
||||||
$article = Article::factory()->create();
|
$article = Article::factory()->create();
|
||||||
|
@ -29,7 +28,7 @@ class ArticlesTest extends TestCase
|
||||||
$response->assertViewIs('articles.show');
|
$response->assertViewIs('articles.show');
|
||||||
}
|
}
|
||||||
|
|
||||||
#[Test]
|
/** @test */
|
||||||
public function wrongDateInUrlRedirectsToCorrectDate()
|
public function wrongDateInUrlRedirectsToCorrectDate()
|
||||||
{
|
{
|
||||||
$article = Article::factory()->create();
|
$article = Article::factory()->create();
|
||||||
|
@ -37,7 +36,7 @@ class ArticlesTest extends TestCase
|
||||||
$response->assertRedirect('/blog/' . date('Y') . '/' . date('m') . '/' . $article->titleurl);
|
$response->assertRedirect('/blog/' . date('Y') . '/' . date('m') . '/' . $article->titleurl);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[Test]
|
/** @test */
|
||||||
public function oldUrlsWithIdAreRedirected()
|
public function oldUrlsWithIdAreRedirected()
|
||||||
{
|
{
|
||||||
$article = Article::factory()->create();
|
$article = Article::factory()->create();
|
||||||
|
@ -46,21 +45,21 @@ class ArticlesTest extends TestCase
|
||||||
$response->assertRedirect($article->link);
|
$response->assertRedirect($article->link);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[Test]
|
/** @test */
|
||||||
public function unknownSlugGetsNotFoundResponse()
|
public function unknownSlugGetsNotFoundResponse()
|
||||||
{
|
{
|
||||||
$response = $this->get('/blog/' . date('Y') . '/' . date('m') . '/unknown-slug');
|
$response = $this->get('/blog/' . date('Y') . '/' . date('m') . '/unknown-slug');
|
||||||
$response->assertNotFound();
|
$response->assertNotFound();
|
||||||
}
|
}
|
||||||
|
|
||||||
#[Test]
|
/** @test */
|
||||||
public function unknownArticleIdGetsNotFoundResponse()
|
public function unknownArticleIdGetsNotFoundResponse()
|
||||||
{
|
{
|
||||||
$response = $this->get('/blog/s/22');
|
$response = $this->get('/blog/s/22');
|
||||||
$response->assertNotFound();
|
$response->assertNotFound();
|
||||||
}
|
}
|
||||||
|
|
||||||
#[Test]
|
/** @test */
|
||||||
public function someUrlsDoNotParseCorrectly(): void
|
public function someUrlsDoNotParseCorrectly(): void
|
||||||
{
|
{
|
||||||
$response = $this->get('/blog/feed.js');
|
$response = $this->get('/blog/feed.js');
|
||||||
|
|
|
@ -8,7 +8,6 @@ use App\Jobs\ProcessBookmark;
|
||||||
use App\Models\Bookmark;
|
use App\Models\Bookmark;
|
||||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||||
use Illuminate\Support\Facades\Queue;
|
use Illuminate\Support\Facades\Queue;
|
||||||
use PHPUnit\Framework\Attributes\Test;
|
|
||||||
use Tests\TestCase;
|
use Tests\TestCase;
|
||||||
use Tests\TestToken;
|
use Tests\TestToken;
|
||||||
|
|
||||||
|
@ -16,14 +15,14 @@ class BookmarksTest extends TestCase
|
||||||
{
|
{
|
||||||
use RefreshDatabase, TestToken;
|
use RefreshDatabase, TestToken;
|
||||||
|
|
||||||
#[Test]
|
/** @test */
|
||||||
public function bookmarksPageLoadsWithoutError(): void
|
public function bookmarksPageLoadsWithoutError(): void
|
||||||
{
|
{
|
||||||
$response = $this->get('/bookmarks');
|
$response = $this->get('/bookmarks');
|
||||||
$response->assertViewIs('bookmarks.index');
|
$response->assertViewIs('bookmarks.index');
|
||||||
}
|
}
|
||||||
|
|
||||||
#[Test]
|
/** @test */
|
||||||
public function singleBookmarkPageLoadsWithoutError(): void
|
public function singleBookmarkPageLoadsWithoutError(): void
|
||||||
{
|
{
|
||||||
$bookmark = Bookmark::factory()->create();
|
$bookmark = Bookmark::factory()->create();
|
||||||
|
@ -31,7 +30,7 @@ class BookmarksTest extends TestCase
|
||||||
$response->assertViewIs('bookmarks.show');
|
$response->assertViewIs('bookmarks.show');
|
||||||
}
|
}
|
||||||
|
|
||||||
#[Test]
|
/** @test */
|
||||||
public function whenBookmarkIsAddedUsingHttpSyntaxCheckJobToTakeScreenshotIsInvoked(): void
|
public function whenBookmarkIsAddedUsingHttpSyntaxCheckJobToTakeScreenshotIsInvoked(): void
|
||||||
{
|
{
|
||||||
Queue::fake();
|
Queue::fake();
|
||||||
|
@ -49,7 +48,7 @@ class BookmarksTest extends TestCase
|
||||||
$this->assertDatabaseHas('bookmarks', ['url' => 'https://example.org/blog-post']);
|
$this->assertDatabaseHas('bookmarks', ['url' => 'https://example.org/blog-post']);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[Test]
|
/** @test */
|
||||||
public function whenBookmarkIsAddedUsingJsonSyntaxCheckJobToTakeScreenshotIsInvoked(): void
|
public function whenBookmarkIsAddedUsingJsonSyntaxCheckJobToTakeScreenshotIsInvoked(): void
|
||||||
{
|
{
|
||||||
Queue::fake();
|
Queue::fake();
|
||||||
|
@ -69,7 +68,7 @@ class BookmarksTest extends TestCase
|
||||||
$this->assertDatabaseHas('bookmarks', ['url' => 'https://example.org/blog-post']);
|
$this->assertDatabaseHas('bookmarks', ['url' => 'https://example.org/blog-post']);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[Test]
|
/** @test */
|
||||||
public function whenTheBookmarkIsCreatedCheckNecessaryTagsAreAlsoCreated(): void
|
public function whenTheBookmarkIsCreatedCheckNecessaryTagsAreAlsoCreated(): void
|
||||||
{
|
{
|
||||||
Queue::fake();
|
Queue::fake();
|
||||||
|
|
|
@ -6,7 +6,6 @@ namespace Tests\Feature;
|
||||||
|
|
||||||
use App\Models\Contact;
|
use App\Models\Contact;
|
||||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||||
use PHPUnit\Framework\Attributes\Test;
|
|
||||||
use Tests\TestCase;
|
use Tests\TestCase;
|
||||||
|
|
||||||
class ContactsTest extends TestCase
|
class ContactsTest extends TestCase
|
||||||
|
@ -15,8 +14,9 @@ class ContactsTest extends TestCase
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check the `/contacts` page gives a good response.
|
* Check the `/contacts` page gives a good response.
|
||||||
|
*
|
||||||
|
* @test
|
||||||
*/
|
*/
|
||||||
#[Test]
|
|
||||||
public function contactsPageLoadsWithoutError(): void
|
public function contactsPageLoadsWithoutError(): void
|
||||||
{
|
{
|
||||||
$response = $this->get('/contacts');
|
$response = $this->get('/contacts');
|
||||||
|
@ -25,8 +25,9 @@ class ContactsTest extends TestCase
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test an individual contact page with default profile image.
|
* Test an individual contact page with default profile image.
|
||||||
|
*
|
||||||
|
* @test
|
||||||
*/
|
*/
|
||||||
#[Test]
|
|
||||||
public function contactPageShouldFallbackToDefaultProfilePic(): void
|
public function contactPageShouldFallbackToDefaultProfilePic(): void
|
||||||
{
|
{
|
||||||
Contact::factory()->create([
|
Contact::factory()->create([
|
||||||
|
@ -38,8 +39,9 @@ class ContactsTest extends TestCase
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test an individual contact page with a specific profile image.
|
* Test an individual contact page with a specific profile image.
|
||||||
|
*
|
||||||
|
* @test
|
||||||
*/
|
*/
|
||||||
#[Test]
|
|
||||||
public function contactPageShouldUseSpecificProfilePicIfPresent(): void
|
public function contactPageShouldUseSpecificProfilePicIfPresent(): void
|
||||||
{
|
{
|
||||||
Contact::factory()->create([
|
Contact::factory()->create([
|
||||||
|
@ -50,7 +52,7 @@ class ContactsTest extends TestCase
|
||||||
$response->assertViewHas('image', '/assets/profile-images/aaronparecki.com/image');
|
$response->assertViewHas('image', '/assets/profile-images/aaronparecki.com/image');
|
||||||
}
|
}
|
||||||
|
|
||||||
#[Test]
|
/** @test */
|
||||||
public function unknownContactReturnsNotFoundResponse(): void
|
public function unknownContactReturnsNotFoundResponse(): void
|
||||||
{
|
{
|
||||||
$response = $this->get('/contacts/unknown');
|
$response = $this->get('/contacts/unknown');
|
||||||
|
|
|
@ -4,7 +4,6 @@ declare(strict_types=1);
|
||||||
|
|
||||||
namespace Tests\Feature;
|
namespace Tests\Feature;
|
||||||
|
|
||||||
use PHPUnit\Framework\Attributes\Test;
|
|
||||||
use Tests\TestCase;
|
use Tests\TestCase;
|
||||||
use Tests\TestToken;
|
use Tests\TestToken;
|
||||||
|
|
||||||
|
@ -12,7 +11,7 @@ class CorsHeadersTest extends TestCase
|
||||||
{
|
{
|
||||||
use TestToken;
|
use TestToken;
|
||||||
|
|
||||||
#[Test]
|
/** @test */
|
||||||
public function checkCorsHeadersOnMediaEndpoint(): void
|
public function checkCorsHeadersOnMediaEndpoint(): void
|
||||||
{
|
{
|
||||||
$response = $this->call(
|
$response = $this->call(
|
||||||
|
@ -26,7 +25,7 @@ class CorsHeadersTest extends TestCase
|
||||||
$response->assertHeader('Access-Control-Allow-Origin', '*');
|
$response->assertHeader('Access-Control-Allow-Origin', '*');
|
||||||
}
|
}
|
||||||
|
|
||||||
#[Test]
|
/** @test */
|
||||||
public function checkForNoCorsHeaderOnNonMediaEndpointLinks(): void
|
public function checkForNoCorsHeaderOnNonMediaEndpointLinks(): void
|
||||||
{
|
{
|
||||||
$response = $this->get('/blog');
|
$response = $this->get('/blog');
|
||||||
|
|
|
@ -8,7 +8,6 @@ use App\Models\Article;
|
||||||
use App\Models\Note;
|
use App\Models\Note;
|
||||||
use App\Models\Place;
|
use App\Models\Place;
|
||||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||||
use PHPUnit\Framework\Attributes\Test;
|
|
||||||
use Tests\TestCase;
|
use Tests\TestCase;
|
||||||
|
|
||||||
class FeedsTest extends TestCase
|
class FeedsTest extends TestCase
|
||||||
|
@ -17,8 +16,9 @@ class FeedsTest extends TestCase
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test the blog RSS feed.
|
* Test the blog RSS feed.
|
||||||
|
*
|
||||||
|
* @test
|
||||||
*/
|
*/
|
||||||
#[Test]
|
|
||||||
public function blogRssFeedIsPresent(): void
|
public function blogRssFeedIsPresent(): void
|
||||||
{
|
{
|
||||||
Article::factory()->count(3)->create();
|
Article::factory()->count(3)->create();
|
||||||
|
@ -29,8 +29,9 @@ class FeedsTest extends TestCase
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test the notes RSS feed.
|
* Test the notes RSS feed.
|
||||||
|
*
|
||||||
|
* @test
|
||||||
*/
|
*/
|
||||||
#[Test]
|
|
||||||
public function notesRssFeedIsPresent(): void
|
public function notesRssFeedIsPresent(): void
|
||||||
{
|
{
|
||||||
Note::factory()->count(3)->create();
|
Note::factory()->count(3)->create();
|
||||||
|
@ -41,8 +42,9 @@ class FeedsTest extends TestCase
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test the blog RSS feed.
|
* Test the blog RSS feed.
|
||||||
|
*
|
||||||
|
* @test
|
||||||
*/
|
*/
|
||||||
#[Test]
|
|
||||||
public function blogAtomFeedIsPresent(): void
|
public function blogAtomFeedIsPresent(): void
|
||||||
{
|
{
|
||||||
Article::factory()->count(3)->create();
|
Article::factory()->count(3)->create();
|
||||||
|
@ -51,7 +53,7 @@ class FeedsTest extends TestCase
|
||||||
$response->assertOk();
|
$response->assertOk();
|
||||||
}
|
}
|
||||||
|
|
||||||
#[Test]
|
/** @test */
|
||||||
public function blogJf2FeedIsPresent(): void
|
public function blogJf2FeedIsPresent(): void
|
||||||
{
|
{
|
||||||
Article::factory()->count(3)->create();
|
Article::factory()->count(3)->create();
|
||||||
|
@ -75,8 +77,9 @@ class FeedsTest extends TestCase
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test the notes RSS feed.
|
* Test the notes RSS feed.
|
||||||
|
*
|
||||||
|
* @test
|
||||||
*/
|
*/
|
||||||
#[Test]
|
|
||||||
public function notesAtomFeedIsPresent(): void
|
public function notesAtomFeedIsPresent(): void
|
||||||
{
|
{
|
||||||
Note::factory()->count(3)->create();
|
Note::factory()->count(3)->create();
|
||||||
|
@ -87,8 +90,9 @@ class FeedsTest extends TestCase
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test the blog JSON feed.
|
* Test the blog JSON feed.
|
||||||
|
*
|
||||||
|
* @test
|
||||||
*/
|
*/
|
||||||
#[Test]
|
|
||||||
public function blogJsonFeedIsPresent(): void
|
public function blogJsonFeedIsPresent(): void
|
||||||
{
|
{
|
||||||
Article::factory()->count(3)->create();
|
Article::factory()->count(3)->create();
|
||||||
|
@ -99,8 +103,9 @@ class FeedsTest extends TestCase
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test the notes JSON feed.
|
* Test the notes JSON feed.
|
||||||
|
*
|
||||||
|
* @test
|
||||||
*/
|
*/
|
||||||
#[Test]
|
|
||||||
public function notesJsonFeedIsPresent(): void
|
public function notesJsonFeedIsPresent(): void
|
||||||
{
|
{
|
||||||
Note::factory()->count(3)->create();
|
Note::factory()->count(3)->create();
|
||||||
|
@ -109,7 +114,7 @@ class FeedsTest extends TestCase
|
||||||
$response->assertOk();
|
$response->assertOk();
|
||||||
}
|
}
|
||||||
|
|
||||||
#[Test]
|
/** @test */
|
||||||
public function notesJf2FeedIsPresent(): void
|
public function notesJf2FeedIsPresent(): void
|
||||||
{
|
{
|
||||||
Note::factory()->count(3)->create();
|
Note::factory()->count(3)->create();
|
||||||
|
@ -134,8 +139,9 @@ class FeedsTest extends TestCase
|
||||||
/**
|
/**
|
||||||
* Each JSON feed item must have one of `content_text` or `content_html`,
|
* Each JSON feed item must have one of `content_text` or `content_html`,
|
||||||
* and whichever one they have can’t be `null`.
|
* and whichever one they have can’t be `null`.
|
||||||
|
*
|
||||||
|
* @test
|
||||||
*/
|
*/
|
||||||
#[Test]
|
|
||||||
public function jsonFeedsHaveRequiredAttributes(): void
|
public function jsonFeedsHaveRequiredAttributes(): void
|
||||||
{
|
{
|
||||||
Note::factory()->count(3)->create();
|
Note::factory()->count(3)->create();
|
||||||
|
@ -155,7 +161,7 @@ class FeedsTest extends TestCase
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[Test]
|
/** @test */
|
||||||
public function jsonNoteFeedLoadsPlaceDataWithoutLazyLoading(): void
|
public function jsonNoteFeedLoadsPlaceDataWithoutLazyLoading(): void
|
||||||
{
|
{
|
||||||
$place = Place::factory()->create();
|
$place = Place::factory()->create();
|
||||||
|
|
|
@ -7,14 +7,13 @@ use App\Models\Bookmark;
|
||||||
use App\Models\Like;
|
use App\Models\Like;
|
||||||
use App\Models\Note;
|
use App\Models\Note;
|
||||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||||
use PHPUnit\Framework\Attributes\Test;
|
|
||||||
use Tests\TestCase;
|
use Tests\TestCase;
|
||||||
|
|
||||||
class FrontPageTest extends TestCase
|
class FrontPageTest extends TestCase
|
||||||
{
|
{
|
||||||
use RefreshDatabase;
|
use RefreshDatabase;
|
||||||
|
|
||||||
#[Test]
|
/** @test */
|
||||||
public function frontPageLoadsAllContent(): void
|
public function frontPageLoadsAllContent(): void
|
||||||
{
|
{
|
||||||
Note::factory()->create(['note' => 'Note 1']);
|
Note::factory()->create(['note' => 'Note 1']);
|
||||||
|
|
|
@ -3,15 +3,15 @@
|
||||||
namespace Tests\Feature;
|
namespace Tests\Feature;
|
||||||
|
|
||||||
use App\Models\User;
|
use App\Models\User;
|
||||||
use PHPUnit\Framework\Attributes\Test;
|
|
||||||
use Tests\TestCase;
|
use Tests\TestCase;
|
||||||
|
|
||||||
class HorizonTest extends TestCase
|
class HorizonTest extends TestCase
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Horizon has its own test suite, here we just test it has been installed successfully.
|
* Horizon has its own test suite, here we just test it has been installed successfully.
|
||||||
|
*
|
||||||
|
* @test
|
||||||
*/
|
*/
|
||||||
#[Test]
|
|
||||||
public function horizonIsInstalled(): void
|
public function horizonIsInstalled(): void
|
||||||
{
|
{
|
||||||
$user = User::factory()->create([
|
$user = User::factory()->create([
|
||||||
|
|
|
@ -31,8 +31,8 @@ class IndieAuthTest extends TestCase
|
||||||
'authorization_endpoint' => route('indieauth.start'),
|
'authorization_endpoint' => route('indieauth.start'),
|
||||||
'token_endpoint' => route('indieauth.token'),
|
'token_endpoint' => route('indieauth.token'),
|
||||||
'code_challenge_methods_supported' => ['S256'],
|
'code_challenge_methods_supported' => ['S256'],
|
||||||
// 'introspection_endpoint' => 'introspection_endpoint',
|
//'introspection_endpoint' => 'introspection_endpoint',
|
||||||
// 'introspection_endpoint_auth_methods_supported' => ['none'],
|
//'introspection_endpoint_auth_methods_supported' => ['none'],
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -14,7 +14,6 @@ use GuzzleHttp\Psr7\Response;
|
||||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||||
use Illuminate\Support\Facades\Queue;
|
use Illuminate\Support\Facades\Queue;
|
||||||
use Jonnybarnes\WebmentionsParser\Authorship;
|
use Jonnybarnes\WebmentionsParser\Authorship;
|
||||||
use PHPUnit\Framework\Attributes\Test;
|
|
||||||
use Tests\TestCase;
|
use Tests\TestCase;
|
||||||
use Tests\TestToken;
|
use Tests\TestToken;
|
||||||
|
|
||||||
|
@ -23,14 +22,14 @@ class LikesTest extends TestCase
|
||||||
use RefreshDatabase;
|
use RefreshDatabase;
|
||||||
use TestToken;
|
use TestToken;
|
||||||
|
|
||||||
#[Test]
|
/** @test */
|
||||||
public function likesPageHasCorrectView(): void
|
public function likesPageHasCorrectView(): void
|
||||||
{
|
{
|
||||||
$response = $this->get('/likes');
|
$response = $this->get('/likes');
|
||||||
$response->assertViewIs('likes.index');
|
$response->assertViewIs('likes.index');
|
||||||
}
|
}
|
||||||
|
|
||||||
#[Test]
|
/** @test */
|
||||||
public function singleLikePageHasCorrectView(): void
|
public function singleLikePageHasCorrectView(): void
|
||||||
{
|
{
|
||||||
$like = Like::factory()->create();
|
$like = Like::factory()->create();
|
||||||
|
@ -38,7 +37,7 @@ class LikesTest extends TestCase
|
||||||
$response->assertViewIs('likes.show');
|
$response->assertViewIs('likes.show');
|
||||||
}
|
}
|
||||||
|
|
||||||
#[Test]
|
/** @test */
|
||||||
public function checkLikeCreatedFromMicropubApiRequests(): void
|
public function checkLikeCreatedFromMicropubApiRequests(): void
|
||||||
{
|
{
|
||||||
Queue::fake();
|
Queue::fake();
|
||||||
|
@ -58,7 +57,7 @@ class LikesTest extends TestCase
|
||||||
$this->assertDatabaseHas('likes', ['url' => 'https://example.org/blog-post']);
|
$this->assertDatabaseHas('likes', ['url' => 'https://example.org/blog-post']);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[Test]
|
/** @test */
|
||||||
public function checkLikeCreatedFromMicropubWebRequests(): void
|
public function checkLikeCreatedFromMicropubWebRequests(): void
|
||||||
{
|
{
|
||||||
Queue::fake();
|
Queue::fake();
|
||||||
|
@ -76,10 +75,10 @@ class LikesTest extends TestCase
|
||||||
$this->assertDatabaseHas('likes', ['url' => 'https://example.org/blog-post']);
|
$this->assertDatabaseHas('likes', ['url' => 'https://example.org/blog-post']);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[Test]
|
/** @test */
|
||||||
public function likeWithSimpleAuthor(): void
|
public function likeWithSimpleAuthor(): void
|
||||||
{
|
{
|
||||||
$like = new Like;
|
$like = new Like();
|
||||||
$like->url = 'http://example.org/note/id';
|
$like->url = 'http://example.org/note/id';
|
||||||
$like->save();
|
$like->save();
|
||||||
$id = $like->id;
|
$id = $like->id;
|
||||||
|
@ -108,17 +107,17 @@ class LikesTest extends TestCase
|
||||||
$this->app->bind(Client::class, function () use ($client) {
|
$this->app->bind(Client::class, function () use ($client) {
|
||||||
return $client;
|
return $client;
|
||||||
});
|
});
|
||||||
$authorship = new Authorship;
|
$authorship = new Authorship();
|
||||||
|
|
||||||
$job->handle($client, $authorship);
|
$job->handle($client, $authorship);
|
||||||
|
|
||||||
$this->assertEquals('Fred Bloggs', Like::find($id)->author_name);
|
$this->assertEquals('Fred Bloggs', Like::find($id)->author_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[Test]
|
/** @test */
|
||||||
public function likeWithHCard(): void
|
public function likeWithHCard(): void
|
||||||
{
|
{
|
||||||
$like = new Like;
|
$like = new Like();
|
||||||
$like->url = 'http://example.org/note/id';
|
$like->url = 'http://example.org/note/id';
|
||||||
$like->save();
|
$like->save();
|
||||||
$id = $like->id;
|
$id = $like->id;
|
||||||
|
@ -151,17 +150,17 @@ class LikesTest extends TestCase
|
||||||
$this->app->bind(Client::class, function () use ($client) {
|
$this->app->bind(Client::class, function () use ($client) {
|
||||||
return $client;
|
return $client;
|
||||||
});
|
});
|
||||||
$authorship = new Authorship;
|
$authorship = new Authorship();
|
||||||
|
|
||||||
$job->handle($client, $authorship);
|
$job->handle($client, $authorship);
|
||||||
|
|
||||||
$this->assertEquals('Fred Bloggs', Like::find($id)->author_name);
|
$this->assertEquals('Fred Bloggs', Like::find($id)->author_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[Test]
|
/** @test */
|
||||||
public function likeWithoutMicroformats(): void
|
public function likeWithoutMicroformats(): void
|
||||||
{
|
{
|
||||||
$like = new Like;
|
$like = new Like();
|
||||||
$like->url = 'http://example.org/note/id';
|
$like->url = 'http://example.org/note/id';
|
||||||
$like->save();
|
$like->save();
|
||||||
$id = $like->id;
|
$id = $like->id;
|
||||||
|
@ -187,17 +186,17 @@ class LikesTest extends TestCase
|
||||||
$this->app->bind(Client::class, function () use ($client) {
|
$this->app->bind(Client::class, function () use ($client) {
|
||||||
return $client;
|
return $client;
|
||||||
});
|
});
|
||||||
$authorship = new Authorship;
|
$authorship = new Authorship();
|
||||||
|
|
||||||
$job->handle($client, $authorship);
|
$job->handle($client, $authorship);
|
||||||
|
|
||||||
$this->assertNull(Like::find($id)->author_name);
|
$this->assertNull(Like::find($id)->author_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[Test]
|
/** @test */
|
||||||
public function likeThatIsATweet(): void
|
public function likeThatIsATweet(): void
|
||||||
{
|
{
|
||||||
$like = new Like;
|
$like = new Like();
|
||||||
$like->url = 'https://twitter.com/jonnybarnes/status/1050823255123251200';
|
$like->url = 'https://twitter.com/jonnybarnes/status/1050823255123251200';
|
||||||
$like->save();
|
$like->save();
|
||||||
$id = $like->id;
|
$id = $like->id;
|
||||||
|
@ -220,23 +219,24 @@ class LikesTest extends TestCase
|
||||||
'author_url' => 'https://twitter.com/jonnybarnes',
|
'author_url' => 'https://twitter.com/jonnybarnes',
|
||||||
'html' => '<div>HTML of the tweet embed</div>',
|
'html' => '<div>HTML of the tweet embed</div>',
|
||||||
];
|
];
|
||||||
$codebirdMock = $this->createPartialMock(Codebird::class, ['__call']);
|
$codebirdMock = $this->getMockBuilder(Codebird::class)
|
||||||
$codebirdMock->method('__call')
|
->addMethods(['statuses_oembed'])
|
||||||
->with('statuses_oembed', $this->anything())
|
->getMock();
|
||||||
|
$codebirdMock->method('statuses_oembed')
|
||||||
->willReturn($info);
|
->willReturn($info);
|
||||||
$this->app->instance(Codebird::class, $codebirdMock);
|
$this->app->instance(Codebird::class, $codebirdMock);
|
||||||
|
|
||||||
$authorship = new Authorship;
|
$authorship = new Authorship();
|
||||||
|
|
||||||
$job->handle($client, $authorship);
|
$job->handle($client, $authorship);
|
||||||
|
|
||||||
$this->assertEquals('Jonny Barnes', Like::find($id)->author_name);
|
$this->assertEquals('Jonny Barnes', Like::find($id)->author_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[Test]
|
/** @test */
|
||||||
public function noErrorForFailureToPosseWithBridgy(): void
|
public function noErrorForFailureToPosseWithBridgy(): void
|
||||||
{
|
{
|
||||||
$like = new Like;
|
$like = new Like();
|
||||||
$like->url = 'https://twitter.com/jonnybarnes/status/1050823255123251200';
|
$like->url = 'https://twitter.com/jonnybarnes/status/1050823255123251200';
|
||||||
$like->save();
|
$like->save();
|
||||||
$id = $like->id;
|
$id = $like->id;
|
||||||
|
@ -257,20 +257,21 @@ class LikesTest extends TestCase
|
||||||
'author_url' => 'https://twitter.com/jonnybarnes',
|
'author_url' => 'https://twitter.com/jonnybarnes',
|
||||||
'html' => '<div>HTML of the tweet embed</div>',
|
'html' => '<div>HTML of the tweet embed</div>',
|
||||||
];
|
];
|
||||||
$codebirdMock = $this->createPartialMock(Codebird::class, ['__call']);
|
$codebirdMock = $this->getMockBuilder(Codebird::class)
|
||||||
$codebirdMock->method('__call')
|
->addMethods(['statuses_oembed'])
|
||||||
->with('statuses_oembed', $this->anything())
|
->getMock();
|
||||||
|
$codebirdMock->method('statuses_oembed')
|
||||||
->willReturn($info);
|
->willReturn($info);
|
||||||
$this->app->instance(Codebird::class, $codebirdMock);
|
$this->app->instance(Codebird::class, $codebirdMock);
|
||||||
|
|
||||||
$authorship = new Authorship;
|
$authorship = new Authorship();
|
||||||
|
|
||||||
$job->handle($client, $authorship);
|
$job->handle($client, $authorship);
|
||||||
|
|
||||||
$this->assertEquals('Jonny Barnes', Like::find($id)->author_name);
|
$this->assertEquals('Jonny Barnes', Like::find($id)->author_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[Test]
|
/** @test */
|
||||||
public function unknownLikeGivesNotFoundResponse(): void
|
public function unknownLikeGivesNotFoundResponse(): void
|
||||||
{
|
{
|
||||||
$response = $this->get('/likes/202');
|
$response = $this->get('/likes/202');
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue