MTM Laravel v12 #31

Merged
jonny merged 4 commits from develop into main 2025-04-04 18:10:47 +02:00
101 changed files with 2134 additions and 2938 deletions

View file

@ -12,7 +12,9 @@ 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
@ -39,7 +41,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
@ -49,6 +51,7 @@ 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

View file

@ -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);

View file

@ -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
} }

View file

@ -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());

View file

@ -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');

View file

@ -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'],
]); ]);
} }

View file

@ -191,7 +191,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 +203,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 +214,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',

View file

@ -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));

View file

@ -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);

View file

@ -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',

View file

@ -32,18 +32,21 @@ class ProcessMedia implements ShouldQueue
*/ */
public function handle(ImageManager $manager): void public function handle(ImageManager $manager): void
{ {
// Load file
$file = Storage::disk('local')->get('media/' . $this->filename);
// Open file // Open file
try { try {
$image = $manager->read(storage_path('app/media/') . $this->filename); $image = $manager->read($file);
} catch (DecoderException) { } catch (DecoderException) {
// not an image; delete file and end job // not an image; delete file and end job
unlink(storage_path('app/media/') . $this->filename); Storage::disk('local')->delete('media/' . $this->filename);
return; return;
} }
// Save the file publicly // Save the file publicly
Storage::disk('local')->copy('media/' . $this->filename, 'public/media/' . $this->filename); Storage::disk('public')->put('media/' . $this->filename, $file);
// Create smaller versions if necessary // Create smaller versions if necessary
if ($image->width() > 1000) { if ($image->width() > 1000) {
@ -54,13 +57,13 @@ class ProcessMedia implements ShouldQueue
$basename = trim(implode('.', $filenameParts), '.'); $basename = trim(implode('.', $filenameParts), '.');
$medium = $image->resize(width: 1000); $medium = $image->resize(width: 1000);
Storage::disk('local')->put('public/media/' . $basename . '-medium.' . $extension, (string) $medium->encode()); Storage::disk('public')->put('media/' . $basename . '-medium.' . $extension, (string) $medium->encode());
$small = $image->resize(width: 500); $small = $image->resize(width: 500);
Storage::disk('local')->put('public/media/' . $basename . '-small.' . $extension, (string) $small->encode()); Storage::disk('public')->put('media/' . $basename . '-small.' . $extension, (string) $small->encode());
} }
// Now we can delete the locally saved image // Now we can delete the locally saved image
unlink(storage_path('app/media/') . $this->filename); Storage::disk('local')->delete('media/' . $this->filename);
} }
} }

View file

@ -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'

View file

@ -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);

View file

@ -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;

View file

@ -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]);
} }

View file

@ -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,7 +135,7 @@ 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;
} }

View file

@ -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,7 +61,7 @@ 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')) {
@ -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;
} }
} }

View file

@ -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')) {

View file

@ -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') {

View file

@ -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\.\-]+)/',
@ -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) {

Some files were not shown because too many files have changed in this diff Show more