[TOOLS] Run CS-fixer on all files

This commit is contained in:
Hugo Sales 2021-12-26 09:48:16 +00:00 committed by Diogo Peralta Cordeiro
parent 5e42723624
commit ec28f23025
Signed by: diogo
GPG Key ID: 18D2D35001FBFAB0
66 changed files with 494 additions and 579 deletions

View File

@ -30,12 +30,12 @@ use App\Core\GSFile;
use function App\Core\I18n\_m;
use App\Core\Log;
use App\Core\Router\Router;
use Component\Attachment\Entity\AttachmentThumbnail;
use App\Util\Common;
use App\Util\Exception\ClientException;
use App\Util\Exception\NoSuchFileException;
use App\Util\Exception\NotFoundException;
use App\Util\Exception\ServerException;
use Component\Attachment\Entity\AttachmentThumbnail;
use Symfony\Component\HttpFoundation\HeaderUtils;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;

View File

@ -1,5 +1,7 @@
<?php
declare(strict_types = 1);
// {{{ License
// This file is part of GNU social - https://www.gnu.org/software/social
//
@ -39,7 +41,7 @@ class ActorToAttachment extends Entity
// @codeCoverageIgnoreStart
private int $attachment_id;
private int $actor_id;
private \DateTimeInterface $modified;
private DateTimeInterface $modified;
public function setAttachmentId(int $attachment_id): self
{
@ -77,10 +79,6 @@ class ActorToAttachment extends Entity
// @codeCoverageIgnoreEnd
// }}} Autocode
/**
* @param int $attachment_id
* @return mixed
*/
public static function removeWhereAttachmentId(int $attachment_id): mixed
{
return DB::dql(
@ -92,11 +90,6 @@ class ActorToAttachment extends Entity
);
}
/**
* @param int $actor_id
* @param int $attachment_id
* @return mixed
*/
public static function removeWhere(int $attachment_id, int $actor_id): mixed
{
return DB::dql(
@ -109,10 +102,6 @@ class ActorToAttachment extends Entity
);
}
/**
* @param int $actor_id
* @return mixed
*/
public static function removeWhereActorId(int $actor_id): mixed
{
return DB::dql(

View File

@ -1,5 +1,7 @@
<?php
declare(strict_types = 1);
// {{{ License
// This file is part of GNU social - https://www.gnu.org/software/social
@ -26,10 +28,10 @@ use App\Core\DB\DB;
use App\Core\Entity;
use App\Core\Event;
use App\Core\GSFile;
use App\Entity\Note;
use function App\Core\I18n\_m;
use App\Core\Log;
use App\Core\Router\Router;
use App\Entity\Note;
use App\Util\Common;
use App\Util\Exception\ClientException;
use App\Util\Exception\DuplicateFoundException;
@ -77,17 +79,11 @@ class Attachment extends Entity
return $this->id;
}
/**
* @return int
*/
public function getLives(): int
{
return $this->lives;
}
/**
* @param int $lives
*/
public function setLives(int $lives): void
{
$this->lives = $lives;
@ -176,39 +172,31 @@ class Attachment extends Entity
public function getMimetypeMajor(): ?string
{
$mime = $this->getMimetype();
return is_null($mime) ? $mime : GSFile::mimetypeMajor($mime);
return \is_null($mime) ? $mime : GSFile::mimetypeMajor($mime);
}
public function getMimetypeMinor(): ?string
{
$mime = $this->getMimetype();
return is_null($mime) ? $mime : GSFile::mimetypeMinor($mime);
return \is_null($mime) ? $mime : GSFile::mimetypeMinor($mime);
}
/**
* @return int
*/
public function livesIncrementAndGet(): int
{
++$this->lives;
return $this->lives;
}
/**
* @return int
*/
public function livesDecrementAndGet(): int
{
--$this->lives;
return $this->lives;
}
const FILEHASH_ALGO = 'sha256';
public const FILEHASH_ALGO = 'sha256';
/**
* Delete a file if safe, removes dependencies, cleanups and flushes
*
* @return bool
*/
public function kill(): bool
{
@ -223,7 +211,7 @@ class Attachment extends Entity
*/
public function deleteStorage(): bool
{
if (!is_null($filepath = $this->getPath())) {
if (!\is_null($filepath = $this->getPath())) {
if (file_exists($filepath)) {
if (@unlink($filepath) === false) {
// @codeCoverageIgnoreStart
@ -248,6 +236,7 @@ class Attachment extends Entity
/**
* Attachment delete always removes dependencies, cleanups and flushes
*
* @see kill() It's more likely that you want to use that rather than call delete directly
*/
protected function delete(): bool
@ -261,7 +250,7 @@ class Attachment extends Entity
// Collect files starting with the one associated with this attachment
$files = [];
if (!is_null($filepath = $this->getPath())) {
if (!\is_null($filepath = $this->getPath())) {
$files[] = $filepath;
}
@ -306,25 +295,21 @@ class Attachment extends Entity
/**
* TODO: Maybe this isn't the best way of handling titles
*
* @param null|Note $note
*
* @throws DuplicateFoundException
* @throws NotFoundException
* @throws ServerException
*
* @return string
*/
public function getBestTitle(?Note $note = null): string
{
// If we have a note, then the best title is the title itself
if (!is_null(($note))) {
if (!\is_null(($note))) {
$title = Cache::get('attachment-title-' . $this->getId() . '-' . $note->getId(), function () use ($note) {
try {
$attachment_to_note = DB::findOneBy('attachment_to_note', [
'attachment_id' => $this->getId(),
'note_id' => $note->getId(),
]);
if (!is_null($attachment_to_note->getTitle())) {
if (!\is_null($attachment_to_note->getTitle())) {
return $attachment_to_note->getTitle();
}
} catch (NotFoundException) {
@ -332,14 +317,14 @@ class Attachment extends Entity
Event::handle('AttachmentGetBestTitle', [$this, $note, &$title]);
return $title;
}
return null;
});
if ($title != null) {
return $title;
}
}
// Else
if (!is_null($filename = $this->getFilename())) {
if (!\is_null($filename = $this->getFilename())) {
// A filename would do just as well
return $filename;
} else {
@ -359,7 +344,7 @@ class Attachment extends Entity
public function getPath()
{
$filename = $this->getFilename();
return is_null($filename) ? null : Common::config('attachments', 'dir') . DIRECTORY_SEPARATOR . $filename;
return \is_null($filename) ? null : Common::config('attachments', 'dir') . \DIRECTORY_SEPARATOR . $filename;
}
public function getUrl(int $type = Router::ABSOLUTE_URL): string
@ -368,9 +353,6 @@ class Attachment extends Entity
}
/**
* @param null|string $size
* @param bool $crop
*
* @throws ClientException
* @throws NotFoundException
* @throws ServerException

View File

@ -1,5 +1,7 @@
<?php
declare(strict_types = 1);
// {{{ License
// This file is part of GNU social - https://www.gnu.org/software/social
//
@ -39,7 +41,7 @@ class AttachmentToLink extends Entity
// @codeCoverageIgnoreStart
private int $attachment_id;
private int $link_id;
private \DateTimeInterface $modified;
private DateTimeInterface $modified;
public function setAttachmentId(int $attachment_id): self
{
@ -77,10 +79,6 @@ class AttachmentToLink extends Entity
// @codeCoverageIgnoreEnd
// }}} Autocode
/**
* @param int $attachment_id
* @return mixed
*/
public static function removeWhereAttachmentId(int $attachment_id): mixed
{
return DB::dql(
@ -92,11 +90,6 @@ class AttachmentToLink extends Entity
);
}
/**
* @param int $link_id
* @param int $attachment_id
* @return mixed
*/
public static function removeWhere(int $link_id, int $attachment_id): mixed
{
return DB::dql(
@ -109,10 +102,6 @@ class AttachmentToLink extends Entity
);
}
/**
* @param int $link_id
* @return mixed
*/
public static function removeWhereLinkId(int $link_id): mixed
{
return DB::dql(

View File

@ -1,5 +1,7 @@
<?php
declare(strict_types = 1);
// {{{ License
// This file is part of GNU social - https://www.gnu.org/software/social
//
@ -19,7 +21,6 @@
namespace Component\Attachment\Entity;
use App\Core\Cache;
use App\Core\DB\DB;
use App\Core\Entity;
use DateTimeInterface;
@ -45,7 +46,7 @@ class AttachmentToNote extends Entity
private int $attachment_id;
private int $note_id;
private ?string $title;
private \DateTimeInterface $modified;
private DateTimeInterface $modified;
public function setAttachmentId(int $attachment_id): self
{
@ -94,11 +95,6 @@ class AttachmentToNote extends Entity
// @codeCoverageIgnoreEnd
// }}} Autocode
/**
* @param int $note_id
* @param int $attachment_id
* @return mixed
*/
public static function removeWhere(int $note_id, int $attachment_id): mixed
{
return DB::dql(
@ -111,10 +107,6 @@ class AttachmentToNote extends Entity
);
}
/**
* @param int $note_id
* @return mixed
*/
public static function removeWhereNoteId(int $note_id): mixed
{
return DB::dql(
@ -126,10 +118,6 @@ class AttachmentToNote extends Entity
);
}
/**
* @param int $attachment_id
* @return mixed
*/
public static function removeWhereAttachmentId(int $attachment_id): mixed
{
return DB::dql(

View File

@ -27,8 +27,8 @@ use App\Core\Cache;
use App\Core\DB\DB;
use App\Core\Entity;
use App\Core\Router\Router;
use Component\Attachment\Entity\Attachment;
use App\Util\Common;
use Component\Attachment\Entity\Attachment;
use DateTimeInterface;
/**

View File

@ -1,5 +1,7 @@
<?php
declare(strict_types = 1);
/**
* @author James Walker <james@status.net>
* @author Craig Andrews <candrews@integralblue.com>
@ -8,13 +10,9 @@
namespace Component\FreeNetwork\Controller;
use App\Core\Controller;
use App\Core\Event;
use Component\FreeNetwork\Util\Discovery;
use Component\FreeNetwork\Util\XrdController;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use XML_XRD;
class HostMeta extends XrdController
{

View File

@ -1,4 +1,6 @@
<?php
declare(strict_types = 1);
// This file is part of GNU social - https://www.gnu.org/software/social
//
// GNU social is free software: you can redistribute it and/or modify
@ -30,7 +32,6 @@ use App\Util\Common;
use Component\FreeNetwork\Util\Discovery;
use Component\FreeNetwork\Util\XrdController;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
class OwnerXrd extends XrdController
{

View File

@ -1,4 +1,6 @@
<?php
declare(strict_types = 1);
/*
* StatusNet - the distributed open-source microblogging tool
* Copyright (C) 2010, StatusNet, Inc.
@ -69,7 +71,7 @@ class Webfinger extends XrdController
$this->xrd->subject = $this->resource;
foreach ($this->target->getAliases() as $alias) {
if ($alias != $this->xrd->subject && !in_array($alias, $this->xrd->aliases)) {
if ($alias != $this->xrd->subject && !\in_array($alias, $this->xrd->aliases)) {
$this->xrd->aliases[] = $alias;
}
}

View File

@ -32,17 +32,11 @@ declare(strict_types = 1);
namespace Component\FreeNetwork\Entity;
use App\Core\Cache;
use App\Core\DB\DB;
use App\Core\Entity;
use function App\Core\I18n\_m;
use App\Core\Log;
use App\Entity\Actor;
use Component\FreeNetwork\Util\Discovery;
use DateTimeInterface;
use Exception;
use Plugin\ActivityPub\Util\DiscoveryHints;
use Plugin\ActivityPub\Util\Explorer;
/**
* Table Definition for free_network_actor_protocol
@ -119,9 +113,9 @@ class FreeNetworkActorProtocol extends Entity
public static function protocolSucceeded(string $protocol, int|Actor $actor_id, string $addr): void
{
$actor_id = is_int($actor_id) ? $actor_id : $actor_id->getId();
$actor_id = \is_int($actor_id) ? $actor_id : $actor_id->getId();
$attributed_protocol = self::getByPK(['actor_id' => $actor_id]);
if (is_null($attributed_protocol)) {
if (\is_null($attributed_protocol)) {
$attributed_protocol = self::create([
'actor_id' => $actor_id,
'protocol' => $protocol,
@ -130,14 +124,14 @@ class FreeNetworkActorProtocol extends Entity
} else {
$attributed_protocol->setProtocol($protocol);
}
DB::wrapInTransaction(fn() => DB::persist($attributed_protocol));
DB::wrapInTransaction(fn () => DB::persist($attributed_protocol));
}
public static function canIActor(string $protocol, int|Actor $actor_id): bool
{
$actor_id = is_int($actor_id) ? $actor_id : $actor_id->getId();
$actor_id = \is_int($actor_id) ? $actor_id : $actor_id->getId();
$attributed_protocol = self::getByPK(['actor_id' => $actor_id])?->getProtocol();
if (is_null($attributed_protocol)) {
if (\is_null($attributed_protocol)) {
// If it is not attributed, you can go ahead.
return true;
} else {
@ -149,9 +143,9 @@ class FreeNetworkActorProtocol extends Entity
public static function canIAddr(string $protocol, string $target): bool
{
// Normalize $addr, i.e. add 'acct:' if missing
$addr = Discovery::normalize($target);
$addr = Discovery::normalize($target);
$attributed_protocol = self::getByPK(['addr' => $addr])?->getProtocol();
if (is_null($attributed_protocol)) {
if (\is_null($attributed_protocol)) {
// If it is not attributed, you can go ahead.
return true;
} else {
@ -167,7 +161,7 @@ class FreeNetworkActorProtocol extends Entity
'fields' => [
'actor_id' => ['type' => 'int', 'not null' => true],
'protocol' => ['type' => 'varchar', 'length' => 32, 'description' => 'the protocol plugin that should handle federation of this actor'],
'addr' => ['type' => 'text', 'not null' => true, 'description' => 'webfinger acct'],
'addr' => ['type' => 'text', 'not null' => true, 'description' => 'webfinger acct'],
'created' => ['type' => 'datetime', 'not null' => true, 'default' => 'CURRENT_TIMESTAMP', 'description' => 'date this record was created'],
'modified' => ['type' => 'timestamp', 'not null' => true, 'default' => 'CURRENT_TIMESTAMP', 'description' => 'date this record was modified'],
],

View File

@ -1,4 +1,6 @@
<?php
declare(strict_types = 1);
/**
* StatusNet, the distributed open-source microblogging tool
*
@ -50,7 +52,7 @@ use Throwable;
*/
class WebfingerReconstructionException extends ServerException
{
public function __construct(string $message = '', int $code = 500, Throwable $previous = null)
public function __construct(string $message = '', int $code = 500, ?Throwable $previous = null)
{
// We could log an entry here with the search parameters
parent::__construct(_m('WebFinger URI generation failed.'));

View File

@ -1,4 +1,6 @@
<?php
declare(strict_types = 1);
/**
* StatusNet - the distributed open-source microblogging tool
* Copyright (C) 2010, StatusNet, Inc.
@ -69,7 +71,7 @@ class LinkHeader
$this->type = null;
// remove uri-reference from header
$str = substr($str, strlen($uri_reference[0]));
$str = mb_substr($str, \mb_strlen($uri_reference[0]));
// parse link-params
$params = explode(';', $str);
@ -78,7 +80,7 @@ class LinkHeader
if (empty($param)) {
continue;
}
list($param_name, $param_value) = explode('=', $param, 2);
[$param_name, $param_value] = explode('=', $param, 2);
$param_name = trim($param_name);
$param_value = preg_replace('(^"|"$)', '', trim($param_value));
@ -110,18 +112,18 @@ class LinkHeader
$headers = $response->getHeader('Link');
if ($headers) {
// Can get an array or string, so try to simplify the path
if (!is_array($headers)) {
if (!\is_array($headers)) {
$headers = [$headers];
}
foreach ($headers as $header) {
$lh = new self($header);
if ((is_null($rel) || $lh->rel == $rel) && (is_null($type) || $lh->type == $type)) {
if ((\is_null($rel) || $lh->rel == $rel) && (\is_null($type) || $lh->type == $type)) {
return $lh->href;
}
}
}
return null;
}
}

View File

@ -1,5 +1,7 @@
<?php
declare(strict_types = 1);
namespace Component\FreeNetwork\Util\LrddMethod;
// This file is part of GNU social - https://www.gnu.org/software/social
@ -39,29 +41,27 @@ class LrddMethodHostMeta extends LRDDMethod
/**
* For RFC6415 and HTTP URIs, fetch the host-meta file
* and look for LRDD templates
*
* @param mixed $uri
*/
public function discover($uri)
{
// This is allowed for RFC6415 but not the 'WebFinger' RFC7033.
$try_schemes = ['https', 'http'];
$scheme = mb_strtolower(parse_url($uri, PHP_URL_SCHEME));
$scheme = mb_strtolower(parse_url($uri, \PHP_URL_SCHEME));
switch ($scheme) {
case 'acct':
// We can't use parse_url data for this, since the 'host'
// entry is only set if the scheme has '://' after it.
$parts = explode('@', parse_url($uri, PHP_URL_PATH), 2);
$parts = explode('@', parse_url($uri, \PHP_URL_PATH), 2);
if (!Discovery::isAcct($uri) || count($parts) != 2) {
if (!Discovery::isAcct($uri) || \count($parts) != 2) {
throw new Exception('Bad resource URI: ' . $uri);
}
[, $domain] = $parts;
break;
case 'http':
case 'https':
$domain = mb_strtolower(parse_url($uri, PHP_URL_HOST));
$domain = mb_strtolower(parse_url($uri, \PHP_URL_HOST));
$try_schemes = [$scheme];
break;
default:

View File

@ -1,5 +1,7 @@
<?php
declare(strict_types = 1);
namespace Component\FreeNetwork\Util\LrddMethod;
// This file is part of GNU social - https://www.gnu.org/software/social
@ -38,10 +40,7 @@ class LrddMethodLinkHtml extends LRDDMethod
* For HTTP IDs, fetch the URL and look for <link> elements
* in the HTML response.
*
* @param mixed $uri
*
* @todo fail out of WebFinger URIs faster
*
*/
public function discover($uri)
{
@ -65,7 +64,7 @@ class LrddMethodLinkHtml extends LRDDMethod
preg_match('/<head(\s[^>]*)?>(.*?)<\/head>/is', $html, $head_matches);
if (count($head_matches) != 3) {
if (\count($head_matches) != 3) {
return [];
}
[, , $head_html] = $head_matches;
@ -78,23 +77,23 @@ class LrddMethodLinkHtml extends LRDDMethod
$link_type = null;
preg_match('/\srel=(("|\')([^\\2]*?)\\2|[^"\'\s]+)/i', $link_html, $rel_matches);
if (count($rel_matches) > 3) {
if (\count($rel_matches) > 3) {
$link_rel = $rel_matches[3];
} elseif (count($rel_matches) > 1) {
} elseif (\count($rel_matches) > 1) {
$link_rel = $rel_matches[1];
}
preg_match('/\shref=(("|\')([^\\2]*?)\\2|[^"\'\s]+)/i', $link_html, $href_matches);
if (count($href_matches) > 3) {
if (\count($href_matches) > 3) {
$link_uri = $href_matches[3];
} elseif (count($href_matches) > 1) {
} elseif (\count($href_matches) > 1) {
$link_uri = $href_matches[1];
}
preg_match('/\stype=(("|\')([^\\2]*?)\\2|[^"\'\s]+)/i', $link_html, $type_matches);
if (count($type_matches) > 3) {
if (\count($type_matches) > 3) {
$link_type = $type_matches[3];
} elseif (count($type_matches) > 1) {
} elseif (\count($type_matches) > 1) {
$link_type = $type_matches[1];
}

View File

@ -1,4 +1,6 @@
<?php
declare(strict_types = 1);
// This file is part of GNU social - https://www.gnu.org/software/social
//
// GNU social is free software: you can redistribute it and/or modify
@ -36,19 +38,17 @@ class LrddMethodWebfinger extends LRDDMethod
/**
* Simply returns the WebFinger URL over HTTPS at the uri's domain:
* https://{domain}/.well-known/webfinger?resource={uri}
*
* @param mixed $uri
*/
public function discover($uri)
{
$parts = explode('@', parse_url($uri, PHP_URL_PATH), 2);
$parts = explode('@', parse_url($uri, \PHP_URL_PATH), 2);
if (!Discovery::isAcct($uri) || count($parts) != 2) {
if (!Discovery::isAcct($uri) || \count($parts) != 2) {
throw new Exception('Bad resource URI: ' . $uri);
}
[, $domain] = $parts;
if (!filter_var($domain, FILTER_VALIDATE_IP)
&& !filter_var(gethostbyname($domain), FILTER_VALIDATE_IP)) {
if (!filter_var($domain, \FILTER_VALIDATE_IP)
&& !filter_var(gethostbyname($domain), \FILTER_VALIDATE_IP)) {
throw new Exception('Bad resource host.');
}
@ -56,7 +56,7 @@ class LrddMethodWebfinger extends LRDDMethod
Discovery::LRDD_REL,
'https://' . $domain . '/.well-known/webfinger?resource={uri}',
Discovery::JRD_MIMETYPE,
true // isTemplate
true, // isTemplate
);
return [$link];

View File

@ -1,5 +1,7 @@
<?php
declare(strict_types = 1);
namespace Component\FreeNetwork\Util;
use App\Core\Entity;
@ -40,8 +42,6 @@ abstract class WebfingerResource
/**
* List of alternative IDs of a certain Actor
*
* @return array
*/
public function getAliases(): array
{
@ -53,7 +53,7 @@ abstract class WebfingerResource
// you've run HTTPS all the time!
if (Common::config('fix', 'legacy_http')) {
foreach ($aliases as $alias => $id) {
if (!strtolower(parse_url($alias, PHP_URL_SCHEME)) === 'https') {
if (!mb_strtolower(parse_url($alias, \PHP_URL_SCHEME)) === 'https') {
continue;
}
$aliases[preg_replace('/^https:/i', 'http:', $alias, 1)] = $id;

View File

@ -1,5 +1,7 @@
<?php
declare(strict_types = 1);
namespace Component\FreeNetwork\Util\WebfingerResource;
use App\Core\Event;
@ -24,9 +26,9 @@ use XML_XRD_Element_Link;
*/
class WebfingerResourceActor extends WebFingerResource
{
const PROFILEPAGE = 'http://webfinger.net/rel/profile-page';
public const PROFILEPAGE = 'http://webfinger.net/rel/profile-page';
public function __construct(Actor $object = null)
public function __construct(?Actor $object = null)
{
// The type argument above verifies that it's our class
parent::__construct($object);
@ -49,8 +51,9 @@ class WebfingerResourceActor extends WebFingerResource
/**
* Reconstruct WebFinger acct: from object
*
* @return array|false|mixed|string|string[]|null
* @throws WebfingerReconstructionException
*
* @return null|array|false|mixed|string|string[]
*/
public function reconstructAcct()
{
@ -58,7 +61,7 @@ class WebfingerResourceActor extends WebFingerResource
if (Event::handle('StartWebFingerReconstruction', [$this->object, &$acct])) {
// TODO: getUri may not always give us the correct host on remote users?
$host = parse_url($this->object->getUri(Router::ABSOLUTE_URL), PHP_URL_HOST);
$host = parse_url($this->object->getUri(Router::ABSOLUTE_URL), \PHP_URL_HOST);
if (empty($this->object->getNickname()) || empty($host)) {
throw new WebFingerReconstructionException(print_r($this->object, true));
}
@ -75,8 +78,11 @@ class WebfingerResourceActor extends WebFingerResource
if (Event::handle('StartWebFingerProfileLinks', [$xrd, $this->object])) {
// Profile page, can give more metadata from Link header or HTML parsing
$xrd->links[] = new XML_XRD_Element_Link(self::PROFILEPAGE,
$this->object->getUrl(Router::ABSOLUTE_URL), 'text/html');
$xrd->links[] = new XML_XRD_Element_Link(
self::PROFILEPAGE,
$this->object->getUrl(Router::ABSOLUTE_URL),
'text/html',
);
// // XFN
// $xrd->links[] = new XML_XRD_Element_Link('http://gmpg.org/xfn/11',

View File

@ -1,5 +1,7 @@
<?php
declare(strict_types = 1);
namespace Component\FreeNetwork\Util\WebfingerResource;
use App\Core\Event;
@ -22,7 +24,7 @@ use XML_XRD_Element_Link;
*/
class WebfingerResourceNote extends WebfingerResource
{
public function __construct(Note $object = null)
public function __construct(?Note $object = null)
{
// The type argument above verifies that it's our class
parent::__construct($object);
@ -30,29 +32,37 @@ class WebfingerResourceNote extends WebfingerResource
/**
* Update given XRD with self's data
*
* @param XML_XRD $xrd
*/
public function updateXRD(XML_XRD $xrd)
{
if (Event::handle('StartWebFingerNoticeLinks', [$xrd, $this->object])) {
if ($this->object->isLocal()) {
$xrd->links[] = new XML_XRD_Element_Link('alternate',
common_local_url('ApiStatusesShow',
$xrd->links[] = new XML_XRD_Element_Link(
'alternate',
common_local_url(
'ApiStatusesShow',
['id' => $this->object->id,
'format' => 'atom', ]),
'application/atom+xml');
'format' => 'atom', ],
),
'application/atom+xml',
);
$xrd->links[] = new XML_XRD_Element_Link('alternate',
common_local_url('ApiStatusesShow',
$xrd->links[] = new XML_XRD_Element_Link(
'alternate',
common_local_url(
'ApiStatusesShow',
['id' => $this->object->id,
'format' => 'json', ]),
'application/json');
'format' => 'json', ],
),
'application/json',
);
} else {
try {
$xrd->links[] = new XML_XRD_Element_Link('alternate',
$xrd->links[] = new XML_XRD_Element_Link(
'alternate',
$this->object->getUrl(),
'text/html');
'text/html',
);
} catch (InvalidUrlException $e) {
// don't do a fallback in webfinger
}

View File

@ -1,5 +1,7 @@
<?php
declare(strict_types = 1);
namespace Component\FreeNetwork\Util;
use App\Core\Controller;
@ -35,4 +37,4 @@ abstract class XrdController extends Controller
$this->setXRD();
return ['xrd' => $this->xrd, 'default_mimetype' => $this->default_mimetype];
}
}
}

View File

@ -28,13 +28,13 @@ use App\Core\Controller;
use App\Core\DB\DB;
use App\Core\Form;
use function App\Core\I18n\_m;
use Component\Language\Entity\ActorLanguage;
use Component\Language\Entity\Language as LangEntity;
use App\Util\Common;
use App\Util\Exception\NoLoggedInUser;
use App\Util\Exception\RedirectException;
use App\Util\Exception\ServerException;
use App\Util\Form\FormFields;
use Component\Language\Entity\ActorLanguage;
use Component\Language\Entity\Language as LangEntity;
use Functional as F;
use Symfony\Component\Form\Extension\Core\Type\IntegerType;
use Symfony\Component\Form\Extension\Core\Type\SubmitType;

View File

@ -1,6 +1,6 @@
<?php
declare(strict_types=1);
declare(strict_types = 1);
// {{{ License
@ -26,13 +26,12 @@ namespace Component\Language\Entity;
use App\Core\Cache;
use App\Core\DB\DB;
use App\Core\Entity;
use function App\Core\I18n\_m;
use App\Entity\Actor;
use App\Entity\Note;
use App\Util\Common;
use DateTimeInterface;
use Functional as F;
use function App\Core\I18n\_m;
use function is_null;
/**
* Entity for languages
@ -115,8 +114,8 @@ class Language extends Entity
{
return Cache::getHashMapKey(
map_key: 'languages-id',
key: (string)$id,
calculate_map: fn() => F\reindex(DB::dql('select l from language l'), fn(self $l) => (string)$l->getId()),
key: (string) $id,
calculate_map: fn () => F\reindex(DB::dql('select l from language l'), fn (self $l) => (string) $l->getId()),
);
}
@ -125,7 +124,7 @@ class Language extends Entity
return Cache::getHashMapKey(
'languages',
$locale,
calculate_map: fn() => F\reindex(DB::dql('select l from language l'), fn(self $l) => $l->getLocale()),
calculate_map: fn () => F\reindex(DB::dql('select l from language l'), fn (self $l) => $l->getLocale()),
);
}
@ -138,10 +137,10 @@ class Language extends Entity
{
$langs = Cache::getHashMap(
'languages',
fn() => F\reindex(DB::dql('select l from language l'), fn(self $l) => $l->getLocale()),
fn () => F\reindex(DB::dql('select l from language l'), fn (self $l) => $l->getLocale()),
);
return array_merge(...F\map(array_values($langs), fn($l) => $l->toChoiceFormat()));
return array_merge(...F\map(array_values($langs), fn ($l) => $l->toChoiceFormat()));
}
public function toChoiceFormat(): array
@ -156,18 +155,18 @@ class Language extends Entity
public static function getSortedLanguageChoices(?Actor $actor, ?Actor $context_actor, ?bool $use_short_display): array
{
$language_choices = self::getLanguageChoices();
if (is_null($actor)) {
if (\is_null($actor)) {
return [$language_choices, []];
}
$preferred_language_choices = $actor->getPreferredLanguageChoices($context_actor);
ksort($language_choices);
if ($use_short_display ?? Common::config('posting', 'use_short_language_display')) {
$key = array_key_first($preferred_language_choices);
$key = array_key_first($preferred_language_choices);
$language = $preferred_language_choices[$key];
unset($preferred_language_choices[$key], $language_choices[$key]);
$short_display = $language->getShortDisplay();
$short_display = $language->getShortDisplay();
$preferred_language_choices[$short_display] = ($locale = $language->getLocale());
$language_choices[$short_display] = $locale;
$language_choices[$short_display] = $locale;
}
return [$language_choices, $preferred_language_choices];
}
@ -175,14 +174,14 @@ class Language extends Entity
public static function schemaDef(): array
{
return [
'name' => 'language',
'name' => 'language',
'description' => 'all known languages',
'fields' => [
'id' => ['type' => 'serial', 'not null' => true, 'description' => 'unique identifier'],
'locale' => ['type' => 'varchar', 'length' => 64, 'description' => 'The locale identifier for the language of a note. 2-leter-iso-language-code_4-leter-script-code_2-leter-iso-country-code, but kept longer in case we get a different format'],
'long_display' => ['type' => 'varchar', 'length' => 64, 'description' => 'The long display string for the language, in english (translated later)'],
'fields' => [
'id' => ['type' => 'serial', 'not null' => true, 'description' => 'unique identifier'],
'locale' => ['type' => 'varchar', 'length' => 64, 'description' => 'The locale identifier for the language of a note. 2-leter-iso-language-code_4-leter-script-code_2-leter-iso-country-code, but kept longer in case we get a different format'],
'long_display' => ['type' => 'varchar', 'length' => 64, 'description' => 'The long display string for the language, in english (translated later)'],
'short_display' => ['type' => 'varchar', 'length' => 12, 'description' => 'The short display string for the language (used for the first option)'],
'created' => ['type' => 'datetime', 'not null' => true, 'default' => 'CURRENT_TIMESTAMP', 'description' => 'date this record was created'],
'created' => ['type' => 'datetime', 'not null' => true, 'default' => 'CURRENT_TIMESTAMP', 'description' => 'date this record was created'],
],
'primary key' => ['id'],
'unique keys' => [

View File

@ -1,5 +1,7 @@
<?php
declare(strict_types = 1);
// {{{ License
// This file is part of GNU social - https://www.gnu.org/software/social
//
@ -40,7 +42,7 @@ class NoteToLink extends Entity
// @codeCoverageIgnoreStart
private int $link_id;
private int $note_id;
private \DateTimeInterface $modified;
private DateTimeInterface $modified;
public function setLinkId(int $link_id): self
{
@ -93,10 +95,6 @@ class NoteToLink extends Entity
return parent::create($args, $obj);
}
/**
* @param int $note_id
* @return mixed
*/
public static function removeWhereNoteId(int $note_id): mixed
{
return DB::dql(
@ -108,11 +106,6 @@ class NoteToLink extends Entity
);
}
/**
* @param int $link_id
* @param int $note_id
* @return mixed
*/
public static function removeWhere(int $link_id, int $note_id): mixed
{
return DB::dql(
@ -125,10 +118,6 @@ class NoteToLink extends Entity
);
}
/**
* @param int $link_id
* @return mixed
*/
public static function removeWhereLinkId(int $link_id): mixed
{
return DB::dql(

View File

@ -1,5 +1,7 @@
<?php
declare(strict_types = 1);
// {{{ License
// This file is part of GNU social - https://www.gnu.org/software/social
//
@ -46,8 +48,8 @@ class Notification extends Entity
private int $activity_id;
private int $target_id;
private ?string $reason;
private \DateTimeInterface $created;
private \DateTimeInterface $modified;
private DateTimeInterface $created;
private DateTimeInterface $modified;
public function setActivityId(int $activity_id): self
{
@ -107,9 +109,6 @@ class Notification extends Entity
// @codeCoverageIgnoreEnd
// }}} Autocode
/**
* @return Actor
*/
public function getTarget(): Actor
{
return Actor::getById($this->getTargetId());
@ -122,18 +121,14 @@ class Notification extends Entity
*/
public static function getNotificationTargetIdsByActivity(int|Activity $activity_id): array
{
$notifications = DB::findBy('notification', ['activity_id' => is_int($activity_id) ? $activity_id : $activity_id->getId()]);
$targets = [];
$notifications = DB::findBy('notification', ['activity_id' => \is_int($activity_id) ? $activity_id : $activity_id->getId()]);
$targets = [];
foreach ($notifications as $notification) {
$targets[] = $notification->getTargetId();
}
return $targets;
}
/**
* @param int|Activity $activity_id
* @return array
*/
public function getNotificationTargetsByActivity(int|Activity $activity_id): array
{
return DB::findBy('actor', ['id' => $this->getNotificationTargetIdsByActivity($activity_id)]);
@ -154,7 +149,7 @@ class Notification extends Entity
'primary key' => ['activity_id', 'target_id'],
'indexes' => [
'attention_activity_id_idx' => ['activity_id'],
'attention_target_id_idx' => ['target_id'],
'attention_target_id_idx' => ['target_id'],
],
];
}

View File

@ -1,5 +1,7 @@
<?php
declare(strict_types = 1);
// {{{ License
// This file is part of GNU social - https://www.gnu.org/software/social
//
@ -48,8 +50,8 @@ class UserNotificationPrefs extends Entity
private bool $dm = true;
private bool $post_on_status_change = false;
private ?bool $enable_posting;
private \DateTimeInterface $created;
private \DateTimeInterface $modified;
private DateTimeInterface $created;
private DateTimeInterface $modified;
public function setUserId(int $user_id): self
{

View File

@ -37,7 +37,6 @@ use App\Core\Security;
use App\Entity\Activity;
use App\Entity\Actor;
use App\Entity\GroupInbox;
use Component\Language\Entity\Language;
use App\Entity\Note;
use App\Util\Common;
use App\Util\Exception\ClientException;
@ -49,6 +48,7 @@ use App\Util\Formatting;
use Component\Attachment\Entity\ActorToAttachment;
use Component\Attachment\Entity\AttachmentToNote;
use Component\Conversation\Conversation;
use Component\Language\Entity\Language;
use Functional as F;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use Symfony\Component\Form\Extension\Core\Type\FileType;

View File

@ -26,7 +26,6 @@ namespace Component\Tag;
use App\Core\Cache;
use App\Core\DB\DB;
use App\Core\Event;
use Component\Language\Entity\Language;
use function App\Core\I18n\_m;
use App\Core\Modules\Component;
use App\Core\Router\Router;
@ -38,6 +37,7 @@ use App\Util\Common;
use App\Util\Exception\ClientException;
use App\Util\Formatting;
use App\Util\HTML;
use Component\Language\Entity\Language;
use Component\Tag\Controller as C;
use Doctrine\Common\Collections\ExpressionBuilder;
use Doctrine\ORM\Query\Expr;

View File

@ -1,6 +1,6 @@
<?php
declare(strict_types=1);
declare(strict_types = 1);
// {{{ License
// This file is part of GNU social - https://www.gnu.org/software/social
@ -24,6 +24,7 @@ declare(strict_types=1);
*
* @package GNUsocial
* @category ActivityPub
*
* @author Diogo Peralta Cordeiro <@diogo.site>
* @copyright 2021 Free Software Foundation, Inc http://www.fsf.org
* @license https://www.gnu.org/licenses/agpl.html GNU AGPL v3 or later
@ -106,15 +107,15 @@ class ActivitypubActivity extends Entity
public static function schemaDef(): array
{
return [
'name' => 'activitypub_activity',
'name' => 'activitypub_activity',
'fields' => [
'activity_id' => ['type' => 'int', 'foreign key' => true, 'target' => 'Activity.id', 'multiplicity' => 'one to one', 'not null' => true, 'description' => 'activity_id to give attention'],
'activity_id' => ['type' => 'int', 'foreign key' => true, 'target' => 'Activity.id', 'multiplicity' => 'one to one', 'not null' => true, 'description' => 'activity_id to give attention'],
'activity_uri' => ['type' => 'text', 'not null' => true, 'description' => 'Activity\'s URI'],
'created' => ['type' => 'datetime', 'not null' => true, 'default' => 'CURRENT_TIMESTAMP', 'description' => 'date this record was created'],
'modified' => ['type' => 'timestamp', 'not null' => true, 'default' => 'CURRENT_TIMESTAMP', 'description' => 'date this record was modified'],
'created' => ['type' => 'datetime', 'not null' => true, 'default' => 'CURRENT_TIMESTAMP', 'description' => 'date this record was created'],
'modified' => ['type' => 'timestamp', 'not null' => true, 'default' => 'CURRENT_TIMESTAMP', 'description' => 'date this record was modified'],
],
'primary key' => ['activity_uri'],
'indexes' => [
'indexes' => [
'activity_activity_uri_idx' => ['activity_uri'],
],
];

View File

@ -1,6 +1,6 @@
<?php
declare(strict_types=1);
declare(strict_types = 1);
// {{{ License
// This file is part of GNU social - https://www.gnu.org/software/social
@ -24,6 +24,7 @@ declare(strict_types=1);
*
* @package GNUsocial
* @category ActivityPub
*
* @author Diogo Peralta Cordeiro <@diogo.site>
* @copyright 2018-2019, 2021 Free Software Foundation, Inc http://www.fsf.org
* @license https://www.gnu.org/licenses/agpl.html GNU AGPL v3 or later
@ -33,6 +34,7 @@ namespace Plugin\ActivityPub\Entity;
use App\Core\Cache;
use App\Core\Entity;
use function App\Core\I18n\_m;
use App\Core\Log;
use App\Entity\Actor;
use Component\FreeNetwork\Util\Discovery;
@ -41,9 +43,6 @@ use Exception;
use Plugin\ActivityPub\Util\DiscoveryHints;
use Plugin\ActivityPub\Util\Explorer;
use XML_XRD;
use function App\Core\I18n\_m;
use function array_key_exists;
use function is_null;
/**
* Table Definition for activitypub_actor
@ -158,10 +157,10 @@ class ActivitypubActor extends Entity
$addr = Discovery::normalize($addr);
// Try the cache
$uri = Cache::get(sprintf('ActivitypubActor-webfinger-%s', urlencode($addr)), fn() => false);
$uri = Cache::get(sprintf('ActivitypubActor-webfinger-%s', urlencode($addr)), fn () => false);
if ($uri !== false) {
if (is_null($uri)) {
if (\is_null($uri)) {
// TRANS: Exception.
throw new Exception(_m('Not a valid WebFinger address (via cache).'));
}
@ -197,7 +196,7 @@ class ActivitypubActor extends Entity
DiscoveryHints::fromXRD($xrd),
);
if (array_key_exists('activitypub', $hints)) {
if (\array_key_exists('activitypub', $hints)) {
$uri = $hints['activitypub'];
try {
LOG::info("Discovery on acct:{$addr} with URI:{$uri}");
@ -240,9 +239,7 @@ class ActivitypubActor extends Entity
/**
* @param ActivitypubActor $ap_actor
* @param Actor $actor
* @param ActivitypubRsa $activitypub_rsa
* @param string $res
*
* @throws Exception
*/
public static function update_profile(self &$ap_actor, Actor &$actor, ActivitypubRsa &$activitypub_rsa, string $res): void
@ -253,17 +250,17 @@ class ActivitypubActor extends Entity
public static function schemaDef(): array
{
return [
'name' => 'activitypub_actor',
'name' => 'activitypub_actor',
'fields' => [
'uri' => ['type' => 'text', 'not null' => true],
'actor_id' => ['type' => 'int', 'not null' => true],
'inbox_uri' => ['type' => 'text', 'not null' => true],
'uri' => ['type' => 'text', 'not null' => true],
'actor_id' => ['type' => 'int', 'not null' => true],
'inbox_uri' => ['type' => 'text', 'not null' => true],
'inbox_shared_uri' => ['type' => 'text'],
'url' => ['type' => 'text'],
'created' => ['type' => 'datetime', 'not null' => true, 'default' => 'CURRENT_TIMESTAMP', 'description' => 'date this record was created'],
'modified' => ['type' => 'timestamp', 'not null' => true, 'default' => 'CURRENT_TIMESTAMP', 'description' => 'date this record was modified'],
'url' => ['type' => 'text'],
'created' => ['type' => 'datetime', 'not null' => true, 'default' => 'CURRENT_TIMESTAMP', 'description' => 'date this record was created'],
'modified' => ['type' => 'timestamp', 'not null' => true, 'default' => 'CURRENT_TIMESTAMP', 'description' => 'date this record was modified'],
],
'primary key' => ['actor_id'],
'primary key' => ['actor_id'],
'foreign keys' => [
'activitypub_actor_actor_id_fkey' => ['actor', ['actor_id' => 'id']],
],

View File

@ -1,6 +1,6 @@
<?php
declare(strict_types=1);
declare(strict_types = 1);
// {{{ License
// This file is part of GNU social - https://www.gnu.org/software/social
@ -24,6 +24,7 @@ declare(strict_types=1);
*
* @package GNUsocial
* @category ActivityPub
*
* @author Diogo Peralta Cordeiro <@diogo.site>
* @copyright 2021 Free Software Foundation, Inc http://www.fsf.org
* @license https://www.gnu.org/licenses/agpl.html GNU AGPL v3 or later
@ -117,16 +118,16 @@ class ActivitypubObject extends Entity
public static function schemaDef(): array
{
return [
'name' => 'activitypub_object',
'name' => 'activitypub_object',
'fields' => [
'object_uri' => ['type' => 'text', 'not null' => true, 'description' => 'Object\'s URI'],
'object_uri' => ['type' => 'text', 'not null' => true, 'description' => 'Object\'s URI'],
'object_type' => ['type' => 'varchar', 'length' => 32, 'not null' => true, 'description' => 'the name of the table this object refers to'],
'object_id' => ['type' => 'int', 'not null' => true, 'description' => 'id in the referenced table'],
'created' => ['type' => 'datetime', 'not null' => true, 'default' => 'CURRENT_TIMESTAMP', 'description' => 'date this record was created'],
'modified' => ['type' => 'timestamp', 'not null' => true, 'default' => 'CURRENT_TIMESTAMP', 'description' => 'date this record was modified'],
'object_id' => ['type' => 'int', 'not null' => true, 'description' => 'id in the referenced table'],
'created' => ['type' => 'datetime', 'not null' => true, 'default' => 'CURRENT_TIMESTAMP', 'description' => 'date this record was created'],
'modified' => ['type' => 'timestamp', 'not null' => true, 'default' => 'CURRENT_TIMESTAMP', 'description' => 'date this record was modified'],
],
'primary key' => ['object_uri'],
'indexes' => [
'indexes' => [
'activity_object_uri_idx' => ['object_uri'],
],
];

View File

@ -1,6 +1,6 @@
<?php
declare(strict_types=1);
declare(strict_types = 1);
// {{{ License
// This file is part of GNU social - https://www.gnu.org/software/social
@ -24,6 +24,7 @@ declare(strict_types=1);
*
* @package GNUsocial
* @category ActivityPub
*
* @author Diogo Peralta Cordeiro <@diogo.site>
* @copyright 2018-2019, 2021 Free Software Foundation, Inc http://www.fsf.org
* @license https://www.gnu.org/licenses/agpl.html GNU AGPL v3 or later
@ -119,15 +120,15 @@ class ActivitypubRsa extends Entity
public static function schemaDef(): array
{
return [
'name' => 'activitypub_rsa',
'name' => 'activitypub_rsa',
'fields' => [
'actor_id' => ['type' => 'int', 'not null' => true],
'actor_id' => ['type' => 'int', 'not null' => true],
'private_key' => ['type' => 'text'],
'public_key' => ['type' => 'text', 'not null' => true],
'created' => ['type' => 'datetime', 'not null' => true, 'default' => 'CURRENT_TIMESTAMP', 'description' => 'date this record was created'],
'modified' => ['type' => 'timestamp', 'not null' => true, 'default' => 'CURRENT_TIMESTAMP', 'description' => 'date this record was modified'],
'public_key' => ['type' => 'text', 'not null' => true],
'created' => ['type' => 'datetime', 'not null' => true, 'default' => 'CURRENT_TIMESTAMP', 'description' => 'date this record was created'],
'modified' => ['type' => 'timestamp', 'not null' => true, 'default' => 'CURRENT_TIMESTAMP', 'description' => 'date this record was modified'],
],
'primary key' => ['actor_id'],
'primary key' => ['actor_id'],
'foreign keys' => [
'activitypub_rsa_actor_id_fkey' => ['actor', ['actor_id' => 'id']],
],
@ -137,27 +138,28 @@ class ActivitypubRsa extends Entity
/**
* Guarantees RSA keys for a given actor.
*
* @param Actor $gsactor
* @param bool $fetch =true Should attempt to fetch keys from a remote profile?
* @return ActivitypubRsa The keys (private key is null for remote actors)
*
* @throws ServerException It should never occur, but if so, we break everything!
*
* @return ActivitypubRsa The keys (private key is null for remote actors)
*/
public static function getByActor(Actor $gsactor, bool $fetch = true): self
{
$apRSA = self::getByPK(['actor_id' => ($actor_id = $gsactor->getId())]);
if (is_null($apRSA)) {
if (\is_null($apRSA)) {
// Nonexistent key pair for this profile
if ($gsactor->getIsLocal()) {
self::generateKeys($private_key, $public_key);
$apRSA = self::create([
'actor_id' => $actor_id,
'actor_id' => $actor_id,
'private_key' => $private_key,
'public_key' => $public_key,
'public_key' => $public_key,
]);
DB::wrapInTransaction(fn() => DB::persist($apRSA));
DB::wrapInTransaction(fn () => DB::persist($apRSA));
} else {
// ASSERT: This should never happen, but try to recover!
Log::error("Activitypub_rsa: An impossible thing has happened... Please let the devs know.");
Log::error('Activitypub_rsa: An impossible thing has happened... Please let the devs know.');
if ($fetch) {
//$res = Activitypub_explorer::get_remote_user_activity($profile->getUri());
//Activitypub_rsa::update_public_key($profile, $res['publicKey']['publicKeyPem']);
@ -173,16 +175,17 @@ class ActivitypubRsa extends Entity
/**
* Generates a pair of RSA keys.
*
* @param string|null $private_key out
* @param string|null $public_key out
* @param null|string $private_key out
* @param null|string $public_key out
*
* @author PHP Manual Contributed Notes <dirt@awoms.com>
*/
private static function generateKeys(?string &$private_key, ?string &$public_key): void
{
$config = [
'digest_alg' => 'sha512',
'digest_alg' => 'sha512',
'private_key_bits' => 2048,
'private_key_type' => OPENSSL_KEYTYPE_RSA,
'private_key_type' => \OPENSSL_KEYTYPE_RSA,
];
// Create the private and public key
@ -192,8 +195,8 @@ class ActivitypubRsa extends Entity
openssl_pkey_export($res, $private_key);
// Extract the public key from $res to $pubKey
$pubKey = openssl_pkey_get_details($res);
$public_key = $pubKey["key"];
$pubKey = openssl_pkey_get_details($res);
$public_key = $pubKey['key'];
unset($pubKey);
}
}

View File

@ -1,6 +1,6 @@
<?php
declare(strict_types=1);
declare(strict_types = 1);
// {{{ License
// This file is part of GNU social - https://www.gnu.org/software/social
@ -24,6 +24,7 @@ declare(strict_types=1);
*
* @package GNUsocial
* @category ActivityPub
*
* @author Diogo Peralta Cordeiro <@diogo.site>
* @copyright 2018-2019, 2021 Free Software Foundation, Inc http://www.fsf.org
* @license https://www.gnu.org/licenses/agpl.html GNU AGPL v3 or later
@ -51,7 +52,6 @@ use XML_XRD;
/**
* DiscoveryHints implementation for GNU social
*
*
* @copyright 2018-2019, 2021 Free Software Foundation, Inc http://www.fsf.org
* @license https://www.gnu.org/licenses/agpl.html GNU AGPL v3 or later
*/
@ -59,9 +59,6 @@ class DiscoveryHints
{
/**
* Search the WebFinger XRD after an ActivityPub URI
*
* @param XML_XRD $xrd
* @return array
*/
public static function fromXRD(XML_XRD $xrd): array
{
@ -79,4 +76,4 @@ class DiscoveryHints
return $hints;
}
}
}

View File

@ -1,6 +1,6 @@
<?php
declare(strict_types=1);
declare(strict_types = 1);
// {{{ License
// This file is part of GNU social - https://www.gnu.org/software/social
@ -24,6 +24,7 @@ declare(strict_types=1);
*
* @package GNUsocial
* @category ActivityPub
*
* @author Diogo Peralta Cordeiro <@diogo.site>
* @copyright 2018-2019, 2021 Free Software Foundation, Inc http://www.fsf.org
* @license https://www.gnu.org/licenses/agpl.html GNU AGPL v3 or later
@ -35,15 +36,13 @@ use App\Core\HTTPClient;
use App\Core\Log;
use App\Util\Exception\NoSuchActorException;
use Exception;
use const JSON_UNESCAPED_SLASHES;
use Plugin\ActivityPub\ActivityPub;
use Plugin\ActivityPub\Entity\ActivitypubActor;
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 in_array;
use function is_null;
use const JSON_UNESCAPED_SLASHES;
/**
* ActivityPub's own Explorer
@ -60,10 +59,8 @@ class Explorer
/**
* Shortcut function to get a single profile from its URL.
*
* @param string $url
* @param bool $grab_online whether to try online grabbing, defaults to true
*
* @return ActivitypubActor
* @throws ClientExceptionInterface
* @throws NoSuchActorException
* @throws RedirectionExceptionInterface
@ -86,8 +83,8 @@ class Explorer
* This function cleans the $this->discovered_actor_profiles array
* so that there is no erroneous data
*
* @param string $url User's url
* @param bool $grab_online whether to try online grabbing, defaults to true
* @param string $url User's url
* @param bool $grab_online whether to try online grabbing, defaults to true
*
* @throws ClientExceptionInterface
* @throws NoSuchActorException
@ -99,7 +96,7 @@ class Explorer
*/
public function lookup(string $url, bool $grab_online = true)
{
if (in_array($url, ActivityPub::PUBLIC_TO)) {
if (\in_array($url, ActivityPub::PUBLIC_TO)) {
return [];
}
@ -114,8 +111,8 @@ class Explorer
* This is a recursive function that will accumulate the results on
* $discovered_actor_profiles array
*
* @param string $url User's url
* @param bool $grab_online whether to try online grabbing, defaults to true
* @param string $url User's url
* @param bool $grab_online whether to try online grabbing, defaults to true
*
* @throws ClientExceptionInterface
* @throws NoSuchActorException
@ -187,13 +184,13 @@ class Explorer
{
Log::debug('ActivityPub Explorer: Trying to grab a remote actor for ' . $url);
$response = HTTPClient::get($url, ['headers' => ACTIVITYPUB::HTTP_CLIENT_HEADERS]);
$res = json_decode($response->getContent(), true);
$res = json_decode($response->getContent(), true);
if ($response->getStatusCode() == 410) { // If it was deleted
return true; // Nothing to add.
} elseif (!HTTPClient::statusCodeIsOkay($response)) { // If it is unavailable
return false; // Try to add at another time.
}
if (is_null($res)) {
if (\is_null($res)) {
Log::debug('ActivityPub Explorer: Invalid response returned from given Actor URL: ' . $res);
return true; // Nothing to add.
}
@ -210,7 +207,7 @@ class Explorer
Log::debug(
'ActivityPub Explorer: Invalid potential remote actor while grabbing remotely: ' . $url
. '. He returned the following: ' . json_encode($res, JSON_UNESCAPED_SLASHES)
. ' and the following exception: ' . $e->getMessage()
. ' and the following exception: ' . $e->getMessage(),
);
return false;
}
@ -229,14 +226,12 @@ class Explorer
public static function get_aprofile_by_url(string $v): ActivitypubActor|bool
{
$aprofile = ActivitypubActor::getByPK(['uri' => $v]);
return is_null($aprofile) ? false : ActivitypubActor::getByPK(['uri' => $v]);
return \is_null($aprofile) ? false : ActivitypubActor::getByPK(['uri' => $v]);
}
/**
* Allows the Explorer to transverse a collection of persons.
*
* @param string $url
* @return bool
* @throws ClientExceptionInterface
* @throws NoSuchActorException
* @throws RedirectionExceptionInterface
@ -246,7 +241,7 @@ class Explorer
private function travel_collection(string $url): bool
{
$response = HTTPClient::get($url, ['headers' => ACTIVITYPUB::HTTP_CLIENT_HEADERS]);
$res = json_decode($response->getContent(), true);
$res = json_decode($response->getContent(), true);
if (!isset($res['orderedItems'])) {
return false;
@ -258,7 +253,7 @@ class Explorer
}
}
// Go through entire collection
if (!is_null($res['next'])) {
if (!\is_null($res['next'])) {
$this->travel_collection($res['next']);
}
@ -272,12 +267,12 @@ class Explorer
* @param string $url User's url
*
* @throws ClientExceptionInterface
* @throws Exception
* @throws RedirectionExceptionInterface
* @throws ServerExceptionInterface
* @throws TransportExceptionInterface
* @throws Exception
*
* @return string|null If it is able to fetch, false if it's gone
* @return null|string If it is able to fetch, false if it's gone
* // Exceptions when network issues or unsupported Activity format
*/
public static function get_remote_user_activity(string $url): string|null

View File

@ -1,6 +1,6 @@
<?php
declare(strict_types=1);
declare(strict_types = 1);
/**
* Licensed under the Apache License, Version 2.0 (the "License");
@ -17,9 +17,11 @@ declare(strict_types=1);
*
* @category Network
* @package Nautilus
*
* @author Aaron Parecki <aaron@parecki.com>
* @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0
* @link https://github.com/aaronpk/Nautilus/blob/master/app/ActivityPub/HTTPSignature.php
*
* @see https://github.com/aaronpk/Nautilus/blob/master/app/ActivityPub/HTTPSignature.php
*/
namespace Plugin\ActivityPub\Util;
@ -34,12 +36,14 @@ class HTTPSignature
/**
* Sign a message with an Actor
*
* @param Actor $user Actor signing
* @param string $url Inbox url
* @param string|bool $body Data to sign (optional)
* @param array $addlHeaders Additional headers (optional)
* @return array Headers to be used in request
* @param Actor $user Actor signing
* @param string $url Inbox url
* @param bool|string $body Data to sign (optional)
* @param array $addlHeaders Additional headers (optional)
*
* @throws Exception Attempted to sign something that belongs to an Actor we don't own
*
* @return array Headers to be used in request
*/
public static function sign(Actor $user, string $url, string|bool $body = false, array $addlHeaders = []): array
{
@ -47,15 +51,15 @@ class HTTPSignature
if ($body) {
$digest = self::_digest($body);
}
$headers = self::_headersToSign($url, $digest);
$headers = array_merge($headers, $addlHeaders);
$stringToSign = self::_headersToSigningString($headers);
$signedHeaders = implode(' ', array_map('strtolower', array_keys($headers)));
$headers = self::_headersToSign($url, $digest);
$headers = array_merge($headers, $addlHeaders);
$stringToSign = self::_headersToSigningString($headers);
$signedHeaders = implode(' ', array_map('strtolower', array_keys($headers)));
$actor_private_key = ActivitypubRsa::getByActor($user)->getPrivateKey();
// Intentionally unhandled exception, we want this to explode if that happens as it would be a bug
$key = openssl_pkey_get_private($actor_private_key);
openssl_sign($stringToSign, $signature, $key, OPENSSL_ALGO_SHA256);
$signature = base64_encode($signature);
openssl_sign($stringToSign, $signature, $key, \OPENSSL_ALGO_SHA256);
$signature = base64_encode($signature);
$signatureHeader = 'keyId="' . $user->getUri() . '#public-key' . '",headers="' . $signedHeaders . '",algorithm="rsa-sha256",signature="' . $signature . '"';
unset($headers['(request-target)']);
$headers['Signature'] = $signatureHeader;
@ -65,20 +69,16 @@ class HTTPSignature
/**
* @param array|string $body array or json string $body
* @return string
*/
private static function _digest(array|string $body): string
{
if (is_array($body)) {
if (\is_array($body)) {
$body = json_encode($body);
}
return base64_encode(hash('sha256', $body, true));
}
/**
* @param string $url
* @param string|bool $digest
* @return array
* @throws Exception
*/
protected static function _headersToSign(string $url, string|bool $digest = false): array
@ -86,12 +86,12 @@ class HTTPSignature
$date = new DateTime('UTC');
$headers = [
'(request-target)' => 'post ' . parse_url($url, PHP_URL_PATH),
'Date' => $date->format('D, d M Y H:i:s \G\M\T'),
'Host' => parse_url($url, PHP_URL_HOST),
'Accept' => 'application/ld+json; profile="https://www.w3.org/ns/activitystreams", application/activity+json, application/json',
'User-Agent' => 'GNU social ActivityPub Plugin - ' . GNUSOCIAL_ENGINE_URL,
'Content-Type' => 'application/activity+json'
'(request-target)' => 'post ' . parse_url($url, \PHP_URL_PATH),
'Date' => $date->format('D, d M Y H:i:s \G\M\T'),
'Host' => parse_url($url, \PHP_URL_HOST),
'Accept' => 'application/ld+json; profile="https://www.w3.org/ns/activitystreams", application/activity+json, application/json',
'User-Agent' => 'GNU social ActivityPub Plugin - ' . GNUSOCIAL_ENGINE_URL,
'Content-Type' => 'application/activity+json',
];
if ($digest) {
@ -101,24 +101,14 @@ class HTTPSignature
return $headers;
}
/**
* @param array $headers
* @return string
*/
private static function _headersToSigningString(array $headers): string
{
return implode("\n", array_map(function ($k, $v) {
return strtolower($k) . ': ' . $v;
}, array_keys($headers), $headers));
return implode("\n", array_map(fn ($k, $v) => mb_strtolower($k) . ': ' . $v, array_keys($headers), $headers));
}
/**
* @param string $signature
* @return array
*/
public static function parseSignatureHeader(string $signature): array
{
$parts = explode(',', $signature);
$parts = explode(',', $signature);
$signatureData = [];
foreach ($parts as $part) {
@ -129,51 +119,43 @@ class HTTPSignature
if (!isset($signatureData['keyId'])) {
return [
'error' => 'No keyId was found in the signature header. Found: ' . implode(', ', array_keys($signatureData))
'error' => 'No keyId was found in the signature header. Found: ' . implode(', ', array_keys($signatureData)),
];
}
if (!filter_var($signatureData['keyId'], FILTER_VALIDATE_URL)) {
if (!filter_var($signatureData['keyId'], \FILTER_VALIDATE_URL)) {
return [
'error' => 'keyId is not a URL: ' . $signatureData['keyId']
'error' => 'keyId is not a URL: ' . $signatureData['keyId'],
];
}
if (!isset($signatureData['headers']) || !isset($signatureData['signature'])) {
return [
'error' => 'Signature is missing headers or signature parts'
'error' => 'Signature is missing headers or signature parts',
];
}
return $signatureData;
}
/**
* @param string $publicKey
* @param array $signatureData
* @param array $inputHeaders
* @param string $path
* @param string $body
* @return array
*/
public static function verify(string $publicKey, array $signatureData, array $inputHeaders, string $path, string $body): array
{
// We need this because the used Request headers fields specified by Signature are in lower case.
$headersContent = array_change_key_case($inputHeaders, CASE_LOWER);
$digest = 'SHA-256=' . base64_encode(hash('sha256', $body, true));
$headersToSign = [];
$headersContent = array_change_key_case($inputHeaders, \CASE_LOWER);
$digest = 'SHA-256=' . base64_encode(hash('sha256', $body, true));
$headersToSign = [];
foreach (explode(' ', $signatureData['headers']) as $h) {
if ($h == '(request-target)') {
$headersToSign[$h] = 'post ' . $path;
} elseif ($h == 'digest') {
$headersToSign[$h] = $digest;
} elseif (array_key_exists($h, $headersContent)) {
} elseif (\array_key_exists($h, $headersContent)) {
$headersToSign[$h] = $headersContent[$h];
}
}
$signingString = self::_headersToSigningString($headersToSign);
$verified = openssl_verify($signingString, base64_decode($signatureData['signature']), $publicKey, OPENSSL_ALGO_SHA256);
$verified = openssl_verify($signingString, base64_decode($signatureData['signature']), $publicKey, \OPENSSL_ALGO_SHA256);
return [$verified, $signingString];
}

View File

@ -1,6 +1,6 @@
<?php
declare(strict_types=1);
declare(strict_types = 1);
// {{{ License
// This file is part of GNU social - https://www.gnu.org/software/social
@ -24,6 +24,7 @@ declare(strict_types=1);
*
* @package GNUsocial
* @category ActivityPub
*
* @author Diogo Peralta Cordeiro <@diogo.site>
* @copyright 2021 Free Software Foundation, Inc http://www.fsf.org
* @license https://www.gnu.org/licenses/agpl.html GNU AGPL v3 or later
@ -53,29 +54,27 @@ abstract class Model
/**
* Create a Type from an ActivityStreams 2.0 JSON string
*
* @param string|array $data
* @return Type\AbstractObject
* @throws Exception
*/
public static function jsonToType(string|array $data): Type\AbstractObject
{
if (is_string($data)) {
if (\is_string($data)) {
$attributes = json_decode($data, true);
if (json_last_error() !== JSON_ERROR_NONE
|| !is_array($attributes)
if (json_last_error() !== \JSON_ERROR_NONE
|| !\is_array($attributes)
) {
throw new Exception(
sprintf(
"An error occurred during the JSON decoding.\n '%s'",
$data
)
$data,
),
);
}
} else {
$attributes = $data;
}
if (!array_key_exists('type', $attributes)) {
if (!\array_key_exists('type', $attributes)) {
throw new InvalidArgumentException('Missing "type" attribute in $data: ' . var_export($data, true));
}
unset($data);
@ -83,13 +82,13 @@ abstract class Model
try {
$type = TypeResolver::getClass($attributes['type']);
} catch (Exception $e) {
$message = json_encode($attributes, JSON_PRETTY_PRINT);
$message = json_encode($attributes, \JSON_PRETTY_PRINT);
throw new Exception(
$e->getMessage() . "\n$message"
$e->getMessage() . "\n{$message}",
);
}
if (is_string($type)) {
if (\is_string($type)) {
$type = new $type();
}
@ -112,22 +111,17 @@ abstract class Model
/**
* Create an Entity from an ActivityStreams 2.0 JSON string
*
* @param string|Type\AbstractObject $json
* @param array $options
* @return Entity
*/
abstract public static function fromJson(string|Type\AbstractObject $json, array $options = []): Entity;
/**
* Get a JSON
*
* @param mixed $object
* @param ?int $options PHP JSON options
* @return string
* @param ?int $options PHP JSON options
*
* @throws ClientException
*/
public static function toJson(mixed $object, int $options = null): string
public static function toJson(mixed $object, ?int $options = null): string
{
switch ($object::class) {
case 'App\Entity\Activity':
@ -140,4 +134,4 @@ abstract class Model
return $type->toJson($options);
}
}
}
}

View File

@ -1,6 +1,6 @@
<?php
declare(strict_types=1);
declare(strict_types = 1);
// {{{ License
// This file is part of GNU social - https://www.gnu.org/software/social
@ -24,6 +24,7 @@ declare(strict_types=1);
*
* @package GNUsocial
* @category ActivityPub
*
* @author Diogo Peralta Cordeiro <@diogo.site>
* @copyright 2021 Free Software Foundation, Inc http://www.fsf.org
* @license https://www.gnu.org/licenses/agpl.html GNU AGPL v3 or later
@ -63,29 +64,26 @@ class Activity extends Model
* Create an Entity from an ActivityStreams 2.0 JSON string
* This will persist new GSActivities, GSObjects, and APActivity
*
* @param string|AbstractObject $json
* @param array $options
* @return ActivitypubActivity
* @throws NoSuchActorException
* @throws ClientExceptionInterface
* @throws NoSuchActorException
* @throws RedirectionExceptionInterface
* @throws ServerExceptionInterface
* @throws TransportExceptionInterface
*/
public static function fromJson(string|AbstractObject $json, array $options = []): ActivitypubActivity
{
$type_activity = is_string($json) ? self::jsonToType($json) : $json;
$type_activity = \is_string($json) ? self::jsonToType($json) : $json;
// Ditch known activities
$ap_act = ActivitypubActivity::getByPK(['activity_uri' => $type_activity->get('id')]);
if (!is_null($ap_act)) {
if (!\is_null($ap_act)) {
return $ap_act;
}
// Find Actor and Object
$actor = ActivityPub::getActorByUri($type_activity->get('actor'));
$actor = ActivityPub::getActorByUri($type_activity->get('actor'));
$type_object = $type_activity->get('object');
if (is_string($type_object)) { // Retrieve it
if (\is_string($type_object)) { // Retrieve it
$type_object = ActivityPub::getObjectByUri($type_object, try_online: true);
} else { // Encapsulated, if we have it locally, prefer it
$type_object = ActivityPub::getObjectByUri($type_object->get('id'), try_online: false) ?? $type_object;
@ -118,20 +116,20 @@ class Activity extends Model
}
// Store Activity
$act = GSActivity::create([
'actor_id' => $actor->getId(),
'verb' => 'create',
'actor_id' => $actor->getId(),
'verb' => 'create',
'object_type' => 'note',
'object_id' => $note->getId(),
'created' => new DateTime($type_activity->get('published') ?? 'now'),
'source' => 'ActivityPub',
'object_id' => $note->getId(),
'created' => new DateTime($type_activity->get('published') ?? 'now'),
'source' => 'ActivityPub',
]);
DB::persist($act);
// Store ActivityPub Activity
$ap_act = ActivitypubActivity::create([
'activity_id' => $act->getId(),
'activity_id' => $act->getId(),
'activity_uri' => $type_activity->get('id'),
'created' => new DateTime($type_activity->get('published') ?? 'now'),
'modified' => new DateTime(),
'created' => new DateTime($type_activity->get('published') ?? 'now'),
'modified' => new DateTime(),
]);
DB::persist($ap_act);
}
@ -141,9 +139,6 @@ class Activity extends Model
/**
* Get a JSON
*
* @param mixed $object
* @param int|null $options
* @return string
* @throws ClientException
*/
public static function toJson(mixed $object, ?int $options = null): string
@ -151,24 +146,24 @@ class Activity extends Model
if ($object::class !== 'App\Entity\Activity') {
throw new InvalidArgumentException('First argument type is Activity');
}
$gs_verb_to_activity_stream_two_verb = null;
if (Event::handle('GSVerbToActivityStreamsTwoActivityType', [($verb = $object->getVerb()), &$gs_verb_to_activity_stream_two_verb]) === Event::next) {
$gs_verb_to_activity_stream_two_verb = match ($verb) {
'create' => 'Create',
'undo' => 'Undo',
default => throw new ClientException('Invalid verb'),
};
}
$gs_verb_to_activity_stream_two_verb = null;
if (Event::handle('GSVerbToActivityStreamsTwoActivityType', [($verb = $object->getVerb()), &$gs_verb_to_activity_stream_two_verb]) === Event::next) {
$gs_verb_to_activity_stream_two_verb = match ($verb) {
'create' => 'Create',
'undo' => 'Undo',
default => throw new ClientException('Invalid verb'),
};
}
$attr = [
'type' => $gs_verb_to_activity_stream_two_verb,
'@context' => 'https://www.w3.org/ns/activitystreams',
'id' => Router::url('activity_view', ['id' => $object->getId()], Router::ABSOLUTE_URL),
'type' => $gs_verb_to_activity_stream_two_verb,
'@context' => 'https://www.w3.org/ns/activitystreams',
'id' => Router::url('activity_view', ['id' => $object->getId()], Router::ABSOLUTE_URL),
'published' => $object->getCreated()->format(DateTimeInterface::RFC3339),
'actor' => $object->getActor()->getUri(Router::ABSOLUTE_URL),
'to' => ['https://www.w3.org/ns/activitystreams#Public'], // TODO: implement proper scope address
'cc' => ['https://www.w3.org/ns/activitystreams#Public'],
'actor' => $object->getActor()->getUri(Router::ABSOLUTE_URL),
'to' => ['https://www.w3.org/ns/activitystreams#Public'], // TODO: implement proper scope address
'cc' => ['https://www.w3.org/ns/activitystreams#Public'],
];
$attr['object'] = ($attr['type'] === 'Create') ? self::jsonToType(Model::toJson($object->getObject())) : ActivityPub::getUriByObject($object->getObject());

View File

@ -1,6 +1,6 @@
<?php
declare(strict_types=1);
declare(strict_types = 1);
// {{{ License
// This file is part of GNU social - https://www.gnu.org/software/social
@ -24,6 +24,7 @@ declare(strict_types=1);
*
* @package GNUsocial
* @category ActivityPub
*
* @author Diogo Peralta Cordeiro <@diogo.site>
* @copyright 2021 Free Software Foundation, Inc http://www.fsf.org
* @license https://www.gnu.org/licenses/agpl.html GNU AGPL v3 or later
@ -60,29 +61,25 @@ use Plugin\ActivityPub\Util\Model;
*/
class Actor extends Model
{
/**
* Create an Entity from an ActivityStreams 2.0 JSON string
* This will persist a new GSActor, ActivityPubRSA, and ActivityPubActor
*
* @param string|AbstractObject $json
* @param array $options
* @return ActivitypubActor
* @throws Exception
*/
public static function fromJson(string|AbstractObject $json, array $options = []): ActivitypubActor
{
$person = is_string($json) ? self::jsonToType($json) : $json;
$person = \is_string($json) ? self::jsonToType($json) : $json;
// Actor
$actor_map = [
'nickname' => $person->get('preferredUsername'),
'fullname' => !empty($person->get('name')) ? $person->get('name') : null,
'created' => new DateTime($person->get('published') ?? 'now'),
'bio' => $person->get('summary'),
'created' => new DateTime($person->get('published') ?? 'now'),
'bio' => $person->get('summary'),
'is_local' => false,
'type' => GSActor::PERSON,
'roles' => UserRoles::USER,
'type' => GSActor::PERSON,
'roles' => UserRoles::USER,
'modified' => new DateTime(),
];
@ -99,11 +96,11 @@ class Actor extends Model
// ActivityPub Actor
$ap_actor = ActivitypubActor::create([
'inbox_uri' => $person->get('inbox'),
'inbox_uri' => $person->get('inbox'),
'inbox_shared_uri' => ($person->has('endpoints') && isset($person->get('endpoints')['sharedInbox'])) ? $person->get('endpoints')['sharedInbox'] : null,
'uri' => $person->get('id'),
'actor_id' => $actor->getId(),
'url' => $person->get('url') ?? null,
'uri' => $person->get('id'),
'actor_id' => $actor->getId(),
'url' => $person->get('url') ?? null,
], $options['objects']['ActivitypubActor'] ?? null);
if (!isset($options['objects']['ActivitypubActor'])) {
@ -112,7 +109,7 @@ class Actor extends Model
// Public Key
$apRSA = ActivitypubRsa::create([
'actor_id' => $actor->getID(),
'actor_id' => $actor->getID(),
'public_key' => ($person->has('publicKey') && isset($person->get('publicKey')['publicKeyPem'])) ? $person->get('publicKey')['publicKeyPem'] : null,
], $options['objects']['ActivitypubRsa'] ?? null);
@ -125,8 +122,8 @@ class Actor extends Model
try {
// Retrieve media
$get_response = HTTPClient::get($person->get('icon')->get('url'));
$media = $get_response->getContent();
$mimetype = $get_response->getHeaders()['content-type'][0] ?? null;
$media = $get_response->getContent();
$mimetype = $get_response->getHeaders()['content-type'][0] ?? null;
unset($get_response);
// Only handle if it is an image
@ -168,9 +165,8 @@ class Actor extends Model
/**
* Get a JSON
*
* @param mixed $object
* @param int|null $options PHP JSON options
* @return string
* @param null|int $options PHP JSON options
*
* @throws ServerException
*/
public static function toJson(mixed $object, ?int $options = null): string
@ -178,41 +174,41 @@ class Actor extends Model
if ($object::class !== 'App\Entity\Actor') {
throw new InvalidArgumentException('First argument type is Actor');
}
$rsa = ActivitypubRsa::getByActor($object);
$rsa = ActivitypubRsa::getByActor($object);
$public_key = $rsa->getPublicKey();
$uri = null;
$attr = [
'@context' => 'https://www.w3.org/ns/activitystreams',
'type' => 'Person',
'id' => $object->getUri(Router::ABSOLUTE_URL),
'inbox' => Router::url('activitypub_actor_inbox', ['gsactor_id' => $object->getId()], Router::ABSOLUTE_URL),
'outbox' => Router::url('activitypub_actor_outbox', ['gsactor_id' => $object->getId()], Router::ABSOLUTE_URL),
$uri = null;
$attr = [
'@context' => 'https://www.w3.org/ns/activitystreams',
'type' => 'Person',
'id' => $object->getUri(Router::ABSOLUTE_URL),
'inbox' => Router::url('activitypub_actor_inbox', ['gsactor_id' => $object->getId()], Router::ABSOLUTE_URL),
'outbox' => Router::url('activitypub_actor_outbox', ['gsactor_id' => $object->getId()], Router::ABSOLUTE_URL),
'following' => Router::url('actor_subscriptions_id', ['id' => $object->getId()], Router::ABSOLUTE_URL),
'followers' => Router::url('actor_subscribers_id', ['id' => $object->getId()], Router::ABSOLUTE_URL),
'liked' => Router::url('favourites_view_by_actor_id', ['id' => $object->getId()], Router::ABSOLUTE_URL),
'liked' => Router::url('favourites_view_by_actor_id', ['id' => $object->getId()], Router::ABSOLUTE_URL),
//'streams' =>
'preferredUsername' => $object->getNickname(),
'publicKey' => [
'id' => $uri . "#public-key",
'owner' => $uri,
'publicKeyPem' => $public_key
'publicKey' => [
'id' => $uri . '#public-key',
'owner' => $uri,
'publicKeyPem' => $public_key,
],
'name' => $object->getFullname(),
'location' => $object->getLocation(),
'name' => $object->getFullname(),
'location' => $object->getLocation(),
'published' => $object->getCreated()->format(DateTimeInterface::RFC3339),
'summary' => $object->getBio(),
'summary' => $object->getBio(),
//'tag' => $object->getSelfTags(),
'updated' => $object->getModified()->format(DateTimeInterface::RFC3339),
'url' => $object->getUrl(Router::ABSOLUTE_URL),
'url' => $object->getUrl(Router::ABSOLUTE_URL),
];
// Avatar
try {
$avatar = Avatar::getAvatar($object->getId());
$avatar = Avatar::getAvatar($object->getId());
$attr['icon'] = $attr['image'] = [
'type' => 'Image',
'type' => 'Image',
'mediaType' => $avatar->getAttachment()->getMimetype(),
'url' => $avatar->getUrl(type: Router::ABSOLUTE_URL),
'url' => $avatar->getUrl(type: Router::ABSOLUTE_URL),
];
} catch (Exception) {
// No icon for this actor
@ -222,4 +218,4 @@ class Actor extends Model
Event::handle('ActivityPubAddActivityStreamsTwoData', [$type->get('type'), &$type]);
return $type->toJson($options);
}
}
}

View File

@ -39,11 +39,10 @@ use App\Core\DB\DB;
use App\Core\Event;
use App\Core\GSFile;
use App\Core\HTTPClient;
use App\Core\VisibilityScope;
use Component\Language\Entity\Language;
use function App\Core\I18n\_m;
use App\Core\Log;
use App\Core\Router\Router;
use App\Core\VisibilityScope;
use App\Entity\Note as GSNote;
use App\Entity\NoteTag;
use App\Util\Common;
@ -56,11 +55,13 @@ use App\Util\TemporaryFile;
use Component\Attachment\Entity\ActorToAttachment;
use Component\Attachment\Entity\AttachmentToNote;
use Component\Conversation\Conversation;
use Component\Language\Entity\Language;
use Component\Tag\Tag;
use DateTime;
use DateTimeInterface;
use Exception;
use InvalidArgumentException;
use const PHP_URL_HOST;
use Plugin\ActivityPub\ActivityPub;
use Plugin\ActivityPub\Entity\ActivitypubObject;
use Plugin\ActivityPub\Util\Model;
@ -68,10 +69,6 @@ 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 array_key_exists;
use function is_null;
use function is_string;
use const PHP_URL_HOST;
/**
* This class handles translation between JSON and GSNotes
@ -98,7 +95,7 @@ class Note extends Model
{
$handleInReplyTo = function (AbstractObject|string $type_note): ?int {
try {
$parent_note = is_null($type_note->get('inReplyTo')) ? null : ActivityPub::getObjectByUri($type_note->get('inReplyTo'), try_online: true);
$parent_note = \is_null($type_note->get('inReplyTo')) ? null : ActivityPub::getObjectByUri($type_note->get('inReplyTo'), try_online: true);
if ($parent_note instanceof GSNote) {
return $parent_note->getId();
} elseif ($parent_note instanceof Type\AbstractObject && $parent_note->get('type') === 'Note') {
@ -116,13 +113,13 @@ class Note extends Model
};
$source = $options['source'] ?? 'ActivityPub';
$type_note = is_string($json) ? self::jsonToType($json) : $json;
$type_note = \is_string($json) ? self::jsonToType($json) : $json;
$actor = null;
$actor_id = null;
if ($json instanceof AbstractObject
&& array_key_exists('test_authority', $options)
&& \array_key_exists('test_authority', $options)
&& $options['test_authority']
&& array_key_exists('actor_uri', $options)
&& \array_key_exists('actor_uri', $options)
) {
$actor_uri = $options['actor_uri'];
if ($actor_uri !== $type_note->get('attributedTo')) {
@ -135,7 +132,7 @@ class Note extends Model
}
}
if (is_null($actor_id)) {
if (\is_null($actor_id)) {
$actor = ActivityPub::getActorByUri($type_note->get('attributedTo'));
$actor_id = $actor->getId();
}
@ -164,14 +161,14 @@ class Note extends Model
]);
}
if (!is_null($map['language_id'])) {
if (!\is_null($map['language_id'])) {
$map['language_id'] = Language::getByLocale($map['language_id'])->getId();
} else {
$map['language_id'] = null;
}
// Scope
if (in_array('https://www.w3.org/ns/activitystreams#Public', $type_note->get('to'))) {
if (\in_array('https://www.w3.org/ns/activitystreams#Public', $type_note->get('to'))) {
// Public: Visible for all, shown in public feeds
$map['scope'] = VisibilityScope::PUBLIC;
} elseif (\in_array('https://www.w3.org/ns/activitystreams#Public', $type_note->get('cc'))) {
@ -258,7 +255,7 @@ class Note extends Model
case 'Hashtag':
$match = ltrim($ap_tag->get('name'), '#');
$tag = Tag::ensureValid($match);
$canonical_tag = $ap_tag->get('canonical') ?? Tag::canonicalTag($tag, is_null($lang_id = $obj->getLanguageId()) ? null : Language::getById($lang_id)->getLocale());
$canonical_tag = $ap_tag->get('canonical') ?? Tag::canonicalTag($tag, \is_null($lang_id = $obj->getLanguageId()) ? null : Language::getById($lang_id)->getLocale());
DB::persist(NoteTag::create([
'tag' => $tag,
'canonical' => $canonical_tag,
@ -323,7 +320,7 @@ class Note extends Model
'content' => $object->getRendered(),
'attachment' => [],
'tag' => [],
'inReplyTo' => is_null($object->getReplyTo()) ? null : ActivityPub::getUriByObject(GSNote::getById($object->getReplyTo())),
'inReplyTo' => \is_null($object->getReplyTo()) ? null : ActivityPub::getUriByObject(GSNote::getById($object->getReplyTo())),
'inConversation' => $object->getConversationUri(),
'directMessage' => $object->getScope() === VisibilityScope::MESSAGE,
];

View File

@ -1,6 +1,6 @@
<?php
declare(strict_types=1);
declare(strict_types = 1);
// {{{ License
// This file is part of GNU social - https://www.gnu.org/software/social
@ -24,6 +24,7 @@ declare(strict_types=1);
*
* @package GNUsocial
* @category ActivityPub
*
* @author Diogo Peralta Cordeiro <@diogo.site>
* @copyright 2021 Free Software Foundation, Inc http://www.fsf.org
* @license https://www.gnu.org/licenses/agpl.html GNU AGPL v3 or later
@ -43,8 +44,7 @@ abstract class ModelResponse
* Provides a response in application/ld+json for ActivityStreams 2.0 Types
*
* @param mixed $object (Entity)
* @param int $status The response status code
* @return TypeResponse
* @param int $status The response status code
*/
public static function handle(mixed $object, int $status = 200): TypeResponse
{

View File

@ -1,6 +1,6 @@
<?php
declare(strict_types=1);
declare(strict_types = 1);
// {{{ License
// This file is part of GNU social - https://www.gnu.org/software/social
@ -24,6 +24,7 @@ declare(strict_types=1);
*
* @package GNUsocial
* @category ActivityPub
*
* @author Diogo Peralta Cordeiro <@diogo.site>
* @copyright 2021 Free Software Foundation, Inc http://www.fsf.org
* @license https://www.gnu.org/licenses/agpl.html GNU AGPL v3 or later

View File

@ -1,6 +1,6 @@
<?php
declare(strict_types=1);
declare(strict_types = 1);
// {{{ License
// This file is part of GNU social - https://www.gnu.org/software/social
@ -24,6 +24,7 @@ declare(strict_types=1);
*
* @package GNUsocial
* @category ActivityPub
*
* @author Diogo Peralta Cordeiro <@diogo.site>
* @copyright 2021 Free Software Foundation, Inc http://www.fsf.org
* @license https://www.gnu.org/licenses/agpl.html GNU AGPL v3 or later
@ -47,9 +48,8 @@ abstract class ActivityResponse
/**
* Provides a response in application/ld+json to GSActivity
*
* @param GSActivity $activity
* @param int $status The response status code
* @return TypeResponse
*
* @throws ClientException
*/
public static function handle(GSActivity $activity, int $status = 200): TypeResponse

View File

@ -1,6 +1,6 @@
<?php
declare(strict_types=1);
declare(strict_types = 1);
// {{{ License
// This file is part of GNU social - https://www.gnu.org/software/social
@ -24,6 +24,7 @@ declare(strict_types=1);
*
* @package GNUsocial
* @category ActivityPub
*
* @author Diogo Peralta Cordeiro <@diogo.site>
* @copyright 2021 Free Software Foundation, Inc http://www.fsf.org
* @license https://www.gnu.org/licenses/agpl.html GNU AGPL v3 or later
@ -47,9 +48,8 @@ abstract class ActorResponse
/**
* Provides a response in application/ld+json to GSActors
*
* @param GSActor $gsactor
* @param int $status The response status code
* @return TypeResponse
*
* @throws ClientException
*/
public static function handle(GSActor $gsactor, int $status = 200): TypeResponse

View File

@ -1,6 +1,6 @@
<?php
declare(strict_types=1);
declare(strict_types = 1);
// {{{ License
// This file is part of GNU social - https://www.gnu.org/software/social
@ -24,6 +24,7 @@ declare(strict_types=1);
*
* @package GNUsocial
* @category ActivityPub
*
* @author Diogo Peralta Cordeiro <@diogo.site>
* @copyright 2021 Free Software Foundation, Inc http://www.fsf.org
* @license https://www.gnu.org/licenses/agpl.html GNU AGPL v3 or later
@ -46,9 +47,7 @@ abstract class NoteResponse
/**
* Provides a response in application/ld+json to GSNotes
*
* @param GSNote $note
* @param int $status The response status code
* @return TypeResponse
*/
public static function handle(GSNote $note, int $status = 200): TypeResponse
{

View File

@ -1,6 +1,6 @@
<?php
declare(strict_types=1);
declare(strict_types = 1);
// {{{ License
// This file is part of GNU social - https://www.gnu.org/software/social
@ -24,6 +24,7 @@ declare(strict_types=1);
*
* @package GNUsocial
* @category ActivityPub
*
* @author Diogo Peralta Cordeiro <@diogo.site>
* @copyright 2021 Free Software Foundation, Inc http://www.fsf.org
* @license https://www.gnu.org/licenses/agpl.html GNU AGPL v3 or later
@ -45,13 +46,13 @@ class TypeResponse extends JsonResponse
/**
* Provides a response in application/ld+json for ActivityStreams 2.0 Types
*
* @param string|AbstractObject|null $json
* @param int $status The response status code
* @param null|AbstractObject|string $json
* @param int $status The response status code
*/
public function __construct(string|AbstractObject|null $json = null, int $status = 202)
{
parent::__construct(
data: is_object($json) ? $json->toJson() : $json,
data: \is_object($json) ? $json->toJson() : $json,
status: $status,
headers: ['content-type' => 'application/ld+json; profile="https://www.w3.org/ns/activitystreams"'],
json: true,

View File

@ -1,6 +1,6 @@
<?php
declare(strict_types=1);
declare(strict_types = 1);
// {{{ License
// This file is part of GNU social - https://www.gnu.org/software/social
@ -24,6 +24,7 @@ declare(strict_types=1);
*
* @package GNUsocial
* @category ActivityPub
*
* @author Diogo Peralta Cordeiro <@diogo.site>
* @copyright 2021 Free Software Foundation, Inc http://www.fsf.org
* @license https://www.gnu.org/licenses/agpl.html GNU AGPL v3 or later
@ -49,8 +50,8 @@ class contentLangModelValidator extends ModelValidator
* Validate manuallyApprovesFollowers value
*
* @param string $value
* @param mixed $container A Note
* @return bool
* @param mixed $container A Note
*
* @throws Exception
*/
public function validate($value, $container): bool

View File

@ -1,6 +1,6 @@
<?php
declare(strict_types=1);
declare(strict_types = 1);
// {{{ License
// This file is part of GNU social - https://www.gnu.org/software/social
@ -24,6 +24,7 @@ declare(strict_types=1);
*
* @package GNUsocial
* @category ActivityPub
*
* @author Diogo Peralta Cordeiro <@diogo.site>
* @copyright 2021 Free Software Foundation, Inc http://www.fsf.org
* @license https://www.gnu.org/licenses/agpl.html GNU AGPL v3 or later
@ -49,8 +50,8 @@ class manuallyApprovesFollowersModelValidator extends ModelValidator
* Validate manuallyApprovesFollowers value
*
* @param string $value
* @param mixed $container A Person
* @return bool
* @param mixed $container A Person
*
* @throws Exception
*/
public function validate($value, $container): bool

View File

@ -23,16 +23,16 @@ declare(strict_types = 1);
namespace Plugin\AttachmentCollections\Controller;
use App\Core\Form;
use App\Core\DB\DB;
use App\Util\Common;
use App\Core\Router\Router;
use App\Core\Form;
use function App\Core\I18n\_m;
use App\Core\Router\Router;
use App\Util\Common;
use Component\Feed\Util\FeedController;
use Symfony\Component\HttpFoundation\Request;
use Plugin\AttachmentCollections\Entity\Collection;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\HttpFoundation\Request;
class Controller extends FeedController
{
@ -47,16 +47,18 @@ class Controller extends FeedController
}
/**
* Generate Collections page
*
* @param int $id actor id
* @param ?string $nickname actor nickname
* @return array twig template options
*
* @return array twig template options
*/
public function collectionsView(Request $request, int $id, ?string $nickname): array
{
$collections = DB::dql(
'select collection from Plugin\AttachmentCollections\Entity\Collection collection '
. 'where collection.actor_id = :id',
['id' => $id]
['id' => $id],
);
// create collection form
$create = null;
@ -64,9 +66,9 @@ class Controller extends FeedController
$create = Form::create([
['name', TextType::class, [
'label' => _m('Create collection'),
'attr' => [
'attr' => [
'placeholder' => _m('Name'),
'required' => 'required'
'required' => 'required',
],
'data' => '',
]],
@ -80,7 +82,7 @@ class Controller extends FeedController
$create->handleRequest($request);
if ($create->isSubmitted() && $create->isValid()) {
DB::persist(Collection::create([
'name' => $create->getData()['name'],
'name' => $create->getData()['name'],
'actor_id' => $id,
]));
DB::flush();
@ -94,15 +96,14 @@ class Controller extends FeedController
// Instead, I'm using an anonymous class to encapsulate
// the functions and passing how the class to the template.
// It's suggested at https://stackoverflow.com/a/50364502.
$fn = new class ($id, $nickname, $request)
{
$fn = new class($id, $nickname, $request) {
private $id;
private $nick;
private $request;
public function __construct($id, $nickname, $request)
{
$this->id = $id;
$this->nick = $nickname;
$this->id = $id;
$this->nick = $nickname;
$this->request = $request;
}
// there's already a injected function called path,
@ -114,12 +115,12 @@ class Controller extends FeedController
if (\is_null($this->nick)) {
return Router::url(
'collection_notes_view_by_actor_id',
['id' => $this->id, 'cid' => $cid]
['id' => $this->id, 'cid' => $cid],
);
}
return Router::url(
'collection_notes_view_by_nickname',
['nickname' => $this->nick, 'cid' => $cid]
['nickname' => $this->nick, 'cid' => $cid],
);
}
// There are many collections in this page and we need two
@ -133,11 +134,11 @@ class Controller extends FeedController
['name', TextType::class, [
'attr' => [
'placeholder' => 'New name',
'required' => 'required'
'required' => 'required',
],
'data' => '',
]],
['update_'.$collection->getId(), SubmitType::class, [
['update_' . $collection->getId(), SubmitType::class, [
'label' => _m('Save'),
'attr' => [
'title' => _m('Save'),
@ -156,7 +157,7 @@ class Controller extends FeedController
public function rmForm($collection)
{
$rm = Form::create([
['remove_'.$collection->getId(), SubmitType::class, [
['remove_' . $collection->getId(), SubmitType::class, [
'label' => _m('Delete collection'),
'attr' => [
'title' => _m('Delete collection'),
@ -190,12 +191,12 @@ class Controller extends FeedController
public function collectionNotesByActorId(Request $request, int $id, int $cid): array
{
$collection = DB::findOneBy('attachment_collection', ['id' => $cid]);
$attchs = DB::dql(
$attchs = DB::dql(
'select attch from attachment_album_entry entry '
. 'left join Component\Attachment\Entity\Attachment attch '
. 'with entry.attachment_id = attch.id '
. 'where entry.collection_id = :cid',
['cid' => $cid]
['cid' => $cid],
);
return [
'_template' => 'AttachmentCollections/collection.html.twig',

View File

@ -1,7 +1,11 @@
<?php
declare(strict_types = 1);
namespace Plugin\AttachmentCollections\Entity;
use App\Core\Entity;
class Collection extends Entity
{
// These tags are meant to be literally included and will be populated with the appropriate fields, setters and getters by `bin/generate_entity_fields`
@ -44,22 +48,19 @@ class Collection extends Entity
return $this->actor_id;
}
// @codeCoverageIgnoreEnd
// }}} Autocode
public static function schemaDef()
{
return [
'name' => 'attachment_collection',
'fields' => [
'id' => ['type' => 'serial', 'not null' => true, 'description' => 'unique identifier'],
'name' => ['type' => 'varchar', 'length' => 255, 'description' => 'collection\'s name'],
'name' => ['type' => 'varchar', 'length' => 255, 'description' => 'collection\'s name'],
'actor_id' => ['type' => 'int', 'foreign key' => true, 'target' => 'Actor.id', 'multiplicity' => 'one to many', 'not null' => true, 'description' => 'foreign key to actor table'],
],
'primary key' => ['id'],
'primary key' => ['id'],
];
}
}

View File

@ -1,7 +1,11 @@
<?php
declare(strict_types = 1);
namespace Plugin\AttachmentCollections\Entity;
use App\Core\Entity;
class CollectionEntry extends Entity
{
// These tags are meant to be literally included and will be populated with the appropriate fields, setters and getters by `bin/generate_entity_fields`
@ -44,11 +48,9 @@ class CollectionEntry extends Entity
return $this->collection_id;
}
// @codeCoverageIgnoreEnd
// }}} Autocode
public static function schemaDef()
{
return [
@ -62,4 +64,3 @@ class CollectionEntry extends Entity
];
}
}

View File

@ -1,6 +1,6 @@
<?php
declare(strict_types=1);
declare(strict_types = 1);
// {{{ License
// This file is part of GNU social - https://www.gnu.org/software/social
//
@ -34,12 +34,12 @@ namespace Plugin\AudioEncoder;
use App\Core\Event;
use App\Core\GSFile;
use function App\Core\I18n\_m;
use App\Core\Modules\Plugin;
use App\Util\Exception\ServerException;
use App\Util\Formatting;
use FFMpeg\FFProbe as ffprobe;
use SplFileInfo;
use function App\Core\I18n\_m;
class AudioEncoder extends Plugin
{
@ -66,7 +66,7 @@ class AudioEncoder extends Plugin
* Adds duration metadata to audios
*
* @param null|string $mimetype in/out
* @param null|int $width out audio duration
* @param null|int $width out audio duration
*
* @return bool true if metadata filled
*/
@ -75,14 +75,14 @@ class AudioEncoder extends Plugin
// Create FFProbe instance
// Need to explicitly tell the drivers' location, or it won't find them
$ffprobe = ffprobe::create([
'ffmpeg.binaries' => exec('which ffmpeg'),
'ffmpeg.binaries' => exec('which ffmpeg'),
'ffprobe.binaries' => exec('which ffprobe'),
]);
$metadata = $ffprobe->streams($file->getRealPath()) // extracts streams informations
->audios() // filters audios streams
->first(); // returns the first audio stream
$width = (int)ceil((float)$metadata->get('duration'));
->audios() // filters audios streams
->first(); // returns the first audio stream
$width = (int) ceil((float) $metadata->get('duration'));
return true;
}
@ -100,7 +100,7 @@ class AudioEncoder extends Plugin
'audioEncoder/audioEncoderView.html.twig',
[
'attachment' => $vars['attachment'],
'note' => $vars['note'],
'note' => $vars['note'],
],
);
return Event::stop;
@ -112,9 +112,9 @@ class AudioEncoder extends Plugin
public function onPluginVersion(array &$versions): bool
{
$versions[] = [
'name' => 'AudioEncoder',
'version' => self::version(),
'author' => 'Diogo Peralta Cordeiro',
'name' => 'AudioEncoder',
'version' => self::version(),
'author' => 'Diogo Peralta Cordeiro',
'rawdescription' => _m('Use PHP-FFMpeg for some more audio support.'),
];
return Event::next;

View File

@ -25,8 +25,8 @@ namespace Plugin\Cover\Entity;
use App\Core\DB\DB;
use App\Core\Entity;
use Component\Attachment\Entity\Attachment;
use App\Util\Common;
use Component\Attachment\Entity\Attachment;
use DateTimeInterface;
/**

View File

@ -187,8 +187,8 @@ class AttachmentEmbed extends Entity
$attr['has_attachment'] = false;
} elseif (!\is_null($thumbnail)) {
$attr['has_attachment'] = true;
$attr['width'] = $thumbnail->getWidth();
$attr['height'] = $thumbnail->getHeight();
$attr['width'] = $thumbnail->getWidth();
$attr['height'] = $thumbnail->getHeight();
}
return $attr;
}

View File

@ -55,7 +55,8 @@ class ImageEncoder extends Plugin
return '3.0.0';
}
public static function shouldHandle (string $mimetype): bool {
public static function shouldHandle(string $mimetype): bool
{
return GSFile::mimetypeMajor($mimetype) === 'image';
}

View File

@ -1,6 +1,6 @@
<?php
declare(strict_types=1);
declare(strict_types = 1);
// {{{ License
@ -26,6 +26,7 @@ namespace Plugin\Oomox\Controller;
use App\Core\Cache;
use App\Core\DB\DB;
use App\Core\Form;
use function App\Core\I18n\_m;
use App\Util\Common;
use App\Util\Exception\ClientException;
use App\Util\Exception\NoLoggedInUser;
@ -41,8 +42,6 @@ use Symfony\Component\Form\FormInterface;
use Symfony\Component\Form\SubmitButton;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use function App\Core\I18n\_m;
use function is_null;
/**
* Oomox controller
@ -64,67 +63,67 @@ class Oomox
*/
public function getOomoxForm(?EntityOomox $current_oomox_settings, bool $is_light): FormInterface
{
$theme = $is_light ? 'light' : 'dark';
$foreground = 'colour_foreground_' . $theme;
$theme = $is_light ? 'light' : 'dark';
$foreground = 'colour_foreground_' . $theme;
$background_hard = 'colour_background_hard_' . $theme;
$background_card = 'colour_background_card_' . $theme;
$border = 'colour_border_' . $theme;
$accent = 'colour_accent_' . $theme;
$reset = 'colour_reset_' . $theme;
$save = 'save_oomox_colours_' . $theme;
$border = 'colour_border_' . $theme;
$accent = 'colour_accent_' . $theme;
$reset = 'colour_reset_' . $theme;
$save = 'save_oomox_colours_' . $theme;
if (isset($current_oomox_settings)) {
if ($is_light) {
$current_foreground = $current_oomox_settings->getColourForegroundLight() ?: '#09090d';
$current_foreground = $current_oomox_settings->getColourForegroundLight() ?: '#09090d';
$current_background_hard = $current_oomox_settings->getColourBackgroundHardLight() ?: '#ebebeb';
$current_background_card = $current_oomox_settings->getColourBackgroundCardLight() ?: '#f0f0f0';
$current_border = $current_oomox_settings->getColourBorderLight() ?: '#d5d5d5';
$current_accent = $current_oomox_settings->getColourAccentLight() ?: '#a22430';
$current_border = $current_oomox_settings->getColourBorderLight() ?: '#d5d5d5';
$current_accent = $current_oomox_settings->getColourAccentLight() ?: '#a22430';
} else {
$current_foreground = $current_oomox_settings->getColourForegroundDark() ?: '#f0f6f6';
$current_foreground = $current_oomox_settings->getColourForegroundDark() ?: '#f0f6f6';
$current_background_hard = $current_oomox_settings->getColourBackgroundHardDark() ?: '#141216';
$current_background_card = $current_oomox_settings->getColourBackgroundCardDark() ?: '#131217';
$current_border = $current_oomox_settings->getColourBorderDark() ?: '#201f25';
$current_accent = $current_oomox_settings->getColourAccentDark() ?: '#5ddbcf';
$current_border = $current_oomox_settings->getColourBorderDark() ?: '#201f25';
$current_accent = $current_oomox_settings->getColourAccentDark() ?: '#5ddbcf';
}
} else {
$current_foreground = $is_light ? '#09090d' : '#f0f6f6';
$current_foreground = $is_light ? '#09090d' : '#f0f6f6';
$current_background_hard = $is_light ? '#ebebeb' : '#141216';
$current_background_card = $is_light ? '#f0f0f0' : '#131217';
$current_border = $is_light ? '#d5d5d5' : '#201f25';
$current_accent = $is_light ? '#a22430' : '#5ddbcf';
$current_border = $is_light ? '#d5d5d5' : '#201f25';
$current_accent = $is_light ? '#a22430' : '#5ddbcf';
}
return Form::create([
[$foreground, ColorType::class, [
'html5' => true,
'data' => $current_foreground,
'data' => $current_foreground,
'label' => _m('Foreground colour'),
'help' => _m('Choose the foreground colour'),],
'help' => _m('Choose the foreground colour'), ],
],
[$background_hard, ColorType::class, [
'html5' => true,
'data' => $current_background_hard,
'data' => $current_background_hard,
'label' => _m('Background colour'),
'help' => _m('Choose the background colour'),],
'help' => _m('Choose the background colour'), ],
],
[$background_card, ColorType::class, [
'html5' => true,
'data' => $current_background_card,
'data' => $current_background_card,
'label' => _m('Card background colour'),
'help' => _m('Choose the card background colour'),],
'help' => _m('Choose the card background colour'), ],
],
[$border, ColorType::class, [
'html5' => true,
'data' => $current_border,
'data' => $current_border,
'label' => _m('Border colour'),
'help' => _m('Choose the borders accents'),],
'help' => _m('Choose the borders accents'), ],
],
[$accent, ColorType::class, [
'html5' => true,
'data' => $current_accent,
'data' => $current_accent,
'label' => _m('Accent colour'),
'help' => _m('Choose the accent colour'),],
'help' => _m('Choose the accent colour'), ],
],
['hidden', HiddenType::class, []],
[$reset, SubmitType::class, ['label' => _m('Reset colours to default')]],
@ -141,11 +140,11 @@ class Oomox
*/
public static function oomoxSettingsLight(Request $request): array
{
$user = Common::ensureLoggedIn();
$user = Common::ensureLoggedIn();
$actor_id = $user->getId();
$current_oomox_settings = PluginOomox::getEntity($user);
$form_light = (new self)->getOomoxForm($current_oomox_settings, true);
$form_light = (new self)->getOomoxForm($current_oomox_settings, true);
$form_light->handleRequest($request);
if ($form_light->isSubmitted() && $form_light->isValid()) {
@ -156,15 +155,15 @@ class Oomox
$current_oomox_settings?->resetTheme(true);
}
} else {
$data = $form_light->getData();
$data = $form_light->getData();
$current_oomox_settings = EntityOomox::create(
[
'actor_id' => $actor_id,
'colour_foreground_light' => $data['colour_foreground_light'],
'actor_id' => $actor_id,
'colour_foreground_light' => $data['colour_foreground_light'],
'colour_background_hard_light' => $data['colour_background_hard_light'],
'colour_background_card_light' => $data['colour_background_card_light'],
'colour_border_light' => $data['colour_border_light'],
'colour_accent_light' => $data['colour_accent_light'],
'colour_border_light' => $data['colour_border_light'],
'colour_accent_light' => $data['colour_accent_light'],
],
);
}
@ -187,11 +186,11 @@ class Oomox
*/
public static function oomoxSettingsDark(Request $request): array
{
$user = Common::ensureLoggedIn();
$user = Common::ensureLoggedIn();
$actor_id = $user->getId();
$current_oomox_settings = PluginOomox::getEntity($user);
$form_dark = (new self)->getOomoxForm($current_oomox_settings, false);
$form_dark = (new self)->getOomoxForm($current_oomox_settings, false);
$form_dark->handleRequest($request);
if ($form_dark->isSubmitted() && $form_dark->isValid()) {
@ -200,15 +199,15 @@ class Oomox
if ($reset_button->isClicked()) {
$current_oomox_settings?->resetTheme(false);
} else {
$data = $form_dark->getData();
$data = $form_dark->getData();
$current_oomox_settings = EntityOomox::create(
[
'actor_id' => $actor_id,
'colour_foreground_dark' => $data['colour_foreground_dark'],
'actor_id' => $actor_id,
'colour_foreground_dark' => $data['colour_foreground_dark'],
'colour_background_hard_dark' => $data['colour_background_hard_dark'],
'colour_background_card_dark' => $data['colour_background_card_dark'],
'colour_border_dark' => $data['colour_border_dark'],
'colour_accent_dark' => $data['colour_accent_dark'],
'colour_border_dark' => $data['colour_border_dark'],
'colour_accent_dark' => $data['colour_accent_dark'],
],
);
}
@ -225,18 +224,16 @@ class Oomox
/**
* Renders the resulting CSS file from user options, serves that file as a response
*
* @return Response
* @throws ClientException
* @throws NoLoggedInUser
* @throws ServerException
*
* @throws ClientException
*/
public function oomoxCSS(): Response
{
$user = Common::ensureLoggedIn();
$oomox_table = PluginOomox::getEntity($user);
if (is_null($oomox_table)) {
if (\is_null($oomox_table)) {
throw new ClientException(_m('No custom colours defined', 404));
}

View File

@ -197,20 +197,20 @@ class Oomox extends Entity
return $this->modified;
}
public function resetTheme(bool $is_light) {
public function resetTheme(bool $is_light)
{
if ($is_light) {
$this->colour_background_hard_light = '#09090d';
$this->colour_background_card_light = '#ebebeb';
$this->colour_foreground_light = '#f0f0f0';
$this->colour_border_light = '#d5d5d5';
$this->colour_accent_light = '#a22430';
$this->colour_foreground_light = '#f0f0f0';
$this->colour_border_light = '#d5d5d5';
$this->colour_accent_light = '#a22430';
} else {
$this->colour_background_hard_dark = '#141216';
$this->colour_background_card_dark = '#131217';
$this->colour_foreground_dark = '#f0f6f6';
$this->colour_border_dark = '#201f25';
$this->colour_accent_dark = '#5ddbcf';
$this->colour_foreground_dark = '#f0f6f6';
$this->colour_border_dark = '#201f25';
$this->colour_accent_dark = '#5ddbcf';
}
}

View File

@ -29,13 +29,13 @@ use App\Core\Router\RouteLoader;
use App\Core\Router\Router;
use App\Entity\Activity;
use App\Entity\Actor;
use Component\Language\Entity\Language;
use App\Entity\Note;
use App\Util\Common;
use App\Util\Exception\DuplicateFoundException;
use App\Util\Exception\NotFoundException;
use App\Util\Exception\ServerException;
use App\Util\Formatting;
use Component\Language\Entity\Language;
use Component\Posting\Posting;
use DateTime;
use Plugin\RepeatNote\Entity\NoteRepeat;
@ -53,11 +53,11 @@ class RepeatNote extends NoteHandlerPlugin
if (!\is_null($repeat_entity)) {
return DB::findBy('activity', [
'actor_id' => $actor_id,
'verb' => 'repeat',
'object_type' => 'note',
'object_id' => $note->getId()
], order_by: ['created' => 'DESC'])[0];
'actor_id' => $actor_id,
'verb' => 'repeat',
'object_type' => 'note',
'object_id' => $note->getId(),
], order_by: ['created' => 'DESC'])[0];
}
// Create a new note with the same content as the original

View File

@ -31,12 +31,12 @@ use function App\Core\I18n\_m;
use App\Entity\Actor;
use App\Entity\ActorTag;
use App\Entity\ActorTagBlock;
use Component\Language\Entity\Language;
use App\Entity\Note;
use App\Entity\NoteTag;
use App\Entity\NoteTagBlock;
use App\Util\Common;
use App\Util\Exception\RedirectException;
use Component\Language\Entity\Language;
use Component\Tag\Tag;
use Functional as F;
use Plugin\TagBasedFiltering\TagBasedFiltering as TagFilerPlugin;

View File

@ -31,7 +31,7 @@ class TreeNotes extends Plugin
*/
public function onFormatNoteList(array $notes_in, ?array &$notes_out)
{
$roots = array_filter($notes_in, static fn (Note $note) => is_null($note->getReplyTo()));
$roots = array_filter($notes_in, static fn (Note $note) => \is_null($note->getReplyTo()));
$notes_out = $this->build_tree($roots, $notes_in);
}

View File

@ -151,7 +151,7 @@ abstract class Entity
public function getNotificationTargetIds(array $ids_already_known = [], ?int $sender_id = null, bool $include_additional = true): array
{
// Additional actors that should know about this
if (array_key_exists('additional', $ids_already_known)) {
if (\array_key_exists('additional', $ids_already_known)) {
return $ids_already_known['additional'];
}
return [];

View File

@ -44,7 +44,7 @@ class BugFoundException extends ServerException
{
parent::__construct($message, $code, $previous);
$frame = debug_backtrace(\DEBUG_BACKTRACE_IGNORE_ARGS, limit: 2)[1];
$file = mb_substr($frame['file'], \mb_strlen(INSTALLDIR) + 1);
$file = mb_substr($frame['file'], mb_strlen(INSTALLDIR) + 1);
Log::critical("{$log_message} in {$file}:{$frame['line']}");
}
}

View File

@ -21,7 +21,9 @@ declare(strict_types = 1);
namespace App\Util\Exception;
class FileNotAllowedException extends \InvalidArgumentException
use InvalidArgumentException;
class FileNotAllowedException extends InvalidArgumentException
{
public function __construct(string $mimetype)
{

View File

@ -1,5 +1,7 @@
<?php
declare(strict_types = 1);
// {{{ License
// This file is part of GNU social - https://www.gnu.org/software/social

View File

@ -6,8 +6,8 @@ namespace App\Util\Form;
use function App\Core\I18n\_m;
use App\Entity\Actor;
use Component\Language\Entity\Language;
use App\Util\Common;
use Component\Language\Entity\Language;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use Symfony\Component\Form\Extension\Core\Type\PasswordType;
use Symfony\Component\Form\Extension\Core\Type\RepeatedType;

View File

@ -263,7 +263,7 @@ abstract class Formatting
// php-intl is highly recommended...
if (!\function_exists('transliterator_transliterate')) {
$str = preg_replace('/[^\pL\pN]/u', '', $str);
$str = mb_convert_case($str, MB_CASE_LOWER, 'UTF-8');
$str = mb_convert_case($str, \MB_CASE_LOWER, 'UTF-8');
return mb_substr($str, 0, $length);
}
$str = transliterator_transliterate('Any-Latin;' // any charset to latin compatible

View File

@ -39,7 +39,7 @@ class Notification
public const NOTICE_BY_SUBSCRIBED = 1;
public const MENTION = 2;
public const REPLY = 3;
public const SUBSCRIPTION = 4;
public const SUBSCRIPTION = 4;
public const FAVORITE = 5;
public const NUDGE = 6;
public const DM = 7;

View File

@ -24,10 +24,10 @@ namespace App\Tests\Entity;
use App\Core\DB\DB;
use App\Core\Event;
use App\Core\GSFile;
use Component\Attachment\Entity\AttachmentToNote;
use App\Entity\Note;
use App\Util\GNUsocialTestCase;
use App\Util\TemporaryFile;
use Component\Attachment\Entity\AttachmentToNote;
use Jchook\AssertThrows\AssertThrows;
use SplFileInfo;
use Symfony\Component\HttpFoundation\File\File;

View File

@ -23,9 +23,9 @@ namespace App\Tests\Entity;
use App\Core\DB\DB;
use App\Core\Event;
use Component\Attachment\Entity\AttachmentThumbnail;
use App\Util\Exception\NotStoredLocallyException;
use App\Util\GNUsocialTestCase;
use Component\Attachment\Entity\AttachmentThumbnail;
use Functional as F;
use Jchook\AssertThrows\AssertThrows;
use SplFileInfo;