[COMPONENT][Link] Fix some minor issues with empty headed links, typo in event handler's name, and refactor entity to inside component

This commit is contained in:
Diogo Peralta Cordeiro 2021-12-03 00:44:45 +00:00
parent 56d653d980
commit 70ed04a7db
Signed by: diogo
GPG Key ID: 18D2D35001FBFAB0
5 changed files with 30 additions and 33 deletions

View File

@ -1,5 +1,7 @@
<?php <?php
declare(strict_types = 1);
// {{{ License // {{{ License
// This file is part of GNU social - https://www.gnu.org/software/social // This file is part of GNU social - https://www.gnu.org/software/social
// //
@ -17,7 +19,7 @@
// along with GNU social. If not, see <http://www.gnu.org/licenses/>. // along with GNU social. If not, see <http://www.gnu.org/licenses/>.
// }}} // }}}
namespace App\Entity; namespace Component\Link\Entity;
use App\Core\DB\DB; use App\Core\DB\DB;
use App\Core\Entity; use App\Core\Entity;
@ -29,9 +31,8 @@ use App\Util\Common;
use App\Util\Exception\DuplicateFoundException; use App\Util\Exception\DuplicateFoundException;
use App\Util\Exception\NotFoundException; use App\Util\Exception\NotFoundException;
use DateTimeInterface; use DateTimeInterface;
use Exception;
use InvalidArgumentException; use InvalidArgumentException;
use Symfony\Component\HttpClient\Exception\ClientException as HTTPClientException;
use Symfony\Component\HttpClient\Exception\TransportException;
/** /**
* Entity for representing a Link * Entity for representing a Link
@ -100,13 +101,13 @@ class Link extends Entity
public function getMimetypeMajor(): ?string public function getMimetypeMajor(): ?string
{ {
$mime = $this->getMimetype(); $mime = $this->getMimetype();
return is_null($mime) ? $mime : GSFile::mimetypeMajor($mime); return \is_null($mime) ? $mime : GSFile::mimetypeMajor($mime);
} }
public function getMimetypeMinor(): ?string public function getMimetypeMinor(): ?string
{ {
$mime = $this->getMimetype(); $mime = $this->getMimetype();
return is_null($mime) ? $mime : GSFile::mimetypeMinor($mime); return \is_null($mime) ? $mime : GSFile::mimetypeMinor($mime);
} }
public function setModified(DateTimeInterface $modified): self public function setModified(DateTimeInterface $modified): self
@ -123,24 +124,21 @@ class Link extends Entity
// @codeCoverageIgnoreEnd // @codeCoverageIgnoreEnd
// }}} Autocode // }}} Autocode
const URLHASH_ALGO = 'sha256'; public const URLHASH_ALGO = 'sha256';
/** /**
* Create an attachment for the given URL, fetching the mimetype * Create an attachment for the given URL, fetching the mimetype
* *
* @param string $url
*
*@throws InvalidArgumentException
* @throws DuplicateFoundException * @throws DuplicateFoundException
*@throws InvalidArgumentException
* *
* @return Link * @return Link
*
*/ */
public static function getOrCreate(string $url): self public static function getOrCreate(string $url): self
{ {
if (Common::isValidHttpUrl($url)) { if (Common::isValidHttpUrl($url)) {
// If the URL is a local one, do not create a Link to it // If the URL is a local one, do not create a Link to it
if (parse_url($url, PHP_URL_HOST) === $_ENV['SOCIAL_DOMAIN']) { if (parse_url($url, \PHP_URL_HOST) === $_ENV['SOCIAL_DOMAIN']) {
Log::warning("It was attempted to create a Link to a local location {$url}."); Log::warning("It was attempted to create a Link to a local location {$url}.");
// Forbidden // Forbidden
throw new InvalidArgumentException(message: "A Link can't point to a local location ({$url}), it must be a remote one", code: 400); throw new InvalidArgumentException(message: "A Link can't point to a local location ({$url}), it must be a remote one", code: 400);
@ -150,7 +148,7 @@ class Link extends Entity
// This must come before getInfo given that Symfony HTTPClient is lazy (thus forcing curl exec) // This must come before getInfo given that Symfony HTTPClient is lazy (thus forcing curl exec)
$headers = $head->getHeaders(); $headers = $head->getHeaders();
// @codeCoverageIgnoreStart // @codeCoverageIgnoreStart
} catch (HTTPClientException | TransportException $e) { } catch (Exception $e) {
throw new InvalidArgumentException(previous: $e); throw new InvalidArgumentException(previous: $e);
// @codeCoverageIgnoreEnd // @codeCoverageIgnoreEnd
} }
@ -159,11 +157,11 @@ class Link extends Entity
try { try {
return DB::findOneBy('link', ['url_hash' => $url_hash]); return DB::findOneBy('link', ['url_hash' => $url_hash]);
} catch (NotFoundException) { } catch (NotFoundException) {
$headers = array_change_key_case($headers, CASE_LOWER); $headers = array_change_key_case($headers, \CASE_LOWER);
$link = self::create([ $link = self::create([
'url' => $url, 'url' => $url,
'url_hash' => $url_hash, 'url_hash' => $url_hash,
'mimetype' => $headers['content-type'][0], 'mimetype' => $headers['content-type'][0] ?? null,
]); ]);
DB::persist($link); DB::persist($link);
Event::handle('LinkStoredNew', [&$link]); Event::handle('LinkStoredNew', [&$link]);

View File

@ -26,7 +26,6 @@ namespace Component\Link;
use App\Core\DB\DB; use App\Core\DB\DB;
use App\Core\Event; use App\Core\Event;
use App\Core\Modules\Component; use App\Core\Modules\Component;
use App\Entity;
use App\Entity\Note; use App\Entity\Note;
use App\Entity\NoteToLink; use App\Entity\NoteToLink;
use App\Util\Common; use App\Util\Common;
@ -56,7 +55,7 @@ class Link extends Component
return Event::next; return Event::next;
} }
public function onRenderPlainTextContent(string &$text): bool public function onRenderPlainTextNoteContent(string &$text): bool
{ {
$text = $this->replaceURLs($text); $text = $this->replaceURLs($text);
return Event::next; return Event::next;

View File

@ -42,17 +42,11 @@ use App\Core\DB\DB;
use App\Core\Event; use App\Core\Event;
use App\Core\GSFile; use App\Core\GSFile;
use App\Core\HTTPClient; use App\Core\HTTPClient;
use Symfony\Contracts\HttpClient\Exception\ClientExceptionInterface;
use Symfony\Contracts\HttpClient\Exception\RedirectionExceptionInterface;
use Symfony\Contracts\HttpClient\Exception\ServerExceptionInterface;
use Symfony\Contracts\HttpClient\Exception\TransportExceptionInterface;
use function App\Core\I18n\_m; use function App\Core\I18n\_m;
use App\Core\Log; use App\Core\Log;
use App\Core\Modules\Plugin; use App\Core\Modules\Plugin;
use App\Core\Router\RouteLoader; use App\Core\Router\RouteLoader;
use App\Core\Router\Router; use App\Core\Router\Router;
use Component\Attachment\Entity\Attachment;
use App\Entity\Link;
use App\Entity\Note; use App\Entity\Note;
use App\Util\Common; use App\Util\Common;
use App\Util\Exception\ClientException; use App\Util\Exception\ClientException;
@ -61,9 +55,15 @@ use App\Util\Exception\NotFoundException;
use App\Util\Exception\ServerException; use App\Util\Exception\ServerException;
use App\Util\Formatting; use App\Util\Formatting;
use App\Util\TemporaryFile; use App\Util\TemporaryFile;
use Component\Attachment\Entity\Attachment;
use Component\Link\Entity\Link;
use Embed\Embed as LibEmbed; use Embed\Embed as LibEmbed;
use Exception; use Exception;
use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Request;
use Symfony\Contracts\HttpClient\Exception\ClientExceptionInterface;
use Symfony\Contracts\HttpClient\Exception\RedirectionExceptionInterface;
use Symfony\Contracts\HttpClient\Exception\ServerExceptionInterface;
use Symfony\Contracts\HttpClient\Exception\TransportExceptionInterface;
/** /**
* Base class for the Embed plugin that does most of the heavy lifting to get * Base class for the Embed plugin that does most of the heavy lifting to get
@ -190,7 +190,7 @@ class Embed extends Plugin
{ {
// Only handle text mime // Only handle text mime
$mimetype = $link->getMimetype(); $mimetype = $link->getMimetype();
if (!(Formatting::startsWith($mimetype, 'text/html') || Formatting::startsWith($mimetype, 'application/xhtml+xml'))) { if (\is_null($mimetype) || !(Formatting::startsWith($mimetype, 'text/html') || Formatting::startsWith($mimetype, 'application/xhtml+xml'))) {
return Event::next; return Event::next;
} }
@ -291,9 +291,9 @@ class Embed extends Plugin
$metadata['author_name'] = $info->authorName; $metadata['author_name'] = $info->authorName;
$root_url = parse_url($url); $root_url = parse_url($url);
$root_url = "{$root_url['scheme']}://{$root_url['host']}"; $root_url = "{$root_url['scheme']}://{$root_url['host']}";
$metadata['author_url'] = $info->authorUrl ? (string)$info->authorUrl : $root_url; $metadata['author_url'] = $info->authorUrl ? (string) $info->authorUrl : $root_url;
$metadata['provider_name'] = $info->providerName; $metadata['provider_name'] = $info->providerName;
$metadata['provider_url'] = (string)$info->providerUrl ?? $metadata['author_name']; $metadata['provider_url'] = (string) $info->providerUrl ?? $metadata['author_name'];
if (!\is_null($info->image)) { if (!\is_null($info->image)) {
$thumbnail_url = (string) $info->image; $thumbnail_url = (string) $info->image;
@ -352,7 +352,7 @@ class Embed extends Plugin
} }
// Validate if the URL really does point to a remote image // Validate if the URL really does point to a remote image
$head = HTTPClient::head($url); $head = HTTPClient::head($url);
try { try {
$headers = $head->getHeaders(); $headers = $head->getHeaders();
} catch (ClientExceptionInterface|RedirectionExceptionInterface|ServerExceptionInterface|TransportExceptionInterface $e) { } catch (ClientExceptionInterface|RedirectionExceptionInterface|ServerExceptionInterface|TransportExceptionInterface $e) {
@ -368,7 +368,7 @@ class Embed extends Plugin
// Does it respect the file quota? // Does it respect the file quota?
$file_size = $headers['content-length'][0] ?? null; $file_size = $headers['content-length'][0] ?? null;
$max_size = Common::config('attachments', 'file_quota'); $max_size = Common::config('attachments', 'file_quota');
if (is_null($file_size) || $file_size > $max_size) { if (\is_null($file_size) || $file_size > $max_size) {
Log::debug("Went to download remote thumbnail of size {$file_size} but the upload limit is {$max_size} so we aborted in Embed->downloadThumbnail."); Log::debug("Went to download remote thumbnail of size {$file_size} but the upload limit is {$max_size} so we aborted in Embed->downloadThumbnail.");
return false; return false;
} }

View File

@ -27,16 +27,16 @@ use App\Core\HTTPClient;
use function App\Core\I18n\_m; use function App\Core\I18n\_m;
use App\Core\Log; use App\Core\Log;
use App\Core\Modules\Plugin; use App\Core\Modules\Plugin;
use Component\Attachment\Entity\AttachmentThumbnail;
use Component\Attachment\Entity\AttachmentToLink;
use Component\Attachment\Entity\AttachmentToNote;
use App\Entity\Link;
use App\Entity\Note; use App\Entity\Note;
use App\Util\Common; use App\Util\Common;
use App\Util\Exception\DuplicateFoundException; use App\Util\Exception\DuplicateFoundException;
use App\Util\Exception\ServerException; use App\Util\Exception\ServerException;
use App\Util\Exception\TemporaryFileException; use App\Util\Exception\TemporaryFileException;
use App\Util\TemporaryFile; use App\Util\TemporaryFile;
use Component\Attachment\Entity\AttachmentThumbnail;
use Component\Attachment\Entity\AttachmentToLink;
use Component\Attachment\Entity\AttachmentToNote;
use Component\Link\Entity\Link;
/** /**
* The StoreRemoteMedia plugin downloads remotely attached files to local server. * The StoreRemoteMedia plugin downloads remotely attached files to local server.
@ -139,7 +139,7 @@ class StoreRemoteMedia extends Plugin
// Retrieve media // Retrieve media
$get_response = HTTPClient::get($link->getUrl()); $get_response = HTTPClient::get($link->getUrl());
$media = $get_response->getContent(); $media = $get_response->getContent();
$mimetype = $get_response->getHeaders()['content-type'][0]; $mimetype = $get_response->getHeaders()['content-type'][0] ?? null;
unset($get_response); unset($get_response);
// Ensure we still want to handle it // Ensure we still want to handle it

View File

@ -21,8 +21,8 @@ declare(strict_types = 1);
namespace App\Tests\Entity; namespace App\Tests\Entity;
use App\Entity\Link;
use App\Util\GNUsocialTestCase; use App\Util\GNUsocialTestCase;
use Component\Link\Entity\Link;
use InvalidArgumentException; use InvalidArgumentException;
use Jchook\AssertThrows\AssertThrows; use Jchook\AssertThrows\AssertThrows;