forked from GNUsocial/gnu-social
[PLUGIN][ActivityPub] Finish base ActivityStreams 2.0 interface
Instructions below To extend an Activity properties do: public function onActivityPubValidateActivityStreamsTwoData(string $type_name, array &$validators): bool { if ($type_name === '{Type}') { $validators['attribute'] = myValidator::class; } return Event::next; } The Validator should be of the form: use ActivityPhp\Type; use ActivityPhp\Type\Util; use Plugin\ActivityPub\Util\ModelValidator; class myValidator extends ModelValidator { /** * Validate Attribute's value * * @param mixed $value from JSON's attribute * @param mixed $container A {Type} * @return bool * @throws Exception */ public function validate($value, $container): bool { // Validate that container is a {Type} Util::subclassOf($container, Type\Extended\Object\{Type}::class, true); return {Validation Result}; To act on received activities do: public function onActivityPubNew{Type}(&$obj): bool { To add information to Activities being federated by ActivityPub do: public function ActivityPubAddActivityStreamsTwoData(string $type_name, &$type): bool { To implement an ActivityStreams 2.0 representation do: public function onActivityPubActivityStreamsTwoResponse(string $route, arrray $vars, ?TypeResponse &$response = null): bool { if ($route === '{Object route}') { $response = ModelResponse::handle($vars[{Object}]); return Event::stop; } return Event::next; }
This commit is contained in:
parent
044649c745
commit
778cb57d83
790
composer.lock
generated
790
composer.lock
generated
File diff suppressed because it is too large
Load Diff
@ -2,6 +2,33 @@
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
// {{{ License
|
||||
// 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
|
||||
// it under the terms of the GNU Affero General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// GNU social is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with GNU social. If not, see <http://www.gnu.org/licenses/>.
|
||||
// }}}
|
||||
|
||||
/**
|
||||
* ActivityPub implementation for GNU social
|
||||
*
|
||||
* @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
|
||||
*/
|
||||
|
||||
namespace Plugin\ActivityPub;
|
||||
|
||||
use App\Core\Event;
|
||||
@ -22,18 +49,30 @@ use Exception;
|
||||
use Plugin\ActivityPub\Controller\Inbox;
|
||||
use Plugin\ActivityPub\Entity\ActivitypubActor;
|
||||
use Plugin\ActivityPub\Util\HTTPSignature;
|
||||
use Plugin\ActivityPub\Util\Model\EntityToType\EntityToType;
|
||||
use Plugin\ActivityPub\Util\Model;
|
||||
use Plugin\ActivityPub\Util\Response\ActorResponse;
|
||||
use Plugin\ActivityPub\Util\Response\NoteResponse;
|
||||
use Plugin\ActivityPub\Util\Response\TypeResponse;
|
||||
use Plugin\ActivityPub\Util\Type;
|
||||
use Plugin\ActivityPub\Util\TypeResponse;
|
||||
use Plugin\ActivityPub\Util\Validator\contentLangModelValidator;
|
||||
use Plugin\ActivityPub\Util\Validator\manuallyApprovesFollowersModelValidator;
|
||||
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 Symfony\Contracts\HttpClient\ResponseInterface;
|
||||
use XML_XRD;
|
||||
use XML_XRD_Element_Link;
|
||||
use function count;
|
||||
use function Psy\debug;
|
||||
use function is_null;
|
||||
use const PHP_URL_HOST;
|
||||
use const PREG_SET_ORDER;
|
||||
|
||||
/**
|
||||
* Adds ActivityPub support to GNU social when enabled
|
||||
*
|
||||
* @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
|
||||
*/
|
||||
class ActivityPub extends Plugin
|
||||
{
|
||||
// ActivityStreams 2.0 Accept Headers
|
||||
@ -89,6 +128,14 @@ class ActivityPub extends Plugin
|
||||
return Event::next;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fill Actor->getUrl() calls with correct URL coming from ActivityPub
|
||||
*
|
||||
* @param Actor $actor
|
||||
* @param int $type
|
||||
* @param string|null $url
|
||||
* @return bool
|
||||
*/
|
||||
public function onStartGetActorUrl(Actor $actor, int $type, ?string &$url): bool
|
||||
{
|
||||
if (
|
||||
@ -106,12 +153,80 @@ class ActivityPub extends Plugin
|
||||
return Event::next;
|
||||
}
|
||||
|
||||
/**
|
||||
* Overload core endpoints to make resources available in ActivityStreams 2.0
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
public function onControllerResponseInFormat(string $route, array $accept_header, array $vars, ?TypeResponse &$response = null): bool
|
||||
{
|
||||
if (count(array_intersect(self::$accept_headers, $accept_header)) === 0) {
|
||||
return Event::next;
|
||||
}
|
||||
switch ($route) {
|
||||
case 'actor_view_id':
|
||||
case 'actor_view_nickname':
|
||||
$response = ActorResponse::handle($vars['actor']);
|
||||
return Event::stop;
|
||||
case 'note_view':
|
||||
$response = NoteResponse::handle($vars['note']);
|
||||
return Event::stop;
|
||||
default:
|
||||
if (Event::handle('ActivityPubActivityStreamsTwoResponse', [$route, $vars, &$response]) === Event::stop) {
|
||||
return Event::stop;
|
||||
}
|
||||
return Event::next;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add ActivityStreams 2 Extensions
|
||||
*
|
||||
* @param string $type_name
|
||||
* @param array $validators
|
||||
* @return bool
|
||||
*/
|
||||
public function onActivityPubValidateActivityStreamsTwoData(string $type_name, array &$validators): bool
|
||||
{
|
||||
switch ($type_name) {
|
||||
case 'Person':
|
||||
$validators['manuallyApprovesFollowers'] = manuallyApprovesFollowersModelValidator::class;
|
||||
break;
|
||||
case 'Note':
|
||||
$validators['contentLang'] = contentLangModelValidator::class;
|
||||
break;
|
||||
}
|
||||
return Event::next;
|
||||
}
|
||||
|
||||
// FreeNetworkComponent Events
|
||||
|
||||
/**
|
||||
* Let FreeNetwork Component know we exist and which class to use to call the freeNetworkDistribute method
|
||||
*
|
||||
* @param array $protocols
|
||||
* @return bool
|
||||
*/
|
||||
public function onAddFreeNetworkProtocol(array &$protocols): bool
|
||||
{
|
||||
$protocols[] = '\Plugin\ActivityPub\ActivityPub';
|
||||
return Event::next;
|
||||
}
|
||||
|
||||
/**
|
||||
* The FreeNetwork component will call this function to distribute this instance's activities
|
||||
*
|
||||
* @param Actor $sender
|
||||
* @param Activity $activity
|
||||
* @param array $targets
|
||||
* @param string|null $reason
|
||||
* @param array $delivered
|
||||
* @return bool
|
||||
* @throws ClientExceptionInterface
|
||||
* @throws RedirectionExceptionInterface
|
||||
* @throws ServerExceptionInterface
|
||||
* @throws TransportExceptionInterface
|
||||
*/
|
||||
public static function freeNetworkDistribute(Actor $sender, Activity $activity, array $targets, ?string $reason = null, array &$delivered = []): bool
|
||||
{
|
||||
$to_addr = [];
|
||||
@ -130,14 +245,13 @@ class ActivityPub extends Plugin
|
||||
//$to_failed = [];
|
||||
foreach ($to_addr as $inbox => $dummy) {
|
||||
try {
|
||||
$res = self::postman($sender, EntityToType::translate($activity), $inbox);
|
||||
$res = self::postman($sender, Model::toJson($activity), $inbox);
|
||||
|
||||
// accumulate errors for later use, if needed
|
||||
$status_code = $res->getStatusCode();
|
||||
if (!($status_code === 200 || $status_code === 202 || $status_code === 409)) {
|
||||
$res_body = json_decode($res->getContent(), true);
|
||||
$errors[] = isset($res_body['error']) ?
|
||||
$res_body['error'] : "An unknown error occurred.";
|
||||
$errors[] = $res_body['error'] ?? 'An unknown error occurred.';
|
||||
//$to_failed[$inbox] = $activity;
|
||||
} else {
|
||||
array_push($delivered, ...$dummy);
|
||||
@ -145,7 +259,7 @@ class ActivityPub extends Plugin
|
||||
FreeNetworkActorProtocol::protocolSucceeded(
|
||||
'activitypub',
|
||||
$actor,
|
||||
Discovery::normalize($actor->getNickname() . '@' . parse_url($inbox, PHP_URL_HOST))
|
||||
Discovery::normalize($actor->getNickname() . '@' . parse_url($inbox, PHP_URL_HOST)),
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -153,7 +267,6 @@ class ActivityPub extends Plugin
|
||||
Log::error('ActivityPub @ freeNetworkDistribute: ' . $e->getMessage());
|
||||
//$to_failed[$inbox] = $activity;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (!empty($errors)) {
|
||||
@ -165,27 +278,117 @@ class ActivityPub extends Plugin
|
||||
}
|
||||
|
||||
/**
|
||||
* Internal tool to sign and send activities out
|
||||
*
|
||||
* @param Actor $sender
|
||||
* @param Type $activity
|
||||
* @param string $json_activity
|
||||
* @param string $inbox
|
||||
* @param string $method
|
||||
* @return ResponseInterface
|
||||
* @throws Exception
|
||||
*/
|
||||
public static function postman(Actor $sender, mixed $activity, string $inbox, string $method = 'post'): ResponseInterface
|
||||
private static function postman(Actor $sender, string $json_activity, string $inbox, string $method = 'post'): ResponseInterface
|
||||
{
|
||||
$data = $activity->toJson();
|
||||
Log::debug('ActivityPub Postman: Delivering ' . $data . ' to ' . $inbox);
|
||||
Log::debug('ActivityPub Postman: Delivering ' . $json_activity . ' to ' . $inbox);
|
||||
|
||||
$headers = HTTPSignature::sign($sender, $inbox, $data);
|
||||
$headers = HTTPSignature::sign($sender, $inbox, $json_activity);
|
||||
Log::debug('ActivityPub Postman: Delivery headers were: ' . print_r($headers, true));
|
||||
|
||||
$response = HTTPClient::$method($inbox, ['headers' => $headers, 'body' => $data]);
|
||||
$response = HTTPClient::$method($inbox, ['headers' => $headers, 'body' => $json_activity]);
|
||||
Log::debug('ActivityPub Postman: Delivery result with status code ' . $response->getStatusCode() . ': ' . $response->getContent());
|
||||
return $response;
|
||||
}
|
||||
|
||||
// WebFinger Events
|
||||
|
||||
public static function getActorByUri(string $resource, ?bool $attempt_fetch = true): Actor
|
||||
/**
|
||||
* Add activity+json mimetype to WebFinger
|
||||
*
|
||||
* @param XML_XRD $xrd
|
||||
* @param Actor $object
|
||||
* @return bool
|
||||
*/
|
||||
public function onEndWebFingerProfileLinks(XML_XRD $xrd, Actor $object): bool
|
||||
{
|
||||
if ($object->isPerson()) {
|
||||
$link = new XML_XRD_Element_Link(
|
||||
rel: 'self',
|
||||
href: $object->getUri(Router::ABSOLUTE_URL),//Router::url('actor_view_id', ['id' => $object->getId()], Router::ABSOLUTE_URL),
|
||||
type: 'application/activity+json',
|
||||
);
|
||||
$xrd->links[] = clone $link;
|
||||
}
|
||||
return Event::next;
|
||||
}
|
||||
|
||||
/**
|
||||
* When FreeNetwork component asks us to help with identifying Actors from XRDs
|
||||
*
|
||||
* @param XML_XRD $xrd
|
||||
* @param Actor|null $actor
|
||||
* @return bool
|
||||
*/
|
||||
public function onFreeNetworkFoundXrd(XML_XRD $xrd, ?Actor &$actor = null): bool
|
||||
{
|
||||
$addr = null;
|
||||
foreach ($xrd->aliases as $alias) {
|
||||
if (Discovery::isAcct($alias)) {
|
||||
$addr = Discovery::normalize($alias);
|
||||
}
|
||||
}
|
||||
if (is_null($addr)) {
|
||||
return Event::next;
|
||||
} else {
|
||||
if (!FreeNetworkActorProtocol::canIAddr('activitypub', $addr)) {
|
||||
return Event::next;
|
||||
}
|
||||
}
|
||||
try {
|
||||
$ap_actor = ActivitypubActor::fromXrd($addr, $xrd);
|
||||
$actor = Actor::getById($ap_actor->getActorId());
|
||||
FreeNetworkActorProtocol::protocolSucceeded('activitypub', $actor, $addr);
|
||||
return Event::stop;
|
||||
} catch (Exception $e) {
|
||||
Log::error('ActivityPub Actor from URL Mention check failed: ' . $e->getMessage());
|
||||
return Event::next;
|
||||
}
|
||||
}
|
||||
|
||||
// Discovery Events
|
||||
|
||||
/**
|
||||
* When FreeNetwork component asks us to help with identifying Actors from URIs
|
||||
*
|
||||
* @param string $target
|
||||
* @param Actor|null $actor
|
||||
* @return bool
|
||||
*/
|
||||
public function onFreeNetworkFindMentions(string $target, ?Actor &$actor = null): bool
|
||||
{
|
||||
try {
|
||||
if (FreeNetworkActorProtocol::canIAddr('activitypub', $addr = Discovery::normalize($target))) {
|
||||
$ap_actor = ActivitypubActor::getByAddr($addr);
|
||||
$actor = Actor::getById($ap_actor->getActorId());
|
||||
FreeNetworkActorProtocol::protocolSucceeded('activitypub', $actor->getId(), $addr);
|
||||
return Event::stop;
|
||||
} else {
|
||||
return Event::next;
|
||||
}
|
||||
} catch (Exception $e) {
|
||||
Log::error('ActivityPub Webfinger Mention check failed: ' . $e->getMessage());
|
||||
return Event::next;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an Actor from ActivityPub URI, if it doesn't exist, attempt to fetch it
|
||||
* This should only be necessary internally.
|
||||
*
|
||||
* @param string $resource
|
||||
* @return Actor got from URI
|
||||
* @throws NoSuchActorException
|
||||
*/
|
||||
public static function getActorByUri(string $resource): Actor
|
||||
{
|
||||
// Try local
|
||||
if (Common::isValidHttpUrl($resource)) {
|
||||
@ -213,168 +416,4 @@ class ActivityPub extends Plugin
|
||||
throw new NoSuchActorException("From URI: {$resource}");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws Exception
|
||||
*/
|
||||
public function onControllerResponseInFormat(string $route, array $accept_header, array $vars, ?TypeResponse &$response = null): bool
|
||||
{
|
||||
if (count(array_intersect(self::$accept_headers, $accept_header)) === 0) {
|
||||
return Event::next;
|
||||
}
|
||||
switch ($route) {
|
||||
case 'actor_view_id':
|
||||
case 'actor_view_nickname':
|
||||
$response = ActorResponse::handle($vars['actor']);
|
||||
return Event::stop;
|
||||
case 'note_view':
|
||||
$response = NoteResponse::handle($vars['note']);
|
||||
return Event::stop;
|
||||
/*case 'actor_favourites_id':
|
||||
case 'actor_favourites_nickname':
|
||||
$response = LikeResponse::handle($vars['actor']);
|
||||
return Event::stop;
|
||||
case 'actor_subscriptions_id':
|
||||
case 'actor_subscriptions_nickname':
|
||||
$response = FollowingResponse::handle($vars['actor']);
|
||||
return Event::stop;
|
||||
case 'actor_subscribers_id':
|
||||
case 'actor_subscribers_nickname':
|
||||
$response = FollowersResponse::handle($vars['actor']);
|
||||
return Event::stop;*/
|
||||
default:
|
||||
if (Event::handle('ActivityStreamsTwoResponse', [$route, &$response]) == Event::stop) {
|
||||
return Event::stop;
|
||||
}
|
||||
return Event::next;
|
||||
}
|
||||
}
|
||||
|
||||
/********************************************************
|
||||
* WebFinger Events *
|
||||
********************************************************/
|
||||
|
||||
/**
|
||||
* Add activity+json mimetype on WebFinger
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
public function onEndWebFingerProfileLinks(XML_XRD $xrd, Actor $object): bool
|
||||
{
|
||||
if ($object->isPerson()) {
|
||||
$link = new XML_XRD_Element_Link(
|
||||
rel: 'self',
|
||||
href: $object->getUri(Router::ABSOLUTE_URL),//Router::url('actor_view_id', ['id' => $object->getId()], Router::ABSOLUTE_URL),
|
||||
type: 'application/activity+json',
|
||||
);
|
||||
$xrd->links[] = clone $link;
|
||||
}
|
||||
return Event::next;
|
||||
}
|
||||
|
||||
public function onFreeNetworkFindMentions(string $target, ?Actor &$actor = null): bool
|
||||
{
|
||||
try {
|
||||
if (FreeNetworkActorProtocol::canIAddr('activitypub', $addr = Discovery::normalize($target))) {
|
||||
$ap_actor = ActivitypubActor::getByAddr($addr);
|
||||
$actor = Actor::getById($ap_actor->getActorId());
|
||||
FreeNetworkActorProtocol::protocolSucceeded('activitypub', $actor->getId(), $addr);
|
||||
return Event::stop;
|
||||
} else {
|
||||
return Event::next;
|
||||
}
|
||||
} catch (Exception $e) {
|
||||
Log::error("ActivityPub Webfinger Mention check failed: " . $e->getMessage());
|
||||
return Event::next;
|
||||
}
|
||||
}
|
||||
|
||||
public function onFreeNetworkFoundXrd(XML_XRD $xrd, ?Actor &$actor = null): bool
|
||||
{
|
||||
$addr = null;
|
||||
foreach ($xrd->aliases as $alias) {
|
||||
if (Discovery::isAcct($alias)) {
|
||||
$addr = Discovery::normalize($alias);
|
||||
}
|
||||
}
|
||||
if (is_null($addr)) {
|
||||
return Event::next;
|
||||
} else {
|
||||
if (!FreeNetworkActorProtocol::canIAddr('activitypub', $addr)) {
|
||||
return Event::next;
|
||||
}
|
||||
}
|
||||
try {
|
||||
$ap_actor = ActivitypubActor::fromXrd($addr, $xrd);
|
||||
$actor = Actor::getById($ap_actor->getActorId());
|
||||
FreeNetworkActorProtocol::protocolSucceeded('activitypub', $actor, $addr);
|
||||
return Event::stop;
|
||||
} catch (Exception $e) {
|
||||
Log::error("ActivityPub Actor from URL Mention check failed: " . $e->getMessage());
|
||||
return Event::next;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Allow remote profile references to be used in commands:
|
||||
* sub update@status.net
|
||||
* whois evan@identi.ca
|
||||
* reply http://identi.ca/evan hey what's up
|
||||
*
|
||||
* @param Command $command
|
||||
* @param string $arg
|
||||
* @param Actor &$profile
|
||||
* @return bool hook return code
|
||||
* @author GNU social
|
||||
*/
|
||||
//public function onStartCommandGetProfile($command, $arg, &$profile)
|
||||
//{
|
||||
// $aprofile = ActivitypubActor::fromUri($arg);
|
||||
// if (!($aprofile instanceof ActivitypubActor)) {
|
||||
// // No remote ActivityPub profile found
|
||||
// return Event::next;
|
||||
// }
|
||||
//
|
||||
// return Event::stop;
|
||||
//}
|
||||
|
||||
/********************************************************
|
||||
* Discovery Events *
|
||||
********************************************************/
|
||||
|
||||
/**
|
||||
* Profile from URI.
|
||||
*
|
||||
* @param string $uri
|
||||
* @param Actor &$profile in/out param: Profile got from URI
|
||||
* @return mixed hook return code
|
||||
* @author GNU social
|
||||
*/
|
||||
//public function onStartGetProfileFromURI($uri, &$profile)
|
||||
//{
|
||||
// try {
|
||||
// $profile = Explorer::get_profile_from_url($uri);
|
||||
// return Event::stop;
|
||||
// } catch (Exception) {
|
||||
// return Event::next; // It's not an ActivityPub profile as far as we know, continue event handling
|
||||
// }
|
||||
//}
|
||||
|
||||
/**
|
||||
* Try to grab and store the remote profile by the given uri
|
||||
*
|
||||
* @param string $uri
|
||||
* @param Actor|null &$profile
|
||||
* @return bool
|
||||
*/
|
||||
//public function onRemoteFollowPullProfile(string $uri, ?Actor &$profile): bool
|
||||
//{
|
||||
// $aprofile = ActivitypubActor::fromUri($uri);
|
||||
// if (!($aprofile instanceof ActivitypubActor)) {
|
||||
// // No remote ActivityPub profile found
|
||||
// return Event::next;
|
||||
// }
|
||||
//
|
||||
// return is_null($profile) ? Event::next : Event::stop;
|
||||
//}
|
||||
}
|
||||
|
@ -3,7 +3,6 @@
|
||||
declare(strict_types=1);
|
||||
|
||||
// {{{ License
|
||||
|
||||
// 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
|
||||
@ -18,9 +17,18 @@ declare(strict_types = 1);
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with GNU social. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
// }}}
|
||||
|
||||
/**
|
||||
* ActivityPub implementation for GNU social
|
||||
*
|
||||
* @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
|
||||
*/
|
||||
|
||||
namespace Plugin\ActivityPub\Controller;
|
||||
|
||||
use App\Core\Controller;
|
||||
@ -28,30 +36,37 @@ use App\Core\DB\DB;
|
||||
use App\Core\Log;
|
||||
use App\Core\Router\Router;
|
||||
use App\Entity\Actor;
|
||||
use App\Util\Exception\ClientException;
|
||||
use Component\FreeNetwork\Entity\FreeNetworkActorProtocol;
|
||||
use Component\FreeNetwork\Util\Discovery;
|
||||
use Exception;
|
||||
use Plugin\ActivityPub\Entity\ActivitypubActor;
|
||||
use Plugin\ActivityPub\Entity\ActivitypubRsa;
|
||||
use Plugin\ActivityPub\Util\Explorer;
|
||||
use Plugin\ActivityPub\Util\HTTPSignature;
|
||||
use Plugin\ActivityPub\Util\Model;
|
||||
use Plugin\ActivityPub\Util\TypeResponse;
|
||||
use function App\Core\I18n\_m;
|
||||
use App\Util\Exception\ClientException;
|
||||
use Plugin\ActivityPub\ActivityPub;
|
||||
use Plugin\ActivityPub\Util\Model\AS2ToEntity\AS2ToEntity;
|
||||
use Plugin\ActivityPub\Util\Response\TypeResponse;
|
||||
use Plugin\ActivityPub\Util\Type;
|
||||
use Plugin\ActivityPub\Util\Type\Util;
|
||||
use function is_null;
|
||||
use const PHP_URL_HOST;
|
||||
|
||||
/**
|
||||
* ActivityPub Inbox Handler
|
||||
*
|
||||
* @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
|
||||
*/
|
||||
class Inbox extends Controller
|
||||
{
|
||||
/**
|
||||
* Inbox handler
|
||||
* Create an Inbox Handler to receive something from someone.
|
||||
*/
|
||||
public function handle(?int $gsactor_id = null): TypeResponse
|
||||
{
|
||||
$error = fn(string $m): TypeResponse => new TypeResponse(json_encode(['error' => $m]));
|
||||
$path = Router::url('activitypub_inbox', type: Router::ABSOLUTE_PATH);
|
||||
|
||||
if (!\is_null($gsactor_id)) {
|
||||
if (!is_null($gsactor_id)) {
|
||||
try {
|
||||
$user = DB::findOneBy('local_user', ['id' => $gsactor_id]);
|
||||
$path = Router::url('activitypub_actor_inbox', ['gsactor_id' => $user->getId()], type: Router::ABSOLUTE_PATH);
|
||||
@ -62,18 +77,18 @@ class Inbox extends Controller
|
||||
|
||||
Log::debug('ActivityPub Inbox: Received a POST request.');
|
||||
$body = (string)$this->request->getContent();
|
||||
$type = Type::fromJson($body);
|
||||
$type = Model::jsonToType($body);
|
||||
|
||||
if ($type->has('actor') === false) {
|
||||
ActivityPubReturn::error('Actor not found in the request.');
|
||||
$error('Actor not found in the request.');
|
||||
}
|
||||
|
||||
try {
|
||||
$ap_actor = ActivitypubActor::fromUri($type->get('actor'));
|
||||
$actor = Actor::getById($ap_actor->getActorId());
|
||||
DB::flush();
|
||||
} catch (Exception) {
|
||||
ActivityPubReturn::error('Invalid actor.');
|
||||
} catch (Exception $e) {
|
||||
$error('Invalid actor.');
|
||||
}
|
||||
|
||||
$actor_public_key = ActivitypubRsa::getByActor($actor)->getPublicKey();
|
||||
@ -86,7 +101,7 @@ class Inbox extends Controller
|
||||
|
||||
if (!isset($headers['signature'])) {
|
||||
Log::debug('ActivityPub Inbox: HTTP Signature: Missing Signature header.');
|
||||
ActivityPubReturn::error('Missing Signature header.', 400);
|
||||
$error('Missing Signature header.', 400);
|
||||
// TODO: support other methods beyond HTTP Signatures
|
||||
}
|
||||
|
||||
@ -95,7 +110,7 @@ class Inbox extends Controller
|
||||
Log::debug('ActivityPub Inbox: HTTP Signature Data: ' . print_r($signatureData, true));
|
||||
if (isset($signatureData['error'])) {
|
||||
Log::debug('ActivityPub Inbox: HTTP Signature: ' . json_encode($signatureData, JSON_PRETTY_PRINT));
|
||||
ActivityPubReturn::error(json_encode($signatureData, JSON_PRETTY_PRINT), 400);
|
||||
$error(json_encode($signatureData, JSON_PRETTY_PRINT), 400);
|
||||
}
|
||||
|
||||
list($verified, /*$headers*/) = HTTPSignature::verify($actor_public_key, $signatureData, $headers, $path, $body);
|
||||
@ -105,12 +120,12 @@ class Inbox extends Controller
|
||||
try {
|
||||
$res = Explorer::get_remote_user_activity($ap_actor->getUri());
|
||||
} catch (Exception) {
|
||||
ActivityPubReturn::error('Invalid remote actor.');
|
||||
$error('Invalid remote actor.');
|
||||
}
|
||||
try {
|
||||
$actor = ActivitypubActor::update_profile($ap_actor, $res);
|
||||
} catch (Exception) {
|
||||
ActivityPubReturn::error('Failed to updated remote actor information.');
|
||||
$error('Failed to updated remote actor information.');
|
||||
}
|
||||
|
||||
[$verified, /*$headers*/] = HTTPSignature::verify($actor_public_key, $signatureData, $headers, $path, $body);
|
||||
@ -119,7 +134,7 @@ class Inbox extends Controller
|
||||
// If it still failed despite profile update
|
||||
if ($verified !== 1) {
|
||||
Log::debug('ActivityPub Inbox: HTTP Signature: Invalid signature.');
|
||||
ActivityPubReturn::error('Invalid signature.');
|
||||
$error('Invalid signature.');
|
||||
}
|
||||
|
||||
// HTTP signature checked out, make sure the "actor" of the activity matches that of the signature
|
||||
@ -128,8 +143,12 @@ class Inbox extends Controller
|
||||
// TODO: Check if Actor has authority over payload
|
||||
|
||||
// Store Activity
|
||||
$ap_act = AS2ToEntity::store(activity: $type->toArray(), source: 'ActivityPub');
|
||||
FreeNetworkActorProtocol::protocolSucceeded('activitypub', $actor->getId());
|
||||
$ap_act = Model\Activity::fromJson($type, ['source' => 'ActivityPub']);
|
||||
FreeNetworkActorProtocol::protocolSucceeded(
|
||||
'activitypub',
|
||||
$ap_actor->getActorId(),
|
||||
Discovery::normalize($actor->getNickname() . '@' . parse_url($ap_actor->getInboxUri(), PHP_URL_HOST))
|
||||
);
|
||||
DB::flush();
|
||||
dd($ap_act, $act = $ap_act->getActivity(), $act->getActor(), $act->getObject());
|
||||
|
||||
|
@ -3,7 +3,6 @@
|
||||
declare(strict_types=1);
|
||||
|
||||
// {{{ License
|
||||
|
||||
// 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
|
||||
@ -18,9 +17,18 @@ declare(strict_types = 1);
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with GNU social. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
// }}}
|
||||
|
||||
/**
|
||||
* ActivityPub implementation for GNU social
|
||||
*
|
||||
* @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
|
||||
*/
|
||||
|
||||
namespace Plugin\ActivityPub\Entity;
|
||||
|
||||
use App\Core\DB\DB;
|
||||
@ -29,14 +37,9 @@ use App\Entity\Activity;
|
||||
use DateTimeInterface;
|
||||
|
||||
/**
|
||||
* Entity for all activities we know about
|
||||
* Table Definition for activitypub_activity
|
||||
*
|
||||
* @category DB
|
||||
* @package GNUsocial
|
||||
*
|
||||
* @author Hugo Sales <hugo@hsal.es>
|
||||
* @author Diogo Peralta Cordeiro <mail@diogo.site>
|
||||
* @copyright 2020-2021 Free Software Foundation, Inc http://www.fsf.org
|
||||
* @copyright 2021 Free Software Foundation, Inc http://www.fsf.org
|
||||
* @license https://www.gnu.org/licenses/agpl.html GNU AGPL v3 or later
|
||||
*/
|
||||
class ActivitypubActivity extends Entity
|
||||
|
@ -1,8 +1,8 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
// {{{ License
|
||||
|
||||
// {{{ License
|
||||
// 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
|
||||
@ -17,16 +17,15 @@ declare(strict_types = 1);
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with GNU social. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
// }}}
|
||||
|
||||
/**
|
||||
* ActivityPub implementation for GNU social
|
||||
*
|
||||
* @package GNUsocial
|
||||
*
|
||||
* @author Diogo Peralta Cordeiro <mail@diogo.site
|
||||
* @copyright 2021 Free Software Foundation, Inc http://www.fsf.org
|
||||
* @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
|
||||
*/
|
||||
|
||||
@ -34,20 +33,21 @@ 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;
|
||||
use DateTimeInterface;
|
||||
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
|
||||
*
|
||||
* @author Diogo Peralta Cordeiro <mail@diogo.site
|
||||
* @copyright 2021 Free Software Foundation, Inc http://www.fsf.org
|
||||
* @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
|
||||
*/
|
||||
class ActivitypubActor extends Entity
|
||||
@ -160,7 +160,7 @@ class ActivitypubActor extends Entity
|
||||
$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).'));
|
||||
}
|
||||
@ -189,14 +189,14 @@ class ActivitypubActor extends Entity
|
||||
return self::fromXrd($addr, $xrd);
|
||||
}
|
||||
|
||||
public static function fromXrd(string $addr, \XML_XRD $xrd): self
|
||||
public static function fromXrd(string $addr, XML_XRD $xrd): self
|
||||
{
|
||||
$hints = array_merge(
|
||||
['webfinger' => $addr],
|
||||
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}");
|
||||
|
@ -1,4 +1,8 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
// {{{ License
|
||||
// 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
|
||||
@ -13,6 +17,17 @@
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with GNU social. If not, see <http://www.gnu.org/licenses/>.
|
||||
// }}}
|
||||
|
||||
/**
|
||||
* ActivityPub implementation for GNU social
|
||||
*
|
||||
* @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
|
||||
*/
|
||||
|
||||
namespace Plugin\ActivityPub\Entity;
|
||||
|
||||
@ -22,25 +37,11 @@ use App\Core\Log;
|
||||
use App\Entity\Actor;
|
||||
use App\Util\Exception\ServerException;
|
||||
use DateTimeInterface;
|
||||
use Doctrine\ORM\UnitOfWork;
|
||||
use Exception;
|
||||
|
||||
/**
|
||||
* ActivityPub implementation for GNU social
|
||||
*
|
||||
* @package GNUsocial
|
||||
* @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
|
||||
* @link http://www.gnu.org/software/social/
|
||||
*/
|
||||
|
||||
/**
|
||||
* ActivityPub Keys System
|
||||
*
|
||||
* @category Plugin
|
||||
* @package GNUsocial
|
||||
* @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
|
||||
*/
|
||||
class ActivitypubRsa extends Entity
|
||||
|
@ -2,6 +2,33 @@
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
// {{{ License
|
||||
// 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
|
||||
// it under the terms of the GNU Affero General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// GNU social is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with GNU social. If not, see <http://www.gnu.org/licenses/>.
|
||||
// }}}
|
||||
|
||||
/**
|
||||
* ActivityPub implementation for GNU social
|
||||
*
|
||||
* @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
|
||||
*/
|
||||
|
||||
namespace Plugin\ActivityPub\Util;
|
||||
|
||||
// This file is part of GNU social - https://www.gnu.org/software/social
|
||||
@ -19,31 +46,24 @@ namespace Plugin\ActivityPub\Util;
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with GNU social. If not, see <http://www.gnu.org/licenses/>.
|
||||
use App\Core\Event;
|
||||
use App\Core\HTTPClient;
|
||||
use Component\FreeNetwork\Util\Discovery;
|
||||
use Component\FreeNetwork\Util\WebfingerResource\WebfingerResourceActor;
|
||||
use Mf2 as Mf2;
|
||||
use XML_XRD;
|
||||
|
||||
/**
|
||||
* ActivityPub implementation for GNU social
|
||||
* DiscoveryHints implementation for GNU social
|
||||
*
|
||||
* @package GNUsocial
|
||||
*
|
||||
* @author Evan Prodromou
|
||||
* @author Brion Vibber
|
||||
* @author James Walker
|
||||
* @author Siebrand Mazeland
|
||||
* @author Mikael Nordfeldth
|
||||
* @author Diogo Cordeiro
|
||||
* @copyright 2010, 2019, 2021 Free Software Foundation, Inc http://www.fsf.org
|
||||
* @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
|
||||
*
|
||||
* @see http://www.gnu.org/software/social/
|
||||
*/
|
||||
class DiscoveryHints
|
||||
{
|
||||
public static function fromXRD(XML_XRD $xrd)
|
||||
/**
|
||||
* Search the WebFinger XRD after an ActivityPub URI
|
||||
*
|
||||
* @param XML_XRD $xrd
|
||||
* @return array
|
||||
*/
|
||||
public static function fromXRD(XML_XRD $xrd): array
|
||||
{
|
||||
$hints = [];
|
||||
|
||||
@ -60,120 +80,3 @@ class DiscoveryHints
|
||||
return $hints;
|
||||
}
|
||||
}
|
||||
//class DiscoveryHints
|
||||
//{
|
||||
// public static function fromXRD(XML_XRD $xrd)
|
||||
// {
|
||||
// $hints = [];
|
||||
//
|
||||
// if (Event::handle('StartDiscoveryHintsFromXRD', [$xrd, &$hints])) {
|
||||
// foreach ($xrd->links as $link) {
|
||||
// switch ($link->rel) {
|
||||
// case WebfingerResourceActor::PROFILEPAGE:
|
||||
// $hints['profileurl'] = $link->href;
|
||||
// break;
|
||||
// case Discovery::UPDATESFROM:
|
||||
// if (empty($link->type) || $link->type == 'application/atom+xml') {
|
||||
// $hints['feedurl'] = $link->href;
|
||||
// }
|
||||
// break;
|
||||
// case Discovery::HCARD:
|
||||
// case Discovery::MF2_HCARD:
|
||||
// $hints['hcard'] = $link->href;
|
||||
// break;
|
||||
// default:
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
// Event::handle('EndDiscoveryHintsFromXRD', [$xrd, &$hints]);
|
||||
// }
|
||||
//
|
||||
// return $hints;
|
||||
// }
|
||||
//
|
||||
// public static function fromHcardUrl($url)
|
||||
// {
|
||||
// $response = HTTPClient::get($url, ['headers' => ['Accept' => 'text/html,application/xhtml+xml']]);
|
||||
//
|
||||
// if (!HTTPClient::statusCodeIsOkay($response)) {
|
||||
// return null;
|
||||
// }
|
||||
//
|
||||
// return self::hcardHints(
|
||||
// $response->getContent(),
|
||||
// HTTPClient::getEffectiveUrl($response)
|
||||
// );
|
||||
// }
|
||||
//
|
||||
// public static function hcardHints($body, $url)
|
||||
// {
|
||||
// $hcard = self::hcard($body, $url);
|
||||
//
|
||||
// if (empty($hcard)) {
|
||||
// return [];
|
||||
// }
|
||||
//
|
||||
// $hints = [];
|
||||
//
|
||||
// // XXX: don't copy stuff into an array and then copy it again
|
||||
//
|
||||
// if (array_key_exists('nickname', $hcard) && !empty($hcard['nickname'][0])) {
|
||||
// $hints['nickname'] = $hcard['nickname'][0];
|
||||
// }
|
||||
//
|
||||
// if (array_key_exists('name', $hcard) && !empty($hcard['name'][0])) {
|
||||
// $hints['fullname'] = $hcard['name'][0];
|
||||
// }
|
||||
//
|
||||
// if (array_key_exists('photo', $hcard) && count($hcard['photo'])) {
|
||||
// $hints['avatar'] = $hcard['photo'][0];
|
||||
// }
|
||||
//
|
||||
// if (array_key_exists('note', $hcard) && !empty($hcard['note'][0])) {
|
||||
// $hints['bio'] = $hcard['note'][0];
|
||||
// }
|
||||
//
|
||||
// if (array_key_exists('adr', $hcard) && !empty($hcard['adr'][0])) {
|
||||
// $hints['location'] = $hcard['adr'][0]['value'];
|
||||
// }
|
||||
//
|
||||
// if (array_key_exists('url', $hcard) && !empty($hcard['url'][0])) {
|
||||
// $hints['homepage'] = $hcard['url'][0];
|
||||
// }
|
||||
//
|
||||
// return $hints;
|
||||
// }
|
||||
//
|
||||
// private static function hcard($body, $url)
|
||||
// {
|
||||
// $mf2 = new Mf2\Parser($body, $url);
|
||||
// $mf2 = $mf2->parse();
|
||||
//
|
||||
// if (empty($mf2['items'])) {
|
||||
// return null;
|
||||
// }
|
||||
//
|
||||
// $hcards = [];
|
||||
//
|
||||
// foreach ($mf2['items'] as $item) {
|
||||
// if (!in_array('h-card', $item['type'])) {
|
||||
// continue;
|
||||
// }
|
||||
//
|
||||
// // We found a match, return it immediately
|
||||
// if (isset($item['properties']['url']) && in_array($url, $item['properties']['url'])) {
|
||||
// return $item['properties'];
|
||||
// }
|
||||
//
|
||||
// // Let's keep all the hcards for later, to return one of them at least
|
||||
// $hcards[] = $item['properties'];
|
||||
// }
|
||||
//
|
||||
// // No match immediately for the url we expected, but there were h-cards found
|
||||
// if (count($hcards) > 0) {
|
||||
// return $hcards[0];
|
||||
// }
|
||||
//
|
||||
// return null;
|
||||
// }
|
||||
//}
|
||||
|
@ -2,6 +2,7 @@
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
// {{{ License
|
||||
// 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
|
||||
@ -16,65 +17,58 @@ declare(strict_types = 1);
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with GNU social. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
namespace Plugin\ActivityPub\Util;
|
||||
|
||||
use App\Core\DB\DB;
|
||||
use App\Core\HTTPClient;
|
||||
use App\Core\Log;
|
||||
use App\Core\Security;
|
||||
use App\Entity\Actor;
|
||||
use App\Util\Exception\NoSuchActorException;
|
||||
use App\Util\Formatting;
|
||||
use DateTime;
|
||||
use Exception;
|
||||
use Plugin\ActivityPub\ActivityPub;
|
||||
use Plugin\ActivityPub\Entity\ActivitypubActor;
|
||||
use Plugin\ActivityPub\Entity\ActivitypubRsa;
|
||||
use Symfony\Contracts\HttpClient\Exception\ClientExceptionInterface;
|
||||
use Symfony\Contracts\HttpClient\Exception\RedirectionExceptionInterface;
|
||||
use Symfony\Contracts\HttpClient\Exception\ServerExceptionInterface;
|
||||
use Symfony\Contracts\HttpClient\Exception\TransportExceptionInterface;
|
||||
// }}}
|
||||
|
||||
/**
|
||||
* ActivityPub implementation for GNU social
|
||||
*
|
||||
* @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
|
||||
*
|
||||
* @see http://www.gnu.org/software/social/
|
||||
*/
|
||||
|
||||
namespace Plugin\ActivityPub\Util;
|
||||
|
||||
use App\Core\HTTPClient;
|
||||
use App\Core\Log;
|
||||
use App\Util\Exception\NoSuchActorException;
|
||||
use Exception;
|
||||
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
|
||||
*
|
||||
* Allows to discovery new remote actors
|
||||
*
|
||||
* @author Diogo Peralta Cordeiro (@diogo.site)
|
||||
*
|
||||
* @category Plugin
|
||||
* @package GNUsocial
|
||||
*
|
||||
* @copyright 2021 Free Software Foundation, Inc http://www.fsf.org
|
||||
* @license https://www.gnu.org/licenses/agpl.html GNU AGPL v3 or later
|
||||
*/
|
||||
class Explorer
|
||||
{
|
||||
private $discovered_actor_profiles = [];
|
||||
private array $discovered_actor_profiles = [];
|
||||
|
||||
/**
|
||||
* 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
|
||||
* @throws ServerExceptionInterface
|
||||
* @throws TransportExceptionInterface
|
||||
*
|
||||
* @return Actor
|
||||
*/
|
||||
public static function get_profile_from_url(string $url, bool $grab_online = true): ActivitypubActor
|
||||
{
|
||||
@ -101,11 +95,11 @@ class Explorer
|
||||
* @throws ServerExceptionInterface
|
||||
* @throws TransportExceptionInterface
|
||||
*
|
||||
* @return array of Profile objects
|
||||
* @return array of Actor objects
|
||||
*/
|
||||
public function lookup(string $url, bool $grab_online = true)
|
||||
{
|
||||
if (\in_array($url, ActivityPub::PUBLIC_TO)) {
|
||||
if (in_array($url, ActivityPub::PUBLIC_TO)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
@ -199,89 +193,32 @@ class Explorer
|
||||
} elseif (!HTTPClient::statusCodeIsOkay($response)) { // If it is unavailable
|
||||
return false; // Try to add at another time.
|
||||
}
|
||||
if (\is_null($res)) {
|
||||
Log::debug('ActivityPub Explorer: Invalid JSON returned from given Actor URL: ' . $response->getContent());
|
||||
if (is_null($res)) {
|
||||
Log::debug('ActivityPub Explorer: Invalid response returned from given Actor URL: ' . $res);
|
||||
return true; // Nothing to add.
|
||||
}
|
||||
|
||||
if (isset($res['type']) && $res['type'] === 'OrderedCollection' && isset($res['first'])) { // It's a potential collection of actors!!!
|
||||
if ($res['type'] === 'OrderedCollection') { // It's a potential collection of actors!!!
|
||||
Log::debug('ActivityPub Explorer: Found a collection of actors for ' . $url);
|
||||
$this->travel_collection($res['first']);
|
||||
return true;
|
||||
} elseif (self::validate_remote_response($res)) {
|
||||
Log::debug('ActivityPub Explorer: Found a valid remote actor for ' . $url);
|
||||
$this->discovered_actor_profiles[] = $this->store_profile($res);
|
||||
return true;
|
||||
} else {
|
||||
Log::debug('ActivityPub Explorer: Invalid potential remote actor while grabbing remotely: ' . $url . '. He returned the following: ' . json_encode($res, \JSON_UNESCAPED_SLASHES));
|
||||
try {
|
||||
$this->discovered_actor_profiles[] = Model\Actor::fromJson(json_encode($res));
|
||||
return true;
|
||||
} catch (Exception $e) {
|
||||
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()
|
||||
);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Save remote user profile in known instance
|
||||
*
|
||||
* @param array $res remote response
|
||||
*
|
||||
* @throws Exception
|
||||
* @throws NoSuchActorException
|
||||
*
|
||||
* @return Actor remote Profile object
|
||||
*/
|
||||
private function store_profile(array $res): ActivitypubActor
|
||||
{
|
||||
// Actor
|
||||
$actor_map = [
|
||||
'nickname' => $res['preferredUsername'],
|
||||
'fullname' => $res['name'] ?? null,
|
||||
'created' => new DateTime($res['published'] ?? 'now'),
|
||||
'bio' => isset($res['summary']) ? mb_substr(Security::sanitize($res['summary']), 0, 1000) : null,
|
||||
'is_local' => false,
|
||||
'modified' => new DateTime(),
|
||||
];
|
||||
|
||||
$actor = new Actor();
|
||||
foreach ($actor_map as $prop => $val) {
|
||||
$set = Formatting::snakeCaseToCamelCase("set_{$prop}");
|
||||
$actor->{$set}($val);
|
||||
}
|
||||
|
||||
DB::persist($actor);
|
||||
|
||||
// ActivityPub Actor
|
||||
$aprofile = ActivitypubActor::create([
|
||||
'inbox_uri' => $res['inbox'],
|
||||
'inbox_shared_uri' => $res['endpoints']['sharedInbox'],
|
||||
'uri' => $res['id'],
|
||||
'actor_id' => $actor->getId(),
|
||||
'url' => $res['url'] ?? null,
|
||||
]);
|
||||
|
||||
DB::persist($aprofile);
|
||||
|
||||
// Public Key
|
||||
$apRSA = ActivitypubRsa::create([
|
||||
'actor_id' => $actor->getID(),
|
||||
'public_key' => $res['publicKey']['publicKeyPem'],
|
||||
]);
|
||||
|
||||
DB::persist($apRSA);
|
||||
|
||||
// Avatar
|
||||
//if (isset($res['icon']['url'])) {
|
||||
// try {
|
||||
// $this->update_avatar($profile, $res['icon']['url']);
|
||||
// } catch (Exception $e) {
|
||||
// // Let the exception go, it isn't a serious issue
|
||||
// Log::debug('ActivityPub Explorer: An error ocurred while grabbing remote avatar: ' . $e->getMessage());
|
||||
// }
|
||||
//}
|
||||
|
||||
return $aprofile;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates a remote response in order to determine whether this
|
||||
* response is a valid profile or not
|
||||
@ -305,13 +242,19 @@ class Explorer
|
||||
public static function get_aprofile_by_url(string $v): ActivitypubActor|bool
|
||||
{
|
||||
$aprofile = ActivitypubActor::getWithPK(['uri' => $v]);
|
||||
return \is_null($aprofile) ? false : ActivitypubActor::getWithPK(['uri' => $v]);
|
||||
return is_null($aprofile) ? false : ActivitypubActor::getWithPK(['uri' => $v]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows the Explorer to transverse a collection of persons.
|
||||
*
|
||||
* @param string $url
|
||||
* @return bool
|
||||
* @throws ClientExceptionInterface
|
||||
* @throws NoSuchActorException
|
||||
* @throws RedirectionExceptionInterface
|
||||
* @throws ServerExceptionInterface
|
||||
* @throws TransportExceptionInterface
|
||||
*/
|
||||
private function travel_collection(string $url): bool
|
||||
{
|
||||
@ -328,7 +271,7 @@ class Explorer
|
||||
}
|
||||
}
|
||||
// Go through entire collection
|
||||
if (!\is_null($res['next'])) {
|
||||
if (!is_null($res['next'])) {
|
||||
$this->travel_collection($res['next']);
|
||||
}
|
||||
|
||||
@ -359,7 +302,7 @@ class Explorer
|
||||
throw new Exception('Non Ok Status Code for given Actor URL.');
|
||||
}
|
||||
$res = json_decode($response->getContent(), true);
|
||||
if (\is_null($res)) {
|
||||
if (is_null($res)) {
|
||||
Log::debug('ActivityPub Explorer: Invalid JSON returned from given Actor URL: ' . $response->getContent());
|
||||
throw new Exception('Given Actor URL didn\'t return a valid JSON.');
|
||||
}
|
||||
|
@ -64,7 +64,7 @@ class HTTPSignature
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array|string array or json string $body
|
||||
* @param array|string $body array or json string $body
|
||||
* @return string
|
||||
*/
|
||||
private static function _digest(array|string $body): string
|
||||
|
143
plugins/ActivityPub/Util/Model.php
Normal file
143
plugins/ActivityPub/Util/Model.php
Normal file
@ -0,0 +1,143 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
// {{{ License
|
||||
// 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
|
||||
// it under the terms of the GNU Affero General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// GNU social is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with GNU social. If not, see <http://www.gnu.org/licenses/>.
|
||||
// }}}
|
||||
|
||||
/**
|
||||
* ActivityPub implementation for GNU social
|
||||
*
|
||||
* @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
|
||||
*/
|
||||
|
||||
namespace Plugin\ActivityPub\Util;
|
||||
|
||||
use ActivityPhp\Type;
|
||||
use ActivityPhp\Type\TypeConfiguration;
|
||||
use ActivityPhp\Type\TypeResolver;
|
||||
use App\Core\Entity;
|
||||
use App\Core\Event;
|
||||
use App\Util\Exception\ClientException;
|
||||
use Exception;
|
||||
use InvalidArgumentException;
|
||||
use Plugin\ActivityPub\Util\Model\Activity;
|
||||
use Plugin\ActivityPub\Util\Model\Note;
|
||||
|
||||
/**
|
||||
* This class handles translation between JSON and GS Entities
|
||||
*
|
||||
* @copyright 2021 Free Software Foundation, Inc http://www.fsf.org
|
||||
* @license https://www.gnu.org/licenses/agpl.html GNU AGPL v3 or later
|
||||
*/
|
||||
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)) {
|
||||
$attributes = json_decode($data, true);
|
||||
if (json_last_error() !== JSON_ERROR_NONE
|
||||
|| !is_array($attributes)
|
||||
) {
|
||||
throw new Exception(
|
||||
sprintf(
|
||||
"An error occurred during the JSON decoding.\n '%s'",
|
||||
$data
|
||||
)
|
||||
);
|
||||
}
|
||||
} else {
|
||||
$attributes = $data;
|
||||
}
|
||||
|
||||
if (!array_key_exists('type', $attributes)) {
|
||||
throw new InvalidArgumentException('Missing "type" attribute in $data: ' . var_export($data, true));
|
||||
}
|
||||
unset($data);
|
||||
|
||||
try {
|
||||
$type = TypeResolver::getClass($attributes['type']);
|
||||
} catch (Exception $e) {
|
||||
$message = json_encode($attributes, JSON_PRETTY_PRINT);
|
||||
throw new Exception(
|
||||
$e->getMessage() . "\n$message"
|
||||
);
|
||||
}
|
||||
|
||||
if (is_string($type)) {
|
||||
$type = new $type();
|
||||
}
|
||||
|
||||
// Add our own extensions
|
||||
$validators = [];
|
||||
if (Event::handle('ActivityPubValidateActivityStreamsTwoData', [$attributes['type'], &$validators]) === Event::next) {
|
||||
foreach ($validators as $name => $class) {
|
||||
Type::addValidator($name, $class);
|
||||
$type->extend($name);
|
||||
}
|
||||
}
|
||||
|
||||
TypeConfiguration::set('undefined_properties', 'include');
|
||||
foreach ($attributes as $name => $value) {
|
||||
$type->set($name, $value);
|
||||
}
|
||||
|
||||
return $type;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
* @throws ClientException
|
||||
*/
|
||||
public static function toJson(mixed $object, int $options = null): string
|
||||
{
|
||||
switch ($object::class) {
|
||||
case 'App\Entity\Activity':
|
||||
return Activity::toJson($object, $options);
|
||||
case 'App\Entity\Note':
|
||||
return Note::toJson($object, $options);
|
||||
default:
|
||||
$type = self::jsonToType($object);
|
||||
Event::handle('ActivityPubAddActivityStreamsTwoData', [$type->get('type'), &$type]);
|
||||
return $type->toJson($options);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,82 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace Plugin\ActivityPub\Util\Model\AS2ToEntity;
|
||||
|
||||
use App\Core\DB\DB;
|
||||
use App\Core\Event;
|
||||
use App\Entity\Activity;
|
||||
use App\Entity\Actor;
|
||||
use App\Entity\Note;
|
||||
use App\Util\Exception\ClientException;
|
||||
use App\Util\Formatting;
|
||||
use DateTime;
|
||||
use Plugin\ActivityPub\ActivityPub;
|
||||
use Plugin\ActivityPub\Entity\ActivitypubActivity;
|
||||
|
||||
abstract class AS2ToEntity
|
||||
{
|
||||
public static function activity_stream_two_verb_to_gs_verb(string $verb): string
|
||||
{
|
||||
return match ($verb) {
|
||||
'Create' => 'create',
|
||||
default => throw new ClientException('Invalid verb'),
|
||||
};
|
||||
}
|
||||
|
||||
public static function activity_stream_two_object_type_to_gs_table(string $object): string
|
||||
{
|
||||
return match ($object) {
|
||||
'Note' => 'note',
|
||||
default => throw new ClientException('Invalid verb'),
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws ClientException
|
||||
*/
|
||||
public static function store(array $activity, ?string $source = null): ActivitypubActivity
|
||||
{
|
||||
$ap_act = ActivitypubActivity::getWithPK(['activity_uri' => $activity['id']]);
|
||||
if (\is_null($ap_act)) {
|
||||
$actor = ActivityPub::getActorByUri($activity['actor']);
|
||||
// Store Object
|
||||
$obj = null;
|
||||
switch ($activity['object']['type']) {
|
||||
case 'Note':
|
||||
$obj = AS2ToNote::translate($activity['object'], $source, $activity['actor'], $actor->getId());
|
||||
break;
|
||||
default:
|
||||
if (!Event::handle('ActivityPubObject', [$activity['object']['type'], $activity['object'], &$obj])) {
|
||||
throw new ClientException('Unsupported Object type.');
|
||||
}
|
||||
break;
|
||||
}
|
||||
DB::persist($obj);
|
||||
// Store Activity
|
||||
$act = Activity::create([
|
||||
'actor_id' => $actor->getId(),
|
||||
'verb' => self::activity_stream_two_verb_to_gs_verb($activity['type']),
|
||||
'object_type' => self::activity_stream_two_object_type_to_gs_table($activity['object']['type']),
|
||||
'object_id' => $obj->getId(),
|
||||
'is_local' => false,
|
||||
'created' => new DateTime($activity['published'] ?? 'now'),
|
||||
'source' => $source,
|
||||
]);
|
||||
DB::persist($act);
|
||||
// Store ActivityPub Activity
|
||||
$ap_act = ActivitypubActivity::create([
|
||||
'activity_id' => $act->getId(),
|
||||
'activity_uri' => $activity['id'],
|
||||
'object_uri' => $activity['object']['id'],
|
||||
'is_local' => false,
|
||||
'created' => new DateTime($activity['published'] ?? 'now'),
|
||||
'modified' => new DateTime(),
|
||||
]);
|
||||
DB::persist($ap_act);
|
||||
}
|
||||
|
||||
return $ap_act;
|
||||
}
|
||||
}
|
@ -1,67 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace Plugin\ActivityPub\Util\Model\AS2ToEntity;
|
||||
|
||||
use App\Core\Event;
|
||||
use App\Entity\Actor;
|
||||
use App\Entity\Language;
|
||||
use App\Entity\Note;
|
||||
use App\Util\Formatting;
|
||||
use DateTime;
|
||||
use Exception;
|
||||
use Plugin\ActivityPub\ActivityPub;
|
||||
use Plugin\ActivityPub\Entity\ActivitypubActivity;
|
||||
|
||||
abstract class AS2ToNote
|
||||
{
|
||||
/**
|
||||
*@throws Exception
|
||||
*/
|
||||
public static function translate(array $object, ?string $source, ?string $actor_uri = null, ?int $actor_id = null): Note
|
||||
{
|
||||
if (is_null($actor_uri) || $actor_uri !== $object['attributedTo']) {
|
||||
$actor_id = ActivityPub::getActorByUri($object['attributedTo'])->getId();
|
||||
}
|
||||
$map = [
|
||||
'is_local' => false,
|
||||
'created' => new DateTime($object['published'] ?? 'now'),
|
||||
'content' => $object['content'] ?? null,
|
||||
'content_type' => 'text/html',
|
||||
'language_id' => $object['contentLang'] ?? null,
|
||||
'url' => \array_key_exists('url', $object) ? $object['url'] : $object['id'],
|
||||
'actor_id' => $actor_id,
|
||||
'modified' => new DateTime(),
|
||||
'source' => $source,
|
||||
];
|
||||
if ($map['content'] !== null) {
|
||||
$mentions = [];
|
||||
Event::handle('RenderNoteContent', [
|
||||
$map['content'],
|
||||
$map['content_type'],
|
||||
&$map['rendered'],
|
||||
Actor::getById($actor_id),
|
||||
$map['language_id'],
|
||||
&$mentions,
|
||||
]);
|
||||
}
|
||||
|
||||
$obj = new Note();
|
||||
|
||||
if (!is_null($map['language_id'])) {
|
||||
$map['language_id'] = Language::getFromLocale($map['language_id'])->getId();
|
||||
} else {
|
||||
$map['language_id'] = null;
|
||||
}
|
||||
|
||||
foreach ($map as $prop => $val) {
|
||||
$set = Formatting::snakeCaseToCamelCase("set_{$prop}");
|
||||
$obj->{$set}($val);
|
||||
}
|
||||
|
||||
Event::handle('NewNoteFromActivityStreamsTwo', [$source, $obj, $actor_id]);
|
||||
|
||||
return $obj;
|
||||
}
|
||||
}
|
160
plugins/ActivityPub/Util/Model/Activity.php
Normal file
160
plugins/ActivityPub/Util/Model/Activity.php
Normal file
@ -0,0 +1,160 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
// {{{ License
|
||||
// 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
|
||||
// it under the terms of the GNU Affero General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// GNU social is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with GNU social. If not, see <http://www.gnu.org/licenses/>.
|
||||
// }}}
|
||||
|
||||
/**
|
||||
* ActivityPub implementation for GNU social
|
||||
*
|
||||
* @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
|
||||
*/
|
||||
|
||||
namespace Plugin\ActivityPub\Util\Model;
|
||||
|
||||
use ActivityPhp\Type\AbstractObject;
|
||||
use App\Core\DB\DB;
|
||||
use App\Core\Event;
|
||||
use App\Core\Router\Router;
|
||||
use App\Entity\Activity as GSActivity;
|
||||
use App\Util\Exception\ClientException;
|
||||
use App\Util\Exception\NoSuchActorException;
|
||||
use DateTime;
|
||||
use DateTimeInterface;
|
||||
use InvalidArgumentException;
|
||||
use Plugin\ActivityPub\ActivityPub;
|
||||
use Plugin\ActivityPub\Entity\ActivitypubActivity;
|
||||
use Plugin\ActivityPub\Util\Model;
|
||||
|
||||
/**
|
||||
* This class handles translation between JSON and ActivityPub Activities
|
||||
*
|
||||
* @copyright 2021 Free Software Foundation, Inc http://www.fsf.org
|
||||
* @license https://www.gnu.org/licenses/agpl.html GNU AGPL v3 or later
|
||||
*/
|
||||
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 ClientException
|
||||
* @throws NoSuchActorException
|
||||
*/
|
||||
public static function fromJson(string|AbstractObject $json, array $options = []): ActivitypubActivity
|
||||
{
|
||||
$type_activity = is_string($json) ? self::jsonToType($json) : $json;
|
||||
|
||||
$activity_stream_two_verb_to_gs_verb = fn(string $verb): string => match ($verb) {
|
||||
'Create' => 'create',
|
||||
default => throw new ClientException('Invalid verb'),
|
||||
};
|
||||
|
||||
$activity_stream_two_object_type_to_gs_table = fn(string $object): string => match ($object) {
|
||||
'Note' => 'note',
|
||||
default => throw new ClientException('Invalid verb'),
|
||||
};
|
||||
|
||||
$ap_act = ActivitypubActivity::getWithPK(['activity_uri' => $type_activity->get('id')]);
|
||||
if (is_null($ap_act)) {
|
||||
$actor = ActivityPub::getActorByUri($type_activity->get('actor'));
|
||||
// Store Object
|
||||
$obj = null;
|
||||
if (!$type_activity->has('object') || !isset($type_activity->get('object')['type'])) {
|
||||
throw new InvalidArgumentException('Activity Object or Activity Object Type is missing.');
|
||||
}
|
||||
switch ($type_activity->get('object')['type']) {
|
||||
case 'Note':
|
||||
$obj = Note::toJson($type_activity->get('object'), ['source' => $source, 'actor_uri' => $type_activity->get('actor'), 'actor_id' => $actor->getId()]);
|
||||
break;
|
||||
default:
|
||||
if (!Event::handle('ActivityPubObject', [$type_activity->get('object')['type'], $type_activity->get('object'), &$obj])) {
|
||||
throw new ClientException('Unsupported Object type.');
|
||||
}
|
||||
break;
|
||||
}
|
||||
DB::persist($obj);
|
||||
// Store Activity
|
||||
$act = GSActivity::create([
|
||||
'actor_id' => $actor->getId(),
|
||||
'verb' => $activity_stream_two_verb_to_gs_verb($type_activity->get('type')),
|
||||
'object_type' => $activity_stream_two_object_type_to_gs_table($type_activity->get('object')['type']),
|
||||
'object_id' => $obj->getId(),
|
||||
'is_local' => false,
|
||||
'created' => new DateTime($activity['published'] ?? 'now'),
|
||||
'source' => $source,
|
||||
]);
|
||||
DB::persist($act);
|
||||
// Store ActivityPub Activity
|
||||
$ap_act = ActivitypubActivity::create([
|
||||
'activity_id' => $act->getId(),
|
||||
'activity_uri' => $activity['id'],
|
||||
'object_uri' => $activity['object']['id'],
|
||||
'is_local' => false,
|
||||
'created' => new DateTime($activity['published'] ?? 'now'),
|
||||
'modified' => new DateTime(),
|
||||
]);
|
||||
DB::persist($ap_act);
|
||||
}
|
||||
|
||||
Event::handle('ActivityPubNewActivity', [&$ap_act, &$act, &$obj]);
|
||||
return $ap_act;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a JSON
|
||||
*
|
||||
* @param mixed $object
|
||||
* @param int|null $options
|
||||
* @return string
|
||||
* @throws ClientException
|
||||
*/
|
||||
public static function toJson(mixed $object, ?int $options = null): string
|
||||
{
|
||||
if ($object::class !== 'App\Entity\Activity') {
|
||||
throw new InvalidArgumentException('First argument type is Activity');
|
||||
}
|
||||
|
||||
$gs_verb_to_activity_stream_two_verb = fn($verb): string => match ($verb) {
|
||||
'create' => 'Create',
|
||||
default => throw new ClientException('Invalid verb'),
|
||||
};
|
||||
|
||||
$attr = [
|
||||
'type' => $gs_verb_to_activity_stream_two_verb($object->getVerb()),
|
||||
'@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'],
|
||||
'object' => self::jsonToType(self::toJson($object->getObject())),
|
||||
];
|
||||
|
||||
$type = self::jsonToType($attr);
|
||||
Event::handle('ActivityPubAddActivityStreamsTwoData', [$type->get('type'), &$type]);
|
||||
return $type->toJson($options);
|
||||
}
|
||||
}
|
174
plugins/ActivityPub/Util/Model/Actor.php
Normal file
174
plugins/ActivityPub/Util/Model/Actor.php
Normal file
@ -0,0 +1,174 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
// {{{ License
|
||||
// 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
|
||||
// it under the terms of the GNU Affero General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// GNU social is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with GNU social. If not, see <http://www.gnu.org/licenses/>.
|
||||
// }}}
|
||||
|
||||
/**
|
||||
* ActivityPub implementation for GNU social
|
||||
*
|
||||
* @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
|
||||
*/
|
||||
|
||||
namespace Plugin\ActivityPub\Util\Model;
|
||||
|
||||
use ActivityPhp\Type\AbstractObject;
|
||||
use App\Core\DB\DB;
|
||||
use App\Core\Event;
|
||||
use App\Core\Router\Router;
|
||||
use App\Core\Security;
|
||||
use App\Entity\Actor as GSActor;
|
||||
use App\Util\Exception\ServerException;
|
||||
use App\Util\Formatting;
|
||||
use Component\Avatar\Avatar;
|
||||
use Component\Avatar\Exception\NoAvatarException;
|
||||
use DateTime;
|
||||
use DateTimeInterface;
|
||||
use Exception;
|
||||
use InvalidArgumentException;
|
||||
use Plugin\ActivityPub\Entity\ActivitypubActor;
|
||||
use Plugin\ActivityPub\Entity\ActivitypubRsa;
|
||||
use Plugin\ActivityPub\Util\Model;
|
||||
|
||||
/**
|
||||
* This class handles translation between JSON and GSActors
|
||||
*
|
||||
* @copyright 2021 Free Software Foundation, Inc http://www.fsf.org
|
||||
* @license https://www.gnu.org/licenses/agpl.html GNU AGPL v3 or later
|
||||
*/
|
||||
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 GSActor
|
||||
* @throws Exception
|
||||
*/
|
||||
public static function fromJson(string|AbstractObject $json, array $options = []): GSActor
|
||||
{
|
||||
$person = is_string($json) ? self::jsonToType($json) : $json;
|
||||
|
||||
// Actor
|
||||
$actor_map = [
|
||||
'nickname' => $person->get('preferredUsername'),
|
||||
'fullname' => $person->get('name'),
|
||||
'created' => new DateTime($person->get('published') ?? 'now'),
|
||||
'bio' => $person->has('summary') ? mb_substr(Security::sanitize($person->get('summary')), 0, 1000) : null,
|
||||
'is_local' => false,
|
||||
'modified' => new DateTime(),
|
||||
];
|
||||
|
||||
$actor = new GSActor();
|
||||
foreach ($actor_map as $prop => $val) {
|
||||
$set = Formatting::snakeCaseToCamelCase("set_{$prop}");
|
||||
$actor->{$set}($val);
|
||||
}
|
||||
|
||||
DB::persist($actor);
|
||||
|
||||
// ActivityPub Actor
|
||||
$aprofile = ActivitypubActor::create([
|
||||
'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,
|
||||
]);
|
||||
|
||||
DB::persist($aprofile);
|
||||
|
||||
// Public Key
|
||||
$apRSA = ActivitypubRsa::create([
|
||||
'actor_id' => $actor->getID(),
|
||||
'public_key' => ($person->has('publicKey') && isset($person->get('publicKey')['publicKeyPem'])) ? $person->get('publicKey')['publicKeyPem'] : null,
|
||||
]);
|
||||
|
||||
DB::persist($apRSA);
|
||||
|
||||
// Avatar
|
||||
//if (isset($res['icon']['url'])) {
|
||||
// try {
|
||||
// $this->update_avatar($profile, $res['icon']['url']);
|
||||
// } catch (Exception $e) {
|
||||
// // Let the exception go, it isn't a serious issue
|
||||
// Log::debug('ActivityPub Explorer: An error occurred while grabbing remote avatar: ' . $e->getMessage());
|
||||
// }
|
||||
//}
|
||||
|
||||
Event::handle('ActivityPubNewActor', [&$aprofile, &$actor, &$apRSA]);
|
||||
return $aprofile;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a JSON
|
||||
*
|
||||
* @param mixed $object
|
||||
* @param int|null $options PHP JSON options
|
||||
* @return string
|
||||
* @throws ServerException
|
||||
*/
|
||||
public static function toJson(mixed $object, ?int $options = null): string
|
||||
{
|
||||
if ($object::class !== 'App\Entity\Actor') {
|
||||
throw new InvalidArgumentException('First argument type is Actor');
|
||||
}
|
||||
$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),
|
||||
'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),
|
||||
//'streams' =>
|
||||
'preferredUsername' => $object->getNickname(),
|
||||
'publicKey' => [
|
||||
'id' => $uri . "#public-key",
|
||||
'owner' => $uri,
|
||||
'publicKeyPem' => $public_key
|
||||
],
|
||||
'name' => $object->getFullname(),
|
||||
'location' => $object->getLocation(),
|
||||
'published' => $object->getCreated()->format(DateTimeInterface::RFC3339),
|
||||
'summary' => $object->getBio(),
|
||||
//'tag' => $object->getSelfTags(),
|
||||
'updated' => $object->getModified()->format(DateTimeInterface::RFC3339),
|
||||
'url' => $object->getUrl(Router::ABSOLUTE_URL),
|
||||
];
|
||||
try {
|
||||
$attr['icon'] = Avatar::getAvatar($object->getId())->getUrl(type: Router::ABSOLUTE_URL);
|
||||
} catch (NoAvatarException) {
|
||||
// No icon for this actor
|
||||
}
|
||||
|
||||
$type = self::jsonToType($attr);
|
||||
return $type->toJson($options);
|
||||
}
|
||||
}
|
@ -1,41 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Plugin\ActivityPub\Util\Model\EntityToType;
|
||||
|
||||
use App\Core\Router\Router;
|
||||
use App\Entity\Activity;
|
||||
use App\Util\Exception\ClientException;
|
||||
use DateTimeInterface;
|
||||
use Exception;
|
||||
use Plugin\ActivityPub\Util\Type;
|
||||
|
||||
class ActivityToType
|
||||
{
|
||||
public static function gs_verb_to_activity_stream_two_verb($verb)
|
||||
{
|
||||
return match ($verb) {
|
||||
'create' => 'Create',
|
||||
default => throw new ClientException('Invalid verb'),
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws Exception
|
||||
*/
|
||||
public static function translate(Activity $activity): Type\Core\Activity
|
||||
{
|
||||
$attr = [
|
||||
'type' => self::gs_verb_to_activity_stream_two_verb($activity->getVerb()),
|
||||
'@context' => 'https://www.w3.org/ns/activitystreams',
|
||||
'id' => Router::url('activity_view', ['id' => $activity->getId()], Router::ABSOLUTE_URL),
|
||||
'published' => $activity->getCreated()->format(DateTimeInterface::RFC3339),
|
||||
'actor' => $activity->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'],
|
||||
'object' => EntityToType::translate($activity->getObject()),
|
||||
];
|
||||
return Type::create($attr);
|
||||
}
|
||||
}
|
@ -1,31 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace Plugin\ActivityPub\Util\Model\EntityToType;
|
||||
|
||||
use App\Core\Entity;
|
||||
use Exception;
|
||||
use Plugin\ActivityPub\Util\Type;
|
||||
|
||||
abstract class EntityToType
|
||||
{
|
||||
/**
|
||||
* @return Type
|
||||
* @throws Exception
|
||||
*/
|
||||
public static function translate(Entity $entity): mixed
|
||||
{
|
||||
switch ($entity::class) {
|
||||
case 'App\Entity\Activity':
|
||||
return ActivityToType::translate($entity);
|
||||
case 'App\Entity\Note':
|
||||
return NoteToType::translate($entity);
|
||||
default:
|
||||
$map = [
|
||||
'type' => 'Object',
|
||||
];
|
||||
return Type::create($map);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,58 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace Plugin\ActivityPub\Util\Model\EntityToType;
|
||||
|
||||
use App\Core\Router\Router;
|
||||
use App\Entity\Actor;
|
||||
use Component\Avatar\Avatar;
|
||||
use Component\Avatar\Exception\NoAvatarException;
|
||||
use DateTimeInterface;
|
||||
use Exception;
|
||||
use Plugin\ActivityPub\Entity\ActivitypubRsa;
|
||||
use Plugin\ActivityPub\Util\Type;
|
||||
use Plugin\ActivityPub\Util\Type\Extended\Actor\Person;
|
||||
|
||||
class GSActorToType
|
||||
{
|
||||
/**
|
||||
*@throws Exception
|
||||
*/
|
||||
public static function translate(Actor $gsactor): Person
|
||||
{
|
||||
$rsa = ActivitypubRsa::getByActor($gsactor);
|
||||
$public_key = $rsa->getPublicKey();
|
||||
$uri = null;
|
||||
$attr = [
|
||||
'@context' => 'https://www.w3.org/ns/activitystreams',
|
||||
'id' => $gsactor->getUri(Router::ABSOLUTE_URL),
|
||||
'inbox' => Router::url('activitypub_actor_inbox', ['gsactor_id' => $gsactor->getId()], Router::ABSOLUTE_URL),
|
||||
'outbox' => Router::url('activitypub_actor_outbox', ['gsactor_id' => $gsactor->getId()], Router::ABSOLUTE_URL),
|
||||
'following' => Router::url('actor_subscriptions_id', ['id' => $gsactor->getId()], Router::ABSOLUTE_URL),
|
||||
'followers' => Router::url('actor_subscribers_id', ['id' => $gsactor->getId()], Router::ABSOLUTE_URL),
|
||||
'liked' => Router::url('favourites_view_by_actor_id', ['id' => $gsactor->getId()], Router::ABSOLUTE_URL),
|
||||
//'streams' =>
|
||||
'preferredUsername' => $gsactor->getNickname(),
|
||||
'publicKey' => [
|
||||
'id' => $uri . "#public-key",
|
||||
'owner' => $uri,
|
||||
'publicKeyPem' => $public_key
|
||||
],
|
||||
'name' => $gsactor->getFullname(),
|
||||
'location' => $gsactor->getLocation(),
|
||||
'published' => $gsactor->getCreated()->format(DateTimeInterface::RFC3339),
|
||||
'summary' => $gsactor->getBio(),
|
||||
//'tag' => $gsactor->getSelfTags(),
|
||||
'updated' => $gsactor->getModified()->format(DateTimeInterface::RFC3339),
|
||||
'url' => $gsactor->getUrl(Router::ABSOLUTE_URL),
|
||||
];
|
||||
try {
|
||||
$attr['icon'] = Avatar::getAvatar($gsactor->getId())->getUrl(type: Router::ABSOLUTE_URL);
|
||||
} catch (NoAvatarException) {
|
||||
// No icon for this actor
|
||||
}
|
||||
|
||||
return Type::create(type: 'Person', attributes: $attr);
|
||||
}
|
||||
}
|
@ -1,32 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Plugin\ActivityPub\Util\Model\EntityToType;
|
||||
|
||||
use App\Core\Router\Router;
|
||||
use App\Entity\Note;
|
||||
use DateTimeInterface;
|
||||
use Exception;
|
||||
use Plugin\ActivityPub\Util\Type;
|
||||
|
||||
class NoteToType
|
||||
{
|
||||
/**
|
||||
* @throws Exception
|
||||
*/
|
||||
public static function translate(Note $note): Type\Extended\Object\Note
|
||||
{
|
||||
$attr = [
|
||||
'@context' => 'https://www.w3.org/ns/activitystreams',
|
||||
'id' => Router::url('note_view', ['id' => $note->getId()], Router::ABSOLUTE_URL),
|
||||
'published' => $note->getCreated()->format(DateTimeInterface::RFC3339),
|
||||
'attributedTo' => $note->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'],
|
||||
'content' => $note->getRendered(),
|
||||
//'tag' => $tags
|
||||
];
|
||||
return Type::create(type: 'Note', attributes: $attr);
|
||||
}
|
||||
}
|
145
plugins/ActivityPub/Util/Model/Note.php
Normal file
145
plugins/ActivityPub/Util/Model/Note.php
Normal file
@ -0,0 +1,145 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
// {{{ License
|
||||
// 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
|
||||
// it under the terms of the GNU Affero General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// GNU social is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with GNU social. If not, see <http://www.gnu.org/licenses/>.
|
||||
// }}}
|
||||
|
||||
/**
|
||||
* ActivityPub implementation for GNU social
|
||||
*
|
||||
* @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
|
||||
*/
|
||||
|
||||
namespace Plugin\ActivityPub\Util\Model;
|
||||
|
||||
use ActivityPhp\Type\AbstractObject;
|
||||
use App\Core\Event;
|
||||
use App\Core\Router\Router;
|
||||
use App\Entity\Actor;
|
||||
use App\Entity\Language;
|
||||
use App\Entity\Note as GSNote;
|
||||
use App\Util\Formatting;
|
||||
use DateTime;
|
||||
use DateTimeInterface;
|
||||
use Exception;
|
||||
use InvalidArgumentException;
|
||||
use Plugin\ActivityPub\ActivityPub;
|
||||
use Plugin\ActivityPub\Util\Model;
|
||||
|
||||
/**
|
||||
* This class handles translation between JSON and GSNotes
|
||||
*
|
||||
* @copyright 2021 Free Software Foundation, Inc http://www.fsf.org
|
||||
* @license https://www.gnu.org/licenses/agpl.html GNU AGPL v3 or later
|
||||
*/
|
||||
class Note extends Model
|
||||
{
|
||||
|
||||
/**
|
||||
* Create an Entity from an ActivityStreams 2.0 JSON string
|
||||
* This will persist a new GSNote
|
||||
*
|
||||
* @param string|AbstractObject $json
|
||||
* @param array $options
|
||||
* @return GSNote
|
||||
* @throws Exception
|
||||
*/
|
||||
public static function fromJson(string|AbstractObject $json, array $options = []): GSNote
|
||||
{
|
||||
$source = $options['source'];
|
||||
$actor_uri = $options['actor_uri'];
|
||||
$actor_id = $options['actor_id'];
|
||||
$type_note = is_string($json) ? self::jsonToType($json) : $json;
|
||||
|
||||
if (is_null($actor_uri) || $actor_uri !== $type_note->get('attributedTo')) {
|
||||
$actor_id = ActivityPub::getActorByUri($type_note->get('attributedTo'))->getId();
|
||||
}
|
||||
$map = [
|
||||
'is_local' => false,
|
||||
'created' => new DateTime($type_note->get('published') ?? 'now'),
|
||||
'content' => $type_note->get('content') ?? null,
|
||||
'content_type' => 'text/html',
|
||||
'language_id' => $type_note->get('contentLang') ?? null,
|
||||
'url' => $type_note->get('url') ?? $type_note->get('id'),
|
||||
'actor_id' => $actor_id,
|
||||
'modified' => new DateTime(),
|
||||
'source' => $source,
|
||||
];
|
||||
if ($map['content'] !== null) {
|
||||
$mentions = [];
|
||||
Event::handle('RenderNoteContent', [
|
||||
$map['content'],
|
||||
$map['content_type'],
|
||||
&$map['rendered'],
|
||||
Actor::getById($actor_id),
|
||||
$map['language_id'],
|
||||
&$mentions,
|
||||
]);
|
||||
}
|
||||
|
||||
$obj = new GSNote();
|
||||
|
||||
if (!is_null($map['language_id'])) {
|
||||
$map['language_id'] = Language::getFromLocale($map['language_id'])->getId();
|
||||
} else {
|
||||
$map['language_id'] = null;
|
||||
}
|
||||
|
||||
foreach ($map as $prop => $val) {
|
||||
$set = Formatting::snakeCaseToCamelCase("set_{$prop}");
|
||||
$obj->{$set}($val);
|
||||
}
|
||||
|
||||
Event::handle('ActivityPubNewNote', [&$obj]);
|
||||
return $obj;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a JSON
|
||||
*
|
||||
* @param mixed $object
|
||||
* @param int|null $options
|
||||
* @return string
|
||||
* @throws Exception
|
||||
*/
|
||||
public static function toJson(mixed $object, ?int $options = null): string
|
||||
{
|
||||
if ($object::class !== 'App\Entity\Note') {
|
||||
throw new InvalidArgumentException('First argument type is Note');
|
||||
}
|
||||
|
||||
$attr = [
|
||||
'@context' => 'https://www.w3.org/ns/activitystreams',
|
||||
'id' => Router::url('note_view', ['id' => $object->getId()], Router::ABSOLUTE_URL),
|
||||
'published' => $object->getCreated()->format(DateTimeInterface::RFC3339),
|
||||
'attributedTo' => $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'],
|
||||
'content' => $object->getRendered(),
|
||||
//'tag' => $tags
|
||||
];
|
||||
|
||||
$type = self::jsonToType($attr);
|
||||
Event::handle('ActivityPubAddActivityStreamsTwoData', [$type->get('type'), &$type]);
|
||||
return $type->toJson($options);
|
||||
}
|
||||
}
|
56
plugins/ActivityPub/Util/ModelResponse.php
Normal file
56
plugins/ActivityPub/Util/ModelResponse.php
Normal file
@ -0,0 +1,56 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
// {{{ License
|
||||
// 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
|
||||
// it under the terms of the GNU Affero General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// GNU social is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with GNU social. If not, see <http://www.gnu.org/licenses/>.
|
||||
// }}}
|
||||
|
||||
/**
|
||||
* ActivityPub implementation for GNU social
|
||||
*
|
||||
* @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
|
||||
*/
|
||||
|
||||
namespace Plugin\ActivityPub\Util;
|
||||
|
||||
/**
|
||||
* Provides a response in application/ld+json to GS Entities
|
||||
*
|
||||
* @copyright 2021 Free Software Foundation, Inc http://www.fsf.org
|
||||
* @license https://www.gnu.org/licenses/agpl.html GNU AGPL v3 or later
|
||||
*/
|
||||
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
|
||||
*/
|
||||
public static function handle(mixed $object, int $status = 200): TypeResponse
|
||||
{
|
||||
return new TypeResponse(
|
||||
json: Model::toJson($object),
|
||||
status: $status,
|
||||
);
|
||||
}
|
||||
}
|
50
plugins/ActivityPub/Util/ModelValidator.php
Normal file
50
plugins/ActivityPub/Util/ModelValidator.php
Normal file
@ -0,0 +1,50 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
// {{{ License
|
||||
// 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
|
||||
// it under the terms of the GNU Affero General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// GNU social is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with GNU social. If not, see <http://www.gnu.org/licenses/>.
|
||||
// }}}
|
||||
|
||||
/**
|
||||
* ActivityPub implementation for GNU social
|
||||
*
|
||||
* @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
|
||||
*/
|
||||
|
||||
namespace Plugin\ActivityPub\Util;
|
||||
|
||||
use ActivityPhp\Type\ValidatorInterface;
|
||||
use ActivityPhp\Type\ValidatorTools;
|
||||
|
||||
/**
|
||||
* \Plugin\ActivityPub\Util\ModelValidator is an abstract class for
|
||||
* attribute validation.
|
||||
* Its purpose is to be extended by Plugin\ActivityPub\Util\Validator\*
|
||||
* classes.
|
||||
* It provides some methods to make some regular validations.
|
||||
* It implements \ActivityPhp\Type\ValidatorInterface.
|
||||
*
|
||||
* @copyright 2021 Free Software Foundation, Inc http://www.fsf.org
|
||||
* @license https://www.gnu.org/licenses/agpl.html GNU AGPL v3 or later
|
||||
*/
|
||||
abstract class ModelValidator extends ValidatorTools implements ValidatorInterface
|
||||
{
|
||||
}
|
@ -1,26 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace Plugin\ActivityPub\Util\Response;
|
||||
|
||||
use Exception;
|
||||
use Plugin\ActivityPub\Util\Model\EntityToType\EntityToType;
|
||||
|
||||
abstract class AbstractResponse
|
||||
{
|
||||
/**
|
||||
* param Type $type // What is this `Type`
|
||||
*
|
||||
* @param int $status The response status code
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
public static function handle($type, int $status = 200): TypeResponse
|
||||
{
|
||||
return new TypeResponse(
|
||||
data: EntityToType::translate($type),
|
||||
status: $status,
|
||||
);
|
||||
}
|
||||
}
|
59
plugins/ActivityPub/Util/Response/ActivityResponse.php
Normal file
59
plugins/ActivityPub/Util/Response/ActivityResponse.php
Normal file
@ -0,0 +1,59 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
// {{{ License
|
||||
// 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
|
||||
// it under the terms of the GNU Affero General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// GNU social is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with GNU social. If not, see <http://www.gnu.org/licenses/>.
|
||||
// }}}
|
||||
|
||||
/**
|
||||
* ActivityPub implementation for GNU social
|
||||
*
|
||||
* @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
|
||||
*/
|
||||
|
||||
namespace Plugin\ActivityPub\Util\Response;
|
||||
|
||||
use App\Entity\Activity as GSActivity;
|
||||
use App\Util\Exception\ClientException;
|
||||
use Plugin\ActivityPub\Util\Model\Activity as ModelActivity;
|
||||
use Plugin\ActivityPub\Util\TypeResponse;
|
||||
|
||||
/**
|
||||
* Provides a response in application/ld+json to GSActivity
|
||||
*
|
||||
* @copyright 2021 Free Software Foundation, Inc http://www.fsf.org
|
||||
* @license https://www.gnu.org/licenses/agpl.html GNU AGPL v3 or later
|
||||
*/
|
||||
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
|
||||
{
|
||||
return new TypeResponse(json: ModelActivity::toJson($activity), status: $status);
|
||||
}
|
||||
}
|
@ -2,24 +2,60 @@
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
// {{{ License
|
||||
// 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
|
||||
// it under the terms of the GNU Affero General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// GNU social is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with GNU social. If not, see <http://www.gnu.org/licenses/>.
|
||||
// }}}
|
||||
|
||||
/**
|
||||
* ActivityPub implementation for GNU social
|
||||
*
|
||||
* @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
|
||||
*/
|
||||
|
||||
namespace Plugin\ActivityPub\Util\Response;
|
||||
|
||||
use App\Entity\Actor;
|
||||
use App\Entity\Actor as GSActor;
|
||||
use App\Util\Exception\ClientException;
|
||||
use Exception;
|
||||
use Plugin\ActivityPub\Util\Model\EntityToType\GSActorToType;
|
||||
use Plugin\ActivityPub\Util\Model\Actor as ModelActor;
|
||||
use Plugin\ActivityPub\Util\TypeResponse;
|
||||
|
||||
/**
|
||||
* Provides a response in application/ld+json to GSActors
|
||||
*
|
||||
* @copyright 2021 Free Software Foundation, Inc http://www.fsf.org
|
||||
* @license https://www.gnu.org/licenses/agpl.html GNU AGPL v3 or later
|
||||
*/
|
||||
abstract class ActorResponse
|
||||
{
|
||||
/**
|
||||
* @param int $status The response status code
|
||||
* Provides a response in application/ld+json to GSActors
|
||||
*
|
||||
*@throws Exception
|
||||
* @param GSActor $gsactor
|
||||
* @param int $status The response status code
|
||||
* @return TypeResponse
|
||||
* @throws ClientException
|
||||
*/
|
||||
public static function handle(Actor $gsactor, int $status = 200): TypeResponse
|
||||
public static function handle(GSActor $gsactor, int $status = 200): TypeResponse
|
||||
{
|
||||
if ($gsactor->getIsLocal()) {
|
||||
return new TypeResponse(data: GSActorToType::translate($gsactor), status: $status);
|
||||
return new TypeResponse(json: ModelActor::toJson($gsactor), status: $status);
|
||||
} else {
|
||||
throw new ClientException('This is a remote actor, you should request it to its source of authority instead.');
|
||||
}
|
||||
|
@ -2,24 +2,56 @@
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
// {{{ License
|
||||
// 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
|
||||
// it under the terms of the GNU Affero General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// GNU social is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with GNU social. If not, see <http://www.gnu.org/licenses/>.
|
||||
// }}}
|
||||
|
||||
/**
|
||||
* ActivityPub implementation for GNU social
|
||||
*
|
||||
* @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
|
||||
*/
|
||||
|
||||
namespace Plugin\ActivityPub\Util\Response;
|
||||
|
||||
use App\Entity\Note;
|
||||
use Exception;
|
||||
use Plugin\ActivityPub\Util\Model\EntityToType\NoteToType;
|
||||
use App\Entity\Note as GSNote;
|
||||
use Plugin\ActivityPub\Util\Model\Note as ModelNote;
|
||||
use Plugin\ActivityPub\Util\TypeResponse;
|
||||
|
||||
/**
|
||||
* Provides a response in application/ld+json to GSNotes
|
||||
*
|
||||
* @copyright 2021 Free Software Foundation, Inc http://www.fsf.org
|
||||
* @license https://www.gnu.org/licenses/agpl.html GNU AGPL v3 or later
|
||||
*/
|
||||
abstract class NoteResponse
|
||||
//class NoteResponse extends Controller
|
||||
{
|
||||
/**
|
||||
* @param int $status The response status code
|
||||
* Provides a response in application/ld+json to GSNotes
|
||||
*
|
||||
* @throws Exception
|
||||
* @param GSNote $note
|
||||
* @param int $status The response status code
|
||||
* @return TypeResponse
|
||||
*/
|
||||
public static function handle(Note $note, int $status = 200): TypeResponse
|
||||
// public function handle(Request $request, int $id): JsonResponse
|
||||
public static function handle(GSNote $note, int $status = 200): TypeResponse
|
||||
{
|
||||
// $note = DB::findOneBy('note', ['id' => $id]);
|
||||
return new TypeResponse(data: NoteToType::translate($note), status: $status);
|
||||
return new TypeResponse(json: ModelNote::toJson($note), status: $status);
|
||||
}
|
||||
}
|
||||
|
@ -1,28 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace Plugin\ActivityPub\Util\Response;
|
||||
|
||||
use Symfony\Component\HttpFoundation\JsonResponse;
|
||||
|
||||
class TypeResponse extends JsonResponse
|
||||
{
|
||||
/**
|
||||
* param Type $data // what `Type` is this?
|
||||
*
|
||||
* @param int $status The response status code
|
||||
* @param null|mixed $data
|
||||
*
|
||||
* @return JsonResponse
|
||||
*/
|
||||
public function __construct($data = null, int $status = 202)
|
||||
{
|
||||
parent::__construct(
|
||||
data: !\is_null($data) ? $data->toJson() : null,
|
||||
status: $status,
|
||||
headers: ['content-type' => 'application/ld+json; profile="https://www.w3.org/ns/activitystreams"'],
|
||||
json: true,
|
||||
);
|
||||
}
|
||||
}
|
@ -1,125 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
/*
|
||||
* This file is part of the ActivityPhp package.
|
||||
*
|
||||
* Copyright (c) landrok at github.com/landrok
|
||||
*
|
||||
* For the full copyright and license information, please see
|
||||
* <https://github.com/landrok/activitypub/blob/master/LICENSE>.
|
||||
*/
|
||||
|
||||
namespace Plugin\ActivityPub\Util;
|
||||
|
||||
use Exception;
|
||||
use Plugin\ActivityPub\Util\Type\AbstractObject;
|
||||
use Plugin\ActivityPub\Util\Type\TypeResolver;
|
||||
use Plugin\ActivityPub\Util\Type\Validator;
|
||||
|
||||
/**
|
||||
* \ActivityPhp\Type is a Factory for ActivityStreams 2.0 types.
|
||||
*
|
||||
* It provides shortcuts methods for type instantiation and more.
|
||||
*
|
||||
* @see https://www.w3.org/TR/activitystreams-vocabulary/#types
|
||||
* @see https://www.w3.org/TR/activitystreams-vocabulary/#activity-types
|
||||
* @see https://www.w3.org/TR/activitystreams-vocabulary/#actor-types
|
||||
* @see https://www.w3.org/TR/activitystreams-vocabulary/#object-types
|
||||
*/
|
||||
abstract class Type
|
||||
{
|
||||
/**
|
||||
* Factory method to create type instance and set attributes values
|
||||
*
|
||||
* To see which default types are defined and their attributes:
|
||||
*
|
||||
* @see https://www.w3.org/TR/activitystreams-vocabulary/#types
|
||||
* @see https://www.w3.org/TR/activitystreams-vocabulary/#activity-types
|
||||
* @see https://www.w3.org/TR/activitystreams-vocabulary/#actor-types
|
||||
* @see https://www.w3.org/TR/activitystreams-vocabulary/#object-types
|
||||
*
|
||||
* @param array<string,mixed>|string $type
|
||||
* @param array<string,mixed> $attributes
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
public static function create($type, array $attributes = []): mixed
|
||||
{
|
||||
if (!\is_string($type) && !\is_array($type)) {
|
||||
throw new Exception(
|
||||
'Type parameter must be a string or an array. Given='
|
||||
. \gettype($type),
|
||||
);
|
||||
}
|
||||
|
||||
if (\is_array($type)) {
|
||||
if (!isset($type['type'])) {
|
||||
throw new Exception(
|
||||
"Type parameter must have a 'type' key",
|
||||
);
|
||||
}
|
||||
|
||||
$attributes = $type;
|
||||
}
|
||||
|
||||
try {
|
||||
$class = \is_array($type)
|
||||
? TypeResolver::getClass($type['type'])
|
||||
: TypeResolver::getClass($type);
|
||||
} catch (Exception $exception) {
|
||||
$message = json_encode($attributes, \JSON_PRETTY_PRINT);
|
||||
throw new Exception(
|
||||
$exception->getMessage() . "\n{$message}",
|
||||
);
|
||||
}
|
||||
|
||||
if (\is_string($class)) {
|
||||
$class = new $class();
|
||||
}
|
||||
|
||||
foreach ($attributes as $name => $value) {
|
||||
try {
|
||||
$class->set($name, $value);
|
||||
} catch (Exception) {
|
||||
// Discard invalid properties
|
||||
}
|
||||
}
|
||||
|
||||
return $class;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an activitystream type from a JSON string
|
||||
*/
|
||||
public static function fromJson(string $json): AbstractObject
|
||||
{
|
||||
$data = json_decode($json, true);
|
||||
|
||||
if (json_last_error() === \JSON_ERROR_NONE
|
||||
&& \is_array($data)
|
||||
) {
|
||||
return self::create($data);
|
||||
}
|
||||
|
||||
throw new Exception(
|
||||
sprintf(
|
||||
"An error occurred during the JSON decoding.\n '%s'",
|
||||
$json,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a custom validator for an attribute.
|
||||
* It checks that it implements Validator\Interface
|
||||
*
|
||||
* @param string $name an attribute name to validate
|
||||
* @param string $class A validator class name
|
||||
*/
|
||||
public static function addValidator(string $name, string $class): void
|
||||
{
|
||||
Validator::add($name, $class);
|
||||
}
|
||||
}
|
@ -1,365 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
/*
|
||||
* This file is part of the ActivityPhp package.
|
||||
*
|
||||
* Copyright (c) landrok at github.com/landrok
|
||||
*
|
||||
* For the full copyright and license information, please see
|
||||
* <https://github.com/landrok/activitypub/blob/master/LICENSE>.
|
||||
*/
|
||||
|
||||
namespace Plugin\ActivityPub\Util\Type;
|
||||
|
||||
use Exception;
|
||||
use Plugin\ActivityPub\Util\Type;
|
||||
use ReflectionClass;
|
||||
use ReflectionProperty;
|
||||
|
||||
/**
|
||||
* \ActivityPhp\Type\ObjectAbstract is an abstract class for all
|
||||
* Activity Streams Core Types.
|
||||
*
|
||||
* @see https://www.w3.org/TR/activitystreams-core/#model
|
||||
*/
|
||||
abstract class AbstractObject
|
||||
{
|
||||
/**
|
||||
* Keep all properties values that have been set
|
||||
*/
|
||||
private array $_props = [];
|
||||
|
||||
protected string $type = 'AbstractObject';
|
||||
|
||||
/**
|
||||
* Standard setter method
|
||||
* - Perform content validation if a validator exists
|
||||
*
|
||||
* @throws Exception
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function set(string $name, mixed $value): static
|
||||
{
|
||||
// Throws an exception when property is undefined
|
||||
if ($name !== '@context') {
|
||||
$this->has($name);
|
||||
}
|
||||
|
||||
// Validate given value
|
||||
if (!Validator::validate($name, $value, $this)) {
|
||||
$message = "Rejected value. Type='%s', Property='%s', value='%s'";
|
||||
throw new Exception(
|
||||
sprintf(
|
||||
$message,
|
||||
static::class,
|
||||
$name,
|
||||
print_r($value, true),
|
||||
)
|
||||
. \PHP_EOL,
|
||||
);
|
||||
}
|
||||
|
||||
// @context has a special role
|
||||
if ($name === '@context') {
|
||||
$this->_props[$name] = $value;
|
||||
|
||||
// All modes and property defined
|
||||
} elseif ($this->has($name)) {
|
||||
$this->_props[$name] = $this->transform($value);
|
||||
|
||||
// Undefined property but it's valid as it was
|
||||
// tested in the if clause above (no exception) so, let's include it
|
||||
} else {
|
||||
$this->_props[$name] = $this->transform($value);
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Affect a value to a property or an extended property
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
private function transform(mixed $value): mixed
|
||||
{
|
||||
// Deep typing
|
||||
if (\is_array($value)) {
|
||||
if (isset($value['type'])) {
|
||||
return Type::create($value);
|
||||
} elseif (\is_int(key($value))) {
|
||||
return array_map(
|
||||
static function ($value) {
|
||||
return \is_array($value) && isset($value['type'])
|
||||
? Type::create($value)
|
||||
: $value;
|
||||
},
|
||||
$value,
|
||||
);
|
||||
// Empty array, array that should not be cast as ActivityStreams types
|
||||
} else {
|
||||
return $value;
|
||||
}
|
||||
} else {
|
||||
// Scalars
|
||||
return $value;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Standard getter method
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
public function get(string $name): mixed
|
||||
{
|
||||
// Throws an exception when property is undefined
|
||||
$this->has($name);
|
||||
|
||||
return $this->_props[$name];
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks that property exists
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
public function has(string $name): bool
|
||||
{
|
||||
if (isset($this->{$name})) {
|
||||
if (!\array_key_exists($name, $this->_props)) {
|
||||
$this->_props[$name] = $this->{$name};
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
if (\array_key_exists($name, $this->_props)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
$reflect = new ReflectionClass(Type::create($this->type));
|
||||
$allowed_props = $reflect->getProperties(ReflectionProperty::IS_PUBLIC | ReflectionProperty::IS_PROTECTED);
|
||||
$allowed = [];
|
||||
foreach ($allowed_props as $prop) {
|
||||
$allowed[] = $prop->getName();
|
||||
}
|
||||
if (!\in_array($name, $allowed)) {
|
||||
sort($allowed);
|
||||
throw new Exception(
|
||||
sprintf(
|
||||
'Property "%s" is not defined. Type="%s", '
|
||||
. 'Class="%s"' . \PHP_EOL . 'Allowed properties: %s',
|
||||
$name,
|
||||
$this->get('type'),
|
||||
static::class,
|
||||
implode(', ', $allowed),
|
||||
),
|
||||
);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a list of all properties names
|
||||
*/
|
||||
public function getProperties(): array
|
||||
{
|
||||
return array_values(
|
||||
array_unique(
|
||||
array_merge(
|
||||
array_keys($this->_props),
|
||||
array_keys(
|
||||
array_diff_key(
|
||||
get_object_vars($this),
|
||||
['_props' => '1'],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a list of all properties and their values
|
||||
* as an associative array.
|
||||
* Null values are not returned.
|
||||
*/
|
||||
public function toArray(): array
|
||||
{
|
||||
$keys = array_keys(
|
||||
array_filter(
|
||||
get_object_vars($this),
|
||||
static fn ($value, $key): bool => !\is_null($value) && $key !== '_props',
|
||||
\ARRAY_FILTER_USE_BOTH,
|
||||
),
|
||||
);
|
||||
|
||||
$stack = [];
|
||||
|
||||
// native properties
|
||||
foreach ($keys as $key) {
|
||||
if ($this->{$key} instanceof self) {
|
||||
$stack[$key] = $this->{$key}->toArray();
|
||||
} elseif (!\is_array($this->{$key})) {
|
||||
$stack[$key] = $this->{$key};
|
||||
} elseif (\is_array($this->{$key})) {
|
||||
if (\is_int(key($this->{$key}))) {
|
||||
$stack[$key] = array_map(
|
||||
static function ($value) {
|
||||
return $value instanceof self
|
||||
? $value->toArray()
|
||||
: $value;
|
||||
},
|
||||
$this->{$key},
|
||||
);
|
||||
} else {
|
||||
$stack[$key] = $this->{$key};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// _props
|
||||
foreach ($this->_props as $key => $value) {
|
||||
if (\is_null($value)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($value instanceof self) {
|
||||
$stack[$key] = $value->toArray();
|
||||
} elseif (!\is_array($value)) {
|
||||
$stack[$key] = $value;
|
||||
} else {
|
||||
if (\is_int(key($value))) {
|
||||
$stack[$key] = array_map(
|
||||
static function ($value) {
|
||||
return $value instanceof self
|
||||
? $value->toArray()
|
||||
: $value;
|
||||
},
|
||||
$value,
|
||||
);
|
||||
} else {
|
||||
$stack[$key] = $value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $stack;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a JSON
|
||||
*
|
||||
* @param null|int $options PHP JSON options
|
||||
*/
|
||||
public function toJson(?int $options = null): string
|
||||
{
|
||||
return json_encode(
|
||||
value: $this->toArray(),
|
||||
flags: (int) $options,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a copy of current object and return a new instance
|
||||
*
|
||||
* @throws Exception
|
||||
*
|
||||
* @return self A new instance of this object
|
||||
*/
|
||||
public function copy(): self
|
||||
{
|
||||
return Type::create(
|
||||
$this->type,
|
||||
$this->toArray(),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Extend current type properties
|
||||
*
|
||||
* @param mixed $default
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
public function extend(string $property, mixed $default = null): void
|
||||
{
|
||||
if ($this->has($property)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!\array_key_exists($property, $this->_props)) {
|
||||
$this->_props[$property] = $default;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Magical isset method
|
||||
*/
|
||||
public function __isset(string $name): bool
|
||||
{
|
||||
return property_exists($this, $name)
|
||||
|| \array_key_exists($name, $this->_props);
|
||||
}
|
||||
|
||||
/**
|
||||
* Magical setter method
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
public function __set(string $name, mixed $value): void
|
||||
{
|
||||
$this->set($name, $value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Magical getter method
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
public function __get(string $name): mixed
|
||||
{
|
||||
return $this->get($name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Overloading methods
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
public function __call(string $name, ?array $arguments = []): mixed
|
||||
{
|
||||
// Getters
|
||||
if (str_starts_with($name, 'get')) {
|
||||
$attr = lcfirst(mb_substr($name, 3));
|
||||
return $this->get($attr);
|
||||
}
|
||||
|
||||
// Setters
|
||||
if (str_starts_with($name, 'set')) {
|
||||
if (\count($arguments) === 1) {
|
||||
$attr = lcfirst(mb_substr($name, 3));
|
||||
return $this->set($attr, $arguments[0]);
|
||||
} else {
|
||||
throw new Exception(
|
||||
sprintf(
|
||||
'Expected exactly one argument for method "%s()"',
|
||||
$name,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
throw new Exception(
|
||||
sprintf(
|
||||
'Method "%s" is not defined',
|
||||
$name,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
@ -1,110 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
/*
|
||||
* This file is part of the ActivityPhp package.
|
||||
*
|
||||
* Copyright (c) landrok at github.com/landrok
|
||||
*
|
||||
* For the full copyright and license information, please see
|
||||
* <https://github.com/landrok/activitypub/blob/master/LICENSE>.
|
||||
*/
|
||||
|
||||
namespace Plugin\ActivityPub\Util\Type\Core;
|
||||
|
||||
/**
|
||||
* \Plugin\ActivityPub\Util\Type\Core\AbstractActivity implements only common
|
||||
* attributes between Activity and IntransitiveActivity.
|
||||
*
|
||||
* It SHOULD NOT be used as if.
|
||||
*
|
||||
* Please use IntransitiveActivity or Activity instead.
|
||||
*
|
||||
* @see https://www.w3.org/TR/activitystreams-core/#activities
|
||||
* @see https://www.w3.org/TR/activitystreams-core/#intransitiveactivities
|
||||
*/
|
||||
abstract class AbstractActivity extends ObjectType
|
||||
{
|
||||
public string $id;
|
||||
|
||||
/**
|
||||
* Describes one or more entities that either performed or are
|
||||
* expected to perform the activity.
|
||||
* Any single activity can have multiple actors.
|
||||
* The actor MAY be specified using an indirect Link.
|
||||
*
|
||||
* @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-actor
|
||||
*
|
||||
* @var string
|
||||
* | \Plugin\ActivityPub\Util\Type\Extended\AbstractActor
|
||||
* | array<Actor>
|
||||
* | array<Link>
|
||||
* | Link
|
||||
*/
|
||||
protected string $actor;
|
||||
|
||||
/**
|
||||
* The indirect object, or target, of the activity.
|
||||
* The precise meaning of the target is largely dependent on the
|
||||
* type of action being described but will often be the object of
|
||||
* the English preposition "to".
|
||||
* For instance, in the activity "John added a movie to his
|
||||
* wishlist", the target of the activity is John's wishlist.
|
||||
* An activity can have more than one target.
|
||||
*
|
||||
* @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-target
|
||||
*
|
||||
* @var string
|
||||
* | ObjectType
|
||||
* | array<ObjectType>
|
||||
* | Link
|
||||
* | array<Link>
|
||||
*/
|
||||
protected string $target;
|
||||
|
||||
/**
|
||||
* Describes the result of the activity.
|
||||
* For instance, if a particular action results in the creation of
|
||||
* a new resource, the result property can be used to describe
|
||||
* that new resource.
|
||||
*
|
||||
* @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-result
|
||||
*
|
||||
* @var string
|
||||
* | ObjectType
|
||||
* | Link
|
||||
* | null
|
||||
*/
|
||||
protected string $result;
|
||||
|
||||
/**
|
||||
* An indirect object of the activity from which the
|
||||
* activity is directed.
|
||||
* The precise meaning of the origin is the object of the English
|
||||
* preposition "from".
|
||||
* For instance, in the activity "John moved an item to List B
|
||||
* from List A", the origin of the activity is "List A".
|
||||
*
|
||||
* @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-origin
|
||||
*
|
||||
* @var string
|
||||
* | ObjectType
|
||||
* | Link
|
||||
* | null
|
||||
*/
|
||||
protected string $origin;
|
||||
|
||||
/**
|
||||
* One or more objects used (or to be used) in the completion of an
|
||||
* Activity.
|
||||
*
|
||||
* @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-instrument
|
||||
*
|
||||
* @var string
|
||||
* | ObjectType
|
||||
* | Link
|
||||
* | null
|
||||
*/
|
||||
protected string $instrument;
|
||||
}
|
@ -1,45 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
/*
|
||||
* This file is part of the ActivityPhp package.
|
||||
*
|
||||
* Copyright (c) landrok at github.com/landrok
|
||||
*
|
||||
* For the full copyright and license information, please see
|
||||
* <https://github.com/landrok/activitypub/blob/master/LICENSE>.
|
||||
*/
|
||||
|
||||
namespace Plugin\ActivityPub\Util\Type\Core;
|
||||
|
||||
use Plugin\ActivityPub\Util\Type;
|
||||
|
||||
/**
|
||||
* \Plugin\ActivityPub\Util\Type\Core\Activity is an implementation of one of the
|
||||
* Activity Streams Core Types.
|
||||
*
|
||||
* Activity objects are specializations of the base Object type that
|
||||
* provide information about actions that have either already occurred,
|
||||
* are in the process of occurring, or may occur in the future.
|
||||
*
|
||||
* @see https://www.w3.org/TR/activitystreams-core/#activities
|
||||
*/
|
||||
class Activity extends AbstractActivity
|
||||
{
|
||||
protected string $type = 'Activity';
|
||||
|
||||
/**
|
||||
* Describes the direct object of the activity.
|
||||
* For instance, in the activity "John added a movie to his
|
||||
* wishlist", the object of the activity is the movie added.
|
||||
*
|
||||
* @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-object-term
|
||||
*
|
||||
* @var string
|
||||
* | ObjectType
|
||||
* | Link
|
||||
* | null
|
||||
*/
|
||||
protected ObjectType $object;
|
||||
}
|
@ -1,103 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
/*
|
||||
* This file is part of the ActivityPhp package.
|
||||
*
|
||||
* Copyright (c) landrok at github.com/landrok
|
||||
*
|
||||
* For the full copyright and license information, please see
|
||||
* <https://github.com/landrok/activitypub/blob/master/LICENSE>.
|
||||
*/
|
||||
|
||||
namespace Plugin\ActivityPub\Util\Type\Core;
|
||||
|
||||
/**
|
||||
* \Plugin\ActivityPub\Util\Type\Core\Collection is an implementation of one of the
|
||||
* Activity Streams Core Types.
|
||||
*
|
||||
* Collection objects are a specialization of the base Object that serve
|
||||
* as a container for other Objects or Links.
|
||||
*
|
||||
* @see https://www.w3.org/TR/activitystreams-core/#collections
|
||||
*/
|
||||
class Collection extends ObjectType
|
||||
{
|
||||
protected string $type = 'Collection';
|
||||
|
||||
public string $id;
|
||||
|
||||
/**
|
||||
* A non-negative integer specifying the total number of objects
|
||||
* contained by the logical view of the collection.
|
||||
* This number might not reflect the actual number of items
|
||||
* serialized within the Collection object instance.
|
||||
*
|
||||
* @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-totalitems
|
||||
*/
|
||||
protected int $totalItems;
|
||||
|
||||
/**
|
||||
* In a paged Collection, indicates the page that contains the most
|
||||
* recently updated member items.
|
||||
*
|
||||
* @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-current
|
||||
*
|
||||
* @var string
|
||||
* | Link
|
||||
* | CollectionPage
|
||||
* | null
|
||||
*/
|
||||
protected string $current;
|
||||
|
||||
/**
|
||||
* The furthest preceding page of items in the collection.
|
||||
*
|
||||
* @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-last
|
||||
*
|
||||
* @var string
|
||||
* | Link
|
||||
* | CollectionPage
|
||||
* | null
|
||||
*/
|
||||
protected string $first;
|
||||
|
||||
/**
|
||||
* The furthest proceeding page of the collection.
|
||||
*
|
||||
* @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-last
|
||||
*
|
||||
* @var string
|
||||
* | Link
|
||||
* | CollectionPage
|
||||
* | null
|
||||
*/
|
||||
protected string $last;
|
||||
|
||||
/**
|
||||
* The items contained in a collection.
|
||||
* The items are considered as unordered.
|
||||
*
|
||||
* @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-items
|
||||
*
|
||||
* @var array
|
||||
* | Link
|
||||
* | array<Link>
|
||||
* | array<ObjectType>
|
||||
*/
|
||||
protected array $items = [];
|
||||
|
||||
/**
|
||||
* The items contained in a collection.
|
||||
* The items are considered as ordered.
|
||||
*
|
||||
* @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-items
|
||||
*
|
||||
* @var array
|
||||
* | Link
|
||||
* | array<Link>
|
||||
* | array<ObjectType>
|
||||
*/
|
||||
protected array $orderedItems = [];
|
||||
}
|
@ -1,66 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
/*
|
||||
* This file is part of the ActivityPhp package.
|
||||
*
|
||||
* Copyright (c) landrok at github.com/landrok
|
||||
*
|
||||
* For the full copyright and license information, please see
|
||||
* <https://github.com/landrok/activitypub/blob/master/LICENSE>.
|
||||
*/
|
||||
|
||||
namespace Plugin\ActivityPub\Util\Type\Core;
|
||||
|
||||
/**
|
||||
* CollectionPage is an implementation of one
|
||||
* of the Activity Streams Core Types.
|
||||
*
|
||||
* Used to represent distinct subsets of items from a Collection.
|
||||
*
|
||||
* @see https://www.w3.org/TR/activitystreams-core/#paging
|
||||
*/
|
||||
class CollectionPage extends Collection
|
||||
{
|
||||
protected string $type = 'CollectionPage';
|
||||
|
||||
public string $id;
|
||||
|
||||
/**
|
||||
* Identifies the Collection to which CollectionPage objects items
|
||||
* belong.
|
||||
*
|
||||
* @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-partof
|
||||
*
|
||||
* @var string
|
||||
* | Link
|
||||
* | Collection
|
||||
* | null
|
||||
*/
|
||||
protected string $partOf;
|
||||
|
||||
/**
|
||||
* Indicates the next page of items.
|
||||
*
|
||||
* @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-next
|
||||
*
|
||||
* @var string
|
||||
* | Link
|
||||
* | CollectionPage
|
||||
* | null
|
||||
*/
|
||||
protected string $next;
|
||||
|
||||
/**
|
||||
* Identifies the previous page of items.
|
||||
*
|
||||
* @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-prev
|
||||
*
|
||||
* @var string
|
||||
* | Link
|
||||
* | CollectionPage
|
||||
* | null
|
||||
*/
|
||||
protected string $prev;
|
||||
}
|
@ -1,29 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
/*
|
||||
* This file is part of the ActivityPhp package.
|
||||
*
|
||||
* Copyright (c) landrok at github.com/landrok
|
||||
*
|
||||
* For the full copyright and license information, please see
|
||||
* <https://github.com/landrok/activitypub/blob/master/LICENSE>.
|
||||
*/
|
||||
|
||||
namespace Plugin\ActivityPub\Util\Type\Core;
|
||||
|
||||
/**
|
||||
* \Plugin\ActivityPub\Util\Type\Core\IntransitiveActivity is an implementation of
|
||||
* one of the Activity Streams Core Types.
|
||||
*
|
||||
* IntransitiveActivity objects are specializations of the Activity type
|
||||
* that represent intransitive actions. IntransitiveActivity objects do
|
||||
* not have an object property.
|
||||
*
|
||||
* @see https://www.w3.org/TR/activitystreams-core/#intransitiveactivities
|
||||
*/
|
||||
class IntransitiveActivity extends AbstractActivity
|
||||
{
|
||||
protected string $type = 'IntransitiveActivity';
|
||||
}
|
@ -1,116 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
/*
|
||||
* This file is part of the ActivityPhp package.
|
||||
*
|
||||
* Copyright (c) landrok at github.com/landrok
|
||||
*
|
||||
* For the full copyright and license information, please see
|
||||
* <https://github.com/landrok/activitypub/blob/master/LICENSE>.
|
||||
*/
|
||||
|
||||
namespace Plugin\ActivityPub\Util\Type\Core;
|
||||
|
||||
use Plugin\ActivityPub\Util\Type\AbstractObject;
|
||||
|
||||
/**
|
||||
* \Plugin\ActivityPub\Util\Type\Core\Link is an implementation of one of the
|
||||
* Activity Streams Core Types.
|
||||
*
|
||||
* A Link describes a qualified, indirect reference to another resource.
|
||||
* The properties of the Link object are not the properties of the
|
||||
* referenced resource, but are provided as hints for rendering agents
|
||||
* to understand how to make use of the resource.
|
||||
*
|
||||
* @see https://www.w3.org/TR/activitystreams-core/#link
|
||||
*/
|
||||
class Link extends AbstractObject
|
||||
{
|
||||
protected string $type = 'Link';
|
||||
|
||||
protected string $id;
|
||||
|
||||
/**
|
||||
* A simple, human-readable, plain-text name for the object.
|
||||
* HTML markup MUST NOT be included.
|
||||
*
|
||||
* @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-name
|
||||
*
|
||||
* @var null|string xsd:string
|
||||
*/
|
||||
protected ?string $name;
|
||||
|
||||
/**
|
||||
* The name MAY be expressed using multiple language-tagged values.
|
||||
*
|
||||
* @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-name
|
||||
*
|
||||
* @var null|array<string,string> rdf:langString
|
||||
*/
|
||||
protected ?array $nameMap;
|
||||
|
||||
/**
|
||||
* The target resource pointed to by a Link.
|
||||
*
|
||||
* @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-href
|
||||
*/
|
||||
protected ?string $href;
|
||||
|
||||
/**
|
||||
* Hints as to the language used by the target resource.
|
||||
* Value MUST be a BCP47 Language-Tag.
|
||||
*
|
||||
* @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-hreflang
|
||||
*/
|
||||
protected ?string $hreflang;
|
||||
|
||||
/**
|
||||
* The MIME media type of the referenced resource.
|
||||
*
|
||||
* @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-mediatype
|
||||
*/
|
||||
protected ?string $mediaType;
|
||||
|
||||
/**
|
||||
* A link relation associated with a Link.
|
||||
* The value MUST conform to both the HTML5
|
||||
* and RFC5988 "link relation" definitions.
|
||||
*
|
||||
* @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-rel
|
||||
*/
|
||||
protected string|array|null $rel;
|
||||
|
||||
/**
|
||||
* Specifies a hint as to the rendering height
|
||||
* in device-independentpixels of the linked resource
|
||||
*
|
||||
* @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-height
|
||||
*
|
||||
* @var null|int A non negative integer
|
||||
*/
|
||||
protected ?int $height;
|
||||
|
||||
/**
|
||||
* An entity that provides a preview of this link.
|
||||
*
|
||||
* @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-preview
|
||||
*
|
||||
* @var string
|
||||
* | Object
|
||||
* | Link
|
||||
* | null
|
||||
*/
|
||||
protected string $preview;
|
||||
|
||||
/**
|
||||
* On a Link, specifies a hint as to the rendering width in
|
||||
* device-independent pixels of the linked resource.
|
||||
*
|
||||
* @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-width
|
||||
*
|
||||
* @var null|int A non negative integer
|
||||
*/
|
||||
protected ?int $width;
|
||||
}
|
@ -1,423 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
/*
|
||||
* This file is part of the ActivityPhp package.
|
||||
*
|
||||
* Copyright (c) landrok at github.com/landrok
|
||||
*
|
||||
* For the full copyright and license information, please see
|
||||
* <https://github.com/landrok/activitypub/blob/master/LICENSE>.
|
||||
*/
|
||||
|
||||
namespace Plugin\ActivityPub\Util\Type\Core;
|
||||
|
||||
use Plugin\ActivityPub\Util\Type\AbstractObject;
|
||||
|
||||
/**
|
||||
* ObjectType is an implementation of one of the
|
||||
* Activity Streams Core Types.
|
||||
*
|
||||
* The Object is the primary base type for the Activity Streams
|
||||
* vocabulary.
|
||||
*
|
||||
* Note: Object is a reserved keyword in PHP. It has been suffixed with
|
||||
* 'Type' for this reason.
|
||||
*
|
||||
* @see https://www.w3.org/TR/activitystreams-core/#object
|
||||
*/
|
||||
class ObjectType extends AbstractObject
|
||||
{
|
||||
/**
|
||||
* The object's unique global identifier
|
||||
*
|
||||
* @see https://www.w3.org/TR/activitypub/#obj-id
|
||||
*/
|
||||
public string $id;
|
||||
|
||||
protected string $type = 'Object';
|
||||
|
||||
/**
|
||||
* A resource attached or related to an object that potentially
|
||||
* requires special handling.
|
||||
* The intent is to provide a model that is at least semantically
|
||||
* similar to attachments in email.
|
||||
*
|
||||
* @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-attachment
|
||||
*
|
||||
* @var string
|
||||
* | ObjectType
|
||||
* | Link
|
||||
* | array<ObjectType>
|
||||
* | array<Link>
|
||||
* | null
|
||||
*/
|
||||
protected string $attachment;
|
||||
|
||||
/**
|
||||
* One or more entities to which this object is attributed.
|
||||
* The attributed entities might not be Actors. For instance, an
|
||||
* object might be attributed to the completion of another activity.
|
||||
*
|
||||
* @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-attributedto
|
||||
*
|
||||
* @var string
|
||||
* | ObjectType
|
||||
* | Link
|
||||
* | array<ObjectType>
|
||||
* | array<Link>
|
||||
* | null
|
||||
*/
|
||||
protected string $attributedTo;
|
||||
|
||||
/**
|
||||
* One or more entities that represent the total population of
|
||||
* entities for which the object can considered to be relevant.
|
||||
*
|
||||
* @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-audience
|
||||
*
|
||||
* @var string
|
||||
* | ObjectType
|
||||
* | Link
|
||||
* | array<ObjectType>
|
||||
* | array<Link>
|
||||
* | null
|
||||
*/
|
||||
protected string $audience;
|
||||
|
||||
/**
|
||||
* The content or textual representation of the Object encoded as a
|
||||
* JSON string. By default, the value of content is HTML.
|
||||
* The mediaType property can be used in the object to indicate a
|
||||
* different content type.
|
||||
*
|
||||
* The content MAY be expressed using multiple language-tagged
|
||||
* values.
|
||||
*
|
||||
* @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-content
|
||||
*/
|
||||
protected ?string $content;
|
||||
|
||||
/**
|
||||
* The context within which the object exists or an activity was
|
||||
* performed.
|
||||
* The notion of "context" used is intentionally vague.
|
||||
* The intended function is to serve as a means of grouping objects
|
||||
* and activities that share a common originating context or
|
||||
* purpose. An example could be all activities relating to a common
|
||||
* project or event.
|
||||
*
|
||||
* @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-context
|
||||
*
|
||||
* @var string
|
||||
* | ObjectType
|
||||
* | Link
|
||||
* | null
|
||||
*/
|
||||
protected string $context;
|
||||
|
||||
/**
|
||||
* The content MAY be expressed using multiple language-tagged
|
||||
* values.
|
||||
*
|
||||
* @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-content
|
||||
*/
|
||||
protected ?array $contentMap;
|
||||
|
||||
/**
|
||||
* A simple, human-readable, plain-text name for the object.
|
||||
* HTML markup MUST NOT be included.
|
||||
*
|
||||
* @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-name
|
||||
*
|
||||
* @var null|string xsd:string
|
||||
*/
|
||||
protected ?string $name;
|
||||
|
||||
/**
|
||||
* The name MAY be expressed using multiple language-tagged values.
|
||||
*
|
||||
* @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-name
|
||||
*
|
||||
* @var null|array rdf:langString
|
||||
*/
|
||||
protected ?array $nameMap;
|
||||
|
||||
/**
|
||||
* The date and time describing the actual or expected ending time
|
||||
* of the object.
|
||||
* When used with an Activity object, for instance, the endTime
|
||||
* property specifies the moment the activity concluded or
|
||||
* is expected to conclude.
|
||||
*
|
||||
* @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-endtime
|
||||
*/
|
||||
protected ?string $endTime;
|
||||
|
||||
/**
|
||||
* The entity (e.g. an application) that generated the object.
|
||||
*/
|
||||
protected ?string $generator;
|
||||
|
||||
/**
|
||||
* An entity that describes an icon for this object.
|
||||
* The image should have an aspect ratio of one (horizontal)
|
||||
* to one (vertical) and should be suitable for presentation
|
||||
* at a small size.
|
||||
*
|
||||
* @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-icon
|
||||
*
|
||||
* @var string
|
||||
* | Image
|
||||
* | Link
|
||||
* | array<Image>
|
||||
* | array<Link>
|
||||
* | null
|
||||
*/
|
||||
protected string $icon;
|
||||
|
||||
/**
|
||||
* An entity that describes an image for this object.
|
||||
* Unlike the icon property, there are no aspect ratio
|
||||
* or display size limitations assumed.
|
||||
*
|
||||
* @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-image-term
|
||||
*
|
||||
* @var string
|
||||
* | Image
|
||||
* | Link
|
||||
* | array<Image>
|
||||
* | array<Link>
|
||||
* | null
|
||||
*/
|
||||
protected string $image;
|
||||
|
||||
/**
|
||||
* One or more entities for which this object is considered a
|
||||
* response.
|
||||
*
|
||||
* @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-inreplyto
|
||||
*
|
||||
* @var string
|
||||
* | ObjectType
|
||||
* | Link
|
||||
* | array<ObjectType>
|
||||
* | array<Link>
|
||||
* | null
|
||||
*/
|
||||
protected string $inReplyTo;
|
||||
|
||||
/**
|
||||
* One or more physical or logical locations associated with the
|
||||
* object.
|
||||
*
|
||||
* @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-location
|
||||
*
|
||||
* @var string
|
||||
* | ObjectType
|
||||
* | Link
|
||||
* | array<ObjectType>
|
||||
* | array<Link>
|
||||
* | null
|
||||
*/
|
||||
protected string $location;
|
||||
|
||||
/**
|
||||
* An entity that provides a preview of this object.
|
||||
*
|
||||
* @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-preview
|
||||
*
|
||||
* @var string
|
||||
* | ObjectType
|
||||
* | Link
|
||||
* | null
|
||||
*/
|
||||
protected string $preview;
|
||||
|
||||
/**
|
||||
* The date and time at which the object was published
|
||||
*
|
||||
* @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-published
|
||||
*
|
||||
* @var null|string xsd:dateTime
|
||||
*/
|
||||
protected ?string $published;
|
||||
|
||||
/**
|
||||
* A Collection containing objects considered to be responses to
|
||||
* this object.
|
||||
*
|
||||
* @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-replies
|
||||
*
|
||||
* @var string
|
||||
* | Collection
|
||||
* | Link
|
||||
* | null
|
||||
*/
|
||||
protected string $replies;
|
||||
|
||||
/**
|
||||
* The date and time describing the actual or expected starting time
|
||||
* of the object.
|
||||
* When used with an Activity object, for instance, the startTime
|
||||
* property specifies the moment the activity began
|
||||
* or is scheduled to begin.
|
||||
*
|
||||
* @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-starttime
|
||||
*
|
||||
* @var null|string xsd:dateTime
|
||||
*/
|
||||
protected ?string $startTime;
|
||||
|
||||
/**
|
||||
* A natural language summarization of the object encoded as HTML.
|
||||
* Multiple language tagged summaries MAY be provided.
|
||||
*
|
||||
* @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-summary
|
||||
*
|
||||
* @var string
|
||||
* | ObjectType
|
||||
* | Link
|
||||
* | null
|
||||
*/
|
||||
protected string $summary;
|
||||
|
||||
/**
|
||||
* The content MAY be expressed using multiple language-tagged
|
||||
* values.
|
||||
*
|
||||
* @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-summary
|
||||
*
|
||||
* @var null|array<string>
|
||||
*/
|
||||
protected mixed $summaryMap;
|
||||
|
||||
/**
|
||||
* One or more "tags" that have been associated with an objects.
|
||||
* A tag can be any kind of Object.
|
||||
* The key difference between attachment and tag is that the former
|
||||
* implies association by inclusion, while the latter implies
|
||||
* associated by reference.
|
||||
*
|
||||
* @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-tag
|
||||
*
|
||||
* @var string
|
||||
* | ObjectType
|
||||
* | Link
|
||||
* | array<ObjectType>
|
||||
* | array<Link>
|
||||
* | null
|
||||
*/
|
||||
protected string $tag;
|
||||
|
||||
/**
|
||||
* The date and time at which the object was updated
|
||||
*
|
||||
* @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-updated
|
||||
*
|
||||
* @var null|string xsd:dateTime
|
||||
*/
|
||||
protected ?string $updated;
|
||||
|
||||
/**
|
||||
* One or more links to representations of the object.
|
||||
*
|
||||
* @var string
|
||||
* | array<string>
|
||||
* | Link
|
||||
* | array<Link>
|
||||
* | null
|
||||
*/
|
||||
protected string $url;
|
||||
|
||||
/**
|
||||
* An entity considered to be part of the public primary audience
|
||||
* of an Object
|
||||
*
|
||||
* @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-to
|
||||
*
|
||||
* @var string
|
||||
* | ObjectType
|
||||
* | Link
|
||||
* | array<ObjectType>
|
||||
* | array<Link>
|
||||
* | null
|
||||
*/
|
||||
protected string $to;
|
||||
|
||||
/**
|
||||
* An Object that is part of the private primary audience of this
|
||||
* Object.
|
||||
*
|
||||
* @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-bto
|
||||
*
|
||||
* @var string
|
||||
* | ObjectType
|
||||
* | Link
|
||||
* | array<ObjectType>
|
||||
* | array<Link>
|
||||
* | null
|
||||
*/
|
||||
protected string $bto;
|
||||
|
||||
/**
|
||||
* An Object that is part of the public secondary audience of this
|
||||
* Object.
|
||||
*
|
||||
* @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-cc
|
||||
*
|
||||
* @var string
|
||||
* | ObjectType
|
||||
* | Link
|
||||
* | array<ObjectType>
|
||||
* | array<Link>
|
||||
* | null
|
||||
*/
|
||||
protected string $cc;
|
||||
|
||||
/**
|
||||
* One or more Objects that are part of the private secondary
|
||||
* audience of this Object.
|
||||
*
|
||||
* @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-bcc
|
||||
*
|
||||
* @var string
|
||||
* | ObjectType
|
||||
* | Link
|
||||
* | array<ObjectType>
|
||||
* | array<Link>
|
||||
* | null
|
||||
*/
|
||||
protected string $bcc;
|
||||
|
||||
/**
|
||||
* The MIME media type of the value of the content property.
|
||||
* If not specified, the content property is assumed to contain
|
||||
* text/html content.
|
||||
*
|
||||
* @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-mediatype
|
||||
*/
|
||||
protected ?string $mediaType;
|
||||
|
||||
/**
|
||||
* When the object describes a time-bound resource, such as an audio
|
||||
* or video, a meeting, etc, the duration property indicates the
|
||||
* object's approximate duration.
|
||||
* The value MUST be expressed as an xsd:duration as defined by
|
||||
* xmlschema11-2, section 3.3.6 (e.g. a period of 5 seconds is
|
||||
* represented as "PT5S").
|
||||
*
|
||||
* @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-duration
|
||||
*/
|
||||
protected ?string $duration;
|
||||
|
||||
/**
|
||||
* Intended to convey some sort of source from which the content
|
||||
* markup was derived, as a form of provenance, or to support
|
||||
* future editing by clients.
|
||||
*
|
||||
* @see https://www.w3.org/TR/activitypub/#source-property
|
||||
*/
|
||||
protected ObjectType $source;
|
||||
}
|
@ -1,28 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
/*
|
||||
* This file is part of the ActivityPhp package.
|
||||
*
|
||||
* Copyright (c) landrok at github.com/landrok
|
||||
*
|
||||
* For the full copyright and license information, please see
|
||||
* <https://github.com/landrok/activitypub/blob/master/LICENSE>.
|
||||
*/
|
||||
|
||||
namespace Plugin\ActivityPub\Util\Type\Core;
|
||||
|
||||
/**
|
||||
* \Plugin\ActivityPub\Util\Type\Core\OrderedCollection is an implementation of one
|
||||
* of the Activity Streams Core Types.
|
||||
*
|
||||
* A subtype of Collection in which members of the logical collection
|
||||
* are assumed to always be strictly ordered.
|
||||
*
|
||||
* @see https://www.w3.org/TR/activitystreams-core/#collections
|
||||
*/
|
||||
class OrderedCollection extends Collection
|
||||
{
|
||||
protected string $type = 'OrderedCollection';
|
||||
}
|
@ -1,38 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
/*
|
||||
* This file is part of the ActivityPhp package.
|
||||
*
|
||||
* Copyright (c) landrok at github.com/landrok
|
||||
*
|
||||
* For the full copyright and license information, please see
|
||||
* <https://github.com/landrok/activitypub/blob/master/LICENSE>.
|
||||
*/
|
||||
|
||||
namespace Plugin\ActivityPub\Util\Type\Core;
|
||||
|
||||
/**
|
||||
* \Plugin\ActivityPub\Util\Type\Core\OrderedCollection is an implementation of one
|
||||
* of the Activity Streams Core Types.
|
||||
*
|
||||
* The OrderedCollectionPage type extends from both CollectionPage and
|
||||
* OrderedCollection. In addition to the properties inherited from each
|
||||
* of those, the OrderedCollectionPage may contain an additional
|
||||
* startIndex property whose value indicates the relative index position
|
||||
* of the first item contained by the page within the OrderedCollection
|
||||
* to which the page belongs.
|
||||
*
|
||||
* @see https://www.w3.org/TR/activitystreams-core/#paging
|
||||
*/
|
||||
class OrderedCollectionPage extends CollectionPage
|
||||
{
|
||||
protected string $type = 'OrderedCollectionPage';
|
||||
|
||||
/**
|
||||
* A non-negative integer value identifying the relative position
|
||||
* within the logical view of a strictly ordered collection.
|
||||
*/
|
||||
protected int $startIndex;
|
||||
}
|
@ -1,114 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
/*
|
||||
* This file is part of the ActivityPhp package.
|
||||
*
|
||||
* Copyright (c) landrok at github.com/landrok
|
||||
*
|
||||
* For the full copyright and license information, please see
|
||||
* <https://github.com/landrok/activitypub/blob/master/LICENSE>.
|
||||
*/
|
||||
|
||||
namespace Plugin\ActivityPub\Util\Type\Extended;
|
||||
|
||||
use Plugin\ActivityPub\Util\Type\Core\ObjectType;
|
||||
use Plugin\ActivityPub\Util\Type\Core\OrderedCollection;
|
||||
|
||||
/**
|
||||
* \ActivityPhp\Type\Extended\AbstractActor is an abstract class that
|
||||
* provides dedicated Actor's properties
|
||||
*/
|
||||
abstract class AbstractActor extends ObjectType
|
||||
{
|
||||
/**
|
||||
* A reference to an ActivityStreams OrderedCollection comprised of
|
||||
* all the messages received by the actor.
|
||||
*
|
||||
* @see https://www.w3.org/TR/activitypub/#inbox
|
||||
*
|
||||
* @var OrderedCollection
|
||||
* | \ActivityPhp\Type\Core\OrderedCollectionPage
|
||||
* | null
|
||||
*/
|
||||
protected OrderedCollection $inbox;
|
||||
|
||||
/**
|
||||
* A reference to an ActivityStreams OrderedCollection comprised of
|
||||
* all the messages produced by the actor.
|
||||
*
|
||||
* @see https://www.w3.org/TR/activitypub/#outbox
|
||||
*
|
||||
* @var OrderedCollection
|
||||
* | \ActivityPhp\Type\Core\OrderedCollectionPage
|
||||
* | null
|
||||
*/
|
||||
protected OrderedCollection $outbox;
|
||||
|
||||
/**
|
||||
* A link to an ActivityStreams collection of the actors that this
|
||||
* actor is following.
|
||||
*
|
||||
* @see https://www.w3.org/TR/activitypub/#following
|
||||
*/
|
||||
protected string $following;
|
||||
|
||||
/**
|
||||
* A link to an ActivityStreams collection of the actors that
|
||||
* follow this actor.
|
||||
*
|
||||
* @see https://www.w3.org/TR/activitypub/#followers
|
||||
*/
|
||||
protected string $followers;
|
||||
|
||||
/**
|
||||
* A link to an ActivityStreams collection of objects this actor has
|
||||
* liked.
|
||||
*
|
||||
* @see https://www.w3.org/TR/activitypub/#liked
|
||||
*/
|
||||
protected string $liked;
|
||||
|
||||
/**
|
||||
* A list of supplementary Collections which may be of interest.
|
||||
*
|
||||
* @see https://www.w3.org/TR/activitypub/#streams-property
|
||||
*/
|
||||
protected array $streams = [];
|
||||
|
||||
/**
|
||||
* A short username which may be used to refer to the actor, with no
|
||||
* uniqueness guarantees.
|
||||
*
|
||||
* @see https://www.w3.org/TR/activitypub/#preferredUsername
|
||||
*/
|
||||
protected ?string $preferredUsername;
|
||||
|
||||
/**
|
||||
* A JSON object which maps additional typically server/domain-wide
|
||||
* endpoints which may be useful either for this actor or someone
|
||||
* referencing this actor. This mapping may be nested inside the
|
||||
* actor document as the value or may be a link to a JSON-LD
|
||||
* document with these properties.
|
||||
*
|
||||
* @see https://www.w3.org/TR/activitypub/#endpoints
|
||||
*/
|
||||
protected string|array|null $endpoints;
|
||||
|
||||
/**
|
||||
* It's not part of the ActivityPub protocol, but it's a quite common
|
||||
* practice handling an actor public key with a publicKey array:
|
||||
* [
|
||||
* 'id' => 'https://my-example.com/actor#main-key'
|
||||
* 'owner' => 'https://my-example.com/actor',
|
||||
* 'publicKeyPem' => '-----BEGIN PUBLIC KEY-----
|
||||
* MIIBI [...]
|
||||
* DQIDAQAB
|
||||
* -----END PUBLIC KEY-----'
|
||||
* ]
|
||||
*
|
||||
* @see https://www.w3.org/wiki/SocialCG/ActivityPub/Authentication_Authorization#Signing_requests_using_HTTP_Signatures
|
||||
*/
|
||||
protected string|array|null $publicKey;
|
||||
}
|
@ -1,31 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
/*
|
||||
* This file is part of the ActivityPhp package.
|
||||
*
|
||||
* Copyright (c) landrok at github.com/landrok
|
||||
*
|
||||
* For the full copyright and license information, please see
|
||||
* <https://github.com/landrok/activitypub/blob/master/LICENSE>.
|
||||
*/
|
||||
|
||||
namespace Plugin\ActivityPub\Util\Type\Extended\Activity;
|
||||
|
||||
use Plugin\ActivityPub\Util\Type\Core\Activity;
|
||||
|
||||
/**
|
||||
* \Plugin\ActivityPub\Util\Type\Extended\Activity\Accept is an implementation of
|
||||
* one of the Activity Streams Extended Types.
|
||||
*
|
||||
* Indicates that the actor accepts the object. The target property can
|
||||
* be used in certain circumstances to indicate the context into which
|
||||
* the object has been accepted.
|
||||
*
|
||||
* @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-accept
|
||||
*/
|
||||
class Accept extends Activity
|
||||
{
|
||||
protected string $type = 'Accept';
|
||||
}
|
@ -1,30 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
/*
|
||||
* This file is part of the ActivityPhp package.
|
||||
*
|
||||
* Copyright (c) landrok at github.com/landrok
|
||||
*
|
||||
* For the full copyright and license information, please see
|
||||
* <https://github.com/landrok/activitypub/blob/master/LICENSE>.
|
||||
*/
|
||||
|
||||
namespace Plugin\ActivityPub\Util\Type\Extended\Activity;
|
||||
|
||||
use Plugin\ActivityPub\Util\Type\Core\Activity;
|
||||
|
||||
/**
|
||||
* \Plugin\ActivityPub\Util\Type\Extended\Activity\Announce is an implementation of
|
||||
* one of the Activity Streams Extended Types.
|
||||
*
|
||||
* Indicates that the actor is calling the target's attention the
|
||||
* object.
|
||||
*
|
||||
* @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-announce
|
||||
*/
|
||||
class Announce extends Activity
|
||||
{
|
||||
protected string $type = 'Announce';
|
||||
}
|
@ -1,30 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
/*
|
||||
* This file is part of the ActivityPhp package.
|
||||
*
|
||||
* Copyright (c) landrok at github.com/landrok
|
||||
*
|
||||
* For the full copyright and license information, please see
|
||||
* <https://github.com/landrok/activitypub/blob/master/LICENSE>.
|
||||
*/
|
||||
|
||||
namespace Plugin\ActivityPub\Util\Type\Extended\Activity;
|
||||
|
||||
/**
|
||||
* \Plugin\ActivityPub\Util\Type\Extended\Activity\Block is an implementation of
|
||||
* one of the Activity Streams Extended Types.
|
||||
*
|
||||
* Indicates that the actor is blocking the object. Blocking is a
|
||||
* stronger form of Ignore. The typical use is to support social systems
|
||||
* that allow one user to block activities or content of other users.
|
||||
* The target and origin typically have no defined meaning.
|
||||
*
|
||||
* @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-block
|
||||
*/
|
||||
class Block extends Ignore
|
||||
{
|
||||
protected string $type = 'Block';
|
||||
}
|
@ -1,29 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
/*
|
||||
* This file is part of the ActivityPhp package.
|
||||
*
|
||||
* Copyright (c) landrok at github.com/landrok
|
||||
*
|
||||
* For the full copyright and license information, please see
|
||||
* <https://github.com/landrok/activitypub/blob/master/LICENSE>.
|
||||
*/
|
||||
|
||||
namespace Plugin\ActivityPub\Util\Type\Extended\Activity;
|
||||
|
||||
use Plugin\ActivityPub\Util\Type\Core\Activity;
|
||||
|
||||
/**
|
||||
* \Plugin\ActivityPub\Util\Type\Extended\Activity\Create is an implementation of
|
||||
* one of the Activity Streams Extended Types.
|
||||
*
|
||||
* Indicates that the actor has created the object.
|
||||
*
|
||||
* @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-create
|
||||
*/
|
||||
class Create extends Activity
|
||||
{
|
||||
protected string $type = 'Create';
|
||||
}
|
@ -1,30 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
/*
|
||||
* This file is part of the ActivityPhp package.
|
||||
*
|
||||
* Copyright (c) landrok at github.com/landrok
|
||||
*
|
||||
* For the full copyright and license information, please see
|
||||
* <https://github.com/landrok/activitypub/blob/master/LICENSE>.
|
||||
*/
|
||||
|
||||
namespace Plugin\ActivityPub\Util\Type\Extended\Activity;
|
||||
|
||||
use Plugin\ActivityPub\Util\Type\Core\Activity;
|
||||
|
||||
/**
|
||||
* \Plugin\ActivityPub\Util\Type\Extended\Activity\Delete is an implementation of
|
||||
* one of the Activity Streams Extended Types.
|
||||
*
|
||||
* Indicates that the actor has deleted the object. If specified, the
|
||||
* origin indicates the context from which the object was deleted.
|
||||
*
|
||||
* @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-delete
|
||||
*/
|
||||
class Delete extends Activity
|
||||
{
|
||||
protected string $type = 'Delete';
|
||||
}
|
@ -1,33 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
/*
|
||||
* This file is part of the ActivityPhp package.
|
||||
*
|
||||
* Copyright (c) landrok at github.com/landrok
|
||||
*
|
||||
* For the full copyright and license information, please see
|
||||
* <https://github.com/landrok/activitypub/blob/master/LICENSE>.
|
||||
*/
|
||||
|
||||
namespace Plugin\ActivityPub\Util\Type\Extended\Activity;
|
||||
|
||||
use Plugin\ActivityPub\Util\Type\Core\Activity;
|
||||
|
||||
/**
|
||||
* \Plugin\ActivityPub\Util\Type\Extended\Activity\Follow is an implementation of
|
||||
* one of the Activity Streams Extended Types.
|
||||
*
|
||||
* Indicates that the actor is "following" the object. Following is
|
||||
* defined in the sense typically used within Social systems in which
|
||||
* the actor is interested in any activity performed by or on the
|
||||
* object.
|
||||
* The target and origin typically have no defined meaning.
|
||||
*
|
||||
* @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-follow
|
||||
*/
|
||||
class Follow extends Activity
|
||||
{
|
||||
protected string $type = 'Follow';
|
||||
}
|
@ -1,30 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
/*
|
||||
* This file is part of the ActivityPhp package.
|
||||
*
|
||||
* Copyright (c) landrok at github.com/landrok
|
||||
*
|
||||
* For the full copyright and license information, please see
|
||||
* <https://github.com/landrok/activitypub/blob/master/LICENSE>.
|
||||
*/
|
||||
|
||||
namespace Plugin\ActivityPub\Util\Type\Extended\Activity;
|
||||
|
||||
use Plugin\ActivityPub\Util\Type\Core\Activity;
|
||||
|
||||
/**
|
||||
* \ActivityPhp\Type\Extended\Activity\Ignore is an implementation of
|
||||
* one of the Activity Streams Extended Types.
|
||||
*
|
||||
* Indicates that the actor is ignoring the object.
|
||||
* The target and origin typically have no defined meaning.
|
||||
*
|
||||
* @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-ignore
|
||||
*/
|
||||
class Ignore extends Activity
|
||||
{
|
||||
protected string $type = 'Ignore';
|
||||
}
|
@ -1,30 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
/*
|
||||
* This file is part of the ActivityPhp package.
|
||||
*
|
||||
* Copyright (c) landrok at github.com/landrok
|
||||
*
|
||||
* For the full copyright and license information, please see
|
||||
* <https://github.com/landrok/activitypub/blob/master/LICENSE>.
|
||||
*/
|
||||
|
||||
namespace Plugin\ActivityPub\Util\Type\Extended\Activity;
|
||||
|
||||
use Plugin\ActivityPub\Util\Type\Core\Activity;
|
||||
|
||||
/**
|
||||
* \Plugin\ActivityPub\Util\Type\Extended\Activity\Join is an implementation of
|
||||
* one of the Activity Streams Extended Types.
|
||||
*
|
||||
* Indicates that the actor has joined the object.
|
||||
* The target and origin typically have no defined meaning.
|
||||
*
|
||||
* @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-join
|
||||
*/
|
||||
class Join extends Activity
|
||||
{
|
||||
protected string $type = 'Join';
|
||||
}
|
@ -1,30 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
/*
|
||||
* This file is part of the ActivityPhp package.
|
||||
*
|
||||
* Copyright (c) landrok at github.com/landrok
|
||||
*
|
||||
* For the full copyright and license information, please see
|
||||
* <https://github.com/landrok/activitypub/blob/master/LICENSE>.
|
||||
*/
|
||||
|
||||
namespace Plugin\ActivityPub\Util\Type\Extended\Activity;
|
||||
|
||||
use Plugin\ActivityPub\Util\Type\Core\Activity;
|
||||
|
||||
/**
|
||||
* \Plugin\ActivityPub\Util\Type\Extended\Activity\Leave is an implementation of
|
||||
* one of the Activity Streams Extended Types.
|
||||
*
|
||||
* Indicates that the actor has left the object.
|
||||
* The target and origin typically have no meaning.
|
||||
*
|
||||
* @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-leave
|
||||
*/
|
||||
class Leave extends Activity
|
||||
{
|
||||
protected string $type = 'Leave';
|
||||
}
|
@ -1,30 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
/*
|
||||
* This file is part of the ActivityPhp package.
|
||||
*
|
||||
* Copyright (c) landrok at github.com/landrok
|
||||
*
|
||||
* For the full copyright and license information, please see
|
||||
* <https://github.com/landrok/activitypub/blob/master/LICENSE>.
|
||||
*/
|
||||
|
||||
namespace Plugin\ActivityPub\Util\Type\Extended\Activity;
|
||||
|
||||
use Plugin\ActivityPub\Util\Type\Core\Activity;
|
||||
|
||||
/**
|
||||
* \Plugin\ActivityPub\Util\Type\Extended\Activity\Like is an implementation of
|
||||
* one of the Activity Streams Extended Types.
|
||||
*
|
||||
* Indicates that the actor likes, recommends or endorses the object.
|
||||
* The target and origin typically have no defined meaning.
|
||||
*
|
||||
* @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-like
|
||||
*/
|
||||
class Like extends Activity
|
||||
{
|
||||
protected string $type = 'Like';
|
||||
}
|
@ -1,75 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
/*
|
||||
* This file is part of the ActivityPhp package.
|
||||
*
|
||||
* Copyright (c) landrok at github.com/landrok
|
||||
*
|
||||
* For the full copyright and license information, please see
|
||||
* <https://github.com/landrok/activitypub/blob/master/LICENSE>.
|
||||
*/
|
||||
|
||||
namespace Plugin\ActivityPub\Util\Type\Extended\Activity;
|
||||
|
||||
use Plugin\ActivityPub\Util\Type\Core\IntransitiveActivity;
|
||||
use Plugin\ActivityPub\Util\Type\Core\ObjectType;
|
||||
|
||||
/**
|
||||
* \Plugin\ActivityPub\Util\Type\Extended\Activity\Question is an implementation of
|
||||
* one of the Activity Streams Extended Types.
|
||||
*
|
||||
* Represents a question being asked. Question objects are an extension
|
||||
* of IntransitiveActivity. That is, the Question object is an Activity,
|
||||
* but the direct object is the question itself, and therefore it would
|
||||
* not contain an object property.
|
||||
*
|
||||
* Either of the anyOf and oneOf properties MAY be used to express
|
||||
* possible answers, but a Question object MUST NOT have both properties
|
||||
*
|
||||
* @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-move
|
||||
*/
|
||||
class Question extends IntransitiveActivity
|
||||
{
|
||||
protected string $type = 'Question';
|
||||
|
||||
/**
|
||||
* An exclusive option for a Question
|
||||
* Use of oneOf implies that the Question can have only a
|
||||
* single answer.
|
||||
*
|
||||
* @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-oneof
|
||||
*
|
||||
* @var array<ObjectType>
|
||||
* | array<\Plugin\ActivityPub\Util\Type\Core\Link>
|
||||
* | null
|
||||
*/
|
||||
protected array $oneOf;
|
||||
|
||||
/**
|
||||
* An inclusive option for a Question.
|
||||
* Use of anyOf implies that the Question can have multiple answers.
|
||||
*
|
||||
* @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-anyof
|
||||
*
|
||||
* @var array<ObjectType>
|
||||
* | array<\Plugin\ActivityPub\Util\Type\Core\Link>
|
||||
* | null
|
||||
*/
|
||||
protected array $anyOf;
|
||||
|
||||
/**
|
||||
* Indicates that a question has been closed, and answers are no
|
||||
* longer accepted.
|
||||
*
|
||||
* @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-closed
|
||||
*
|
||||
* @var ObjectType
|
||||
* | \Plugin\ActivityPub\Util\Type\Core\Link
|
||||
* | \DateTime
|
||||
* | bool
|
||||
* | null
|
||||
*/
|
||||
protected ObjectType $closed;
|
||||
}
|
@ -1,30 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
/*
|
||||
* This file is part of the ActivityPhp package.
|
||||
*
|
||||
* Copyright (c) landrok at github.com/landrok
|
||||
*
|
||||
* For the full copyright and license information, please see
|
||||
* <https://github.com/landrok/activitypub/blob/master/LICENSE>.
|
||||
*/
|
||||
|
||||
namespace Plugin\ActivityPub\Util\Type\Extended\Activity;
|
||||
|
||||
use Plugin\ActivityPub\Util\Type\Core\Activity;
|
||||
|
||||
/**
|
||||
* \Plugin\ActivityPub\Util\Type\Extended\Activity\Reject is an implementation of
|
||||
* one of the Activity Streams Extended Types.
|
||||
*
|
||||
* Indicates that the actor is rejecting the object.
|
||||
* The target and origin typically have no defined meaning.
|
||||
*
|
||||
* @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-reject
|
||||
*/
|
||||
class Reject extends Activity
|
||||
{
|
||||
protected string $type = 'Reject';
|
||||
}
|
@ -1,31 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
/*
|
||||
* This file is part of the ActivityPhp package.
|
||||
*
|
||||
* Copyright (c) landrok at github.com/landrok
|
||||
*
|
||||
* For the full copyright and license information, please see
|
||||
* <https://github.com/landrok/activitypub/blob/master/LICENSE>.
|
||||
*/
|
||||
|
||||
namespace Plugin\ActivityPub\Util\Type\Extended\Activity;
|
||||
|
||||
use Plugin\ActivityPub\Util\Type\Core\Activity;
|
||||
|
||||
/**
|
||||
* \Plugin\ActivityPub\Util\Type\Extended\Activity\Remove is an implementation of
|
||||
* one of the Activity Streams Extended Types.
|
||||
*
|
||||
* Indicates that the actor is removing the object.
|
||||
* If specified, the origin indicates the context from which the object
|
||||
* is being removed.
|
||||
*
|
||||
* @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-remove
|
||||
*/
|
||||
class Remove extends Activity
|
||||
{
|
||||
protected string $type = 'Remove';
|
||||
}
|
@ -1,35 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
/*
|
||||
* This file is part of the ActivityPhp package.
|
||||
*
|
||||
* Copyright (c) landrok at github.com/landrok
|
||||
*
|
||||
* For the full copyright and license information, please see
|
||||
* <https://github.com/landrok/activitypub/blob/master/LICENSE>.
|
||||
*/
|
||||
|
||||
namespace Plugin\ActivityPub\Util\Type\Extended\Activity;
|
||||
|
||||
use Plugin\ActivityPub\Util\Type\Core\Activity;
|
||||
|
||||
/**
|
||||
* \Plugin\ActivityPub\Util\Type\Extended\Activity\Undo is an implementation of
|
||||
* one of the Activity Streams Extended Types.
|
||||
*
|
||||
* Indicates that the actor is undoing the object. In most cases, the
|
||||
* object will be an Activity describing some previously performed
|
||||
* action (for instance, a person may have previously "liked" an article
|
||||
* but, for whatever reason, might choose to undo that like at some
|
||||
* later point in time).
|
||||
*
|
||||
* The target and origin typically have no defined meaning.
|
||||
*
|
||||
* @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-undo
|
||||
*/
|
||||
class Undo extends Activity
|
||||
{
|
||||
protected string $type = 'Undo';
|
||||
}
|
@ -1,33 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
/*
|
||||
* This file is part of the ActivityPhp package.
|
||||
*
|
||||
* Copyright (c) landrok at github.com/landrok
|
||||
*
|
||||
* For the full copyright and license information, please see
|
||||
* <https://github.com/landrok/activitypub/blob/master/LICENSE>.
|
||||
*/
|
||||
|
||||
namespace Plugin\ActivityPub\Util\Type\Extended\Activity;
|
||||
|
||||
use Plugin\ActivityPub\Util\Type\Core\Activity;
|
||||
|
||||
/**
|
||||
* \Plugin\ActivityPub\Util\Type\Extended\Activity\Update is an implementation of
|
||||
* one of the Activity Streams Extended Types.
|
||||
*
|
||||
* Indicates that the actor has updated the object. Note, however, that
|
||||
* this vocabulary does not define a mechanism for describing the actual
|
||||
* set of modifications made to object.
|
||||
*
|
||||
* The target and origin typically have no defined meaning.
|
||||
*
|
||||
* @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-update
|
||||
*/
|
||||
class Update extends Activity
|
||||
{
|
||||
protected string $type = 'Update';
|
||||
}
|
@ -1,29 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
/*
|
||||
* This file is part of the ActivityPhp package.
|
||||
*
|
||||
* Copyright (c) landrok at github.com/landrok
|
||||
*
|
||||
* For the full copyright and license information, please see
|
||||
* <https://github.com/landrok/activitypub/blob/master/LICENSE>.
|
||||
*/
|
||||
|
||||
namespace Plugin\ActivityPub\Util\Type\Extended\Actor;
|
||||
|
||||
use Plugin\ActivityPub\Util\Type\Extended\AbstractActor;
|
||||
|
||||
/**
|
||||
* \Plugin\ActivityPub\Util\Type\Extended\Actor\Application is an implementation of
|
||||
* one of the Activity Streams Extended Types.
|
||||
*
|
||||
* Describes a software application.
|
||||
*
|
||||
* @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-application
|
||||
*/
|
||||
class Application extends AbstractActor
|
||||
{
|
||||
protected string $type = 'Application';
|
||||
}
|
@ -1,29 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
/*
|
||||
* This file is part of the ActivityPhp package.
|
||||
*
|
||||
* Copyright (c) landrok at github.com/landrok
|
||||
*
|
||||
* For the full copyright and license information, please see
|
||||
* <https://github.com/landrok/activitypub/blob/master/LICENSE>.
|
||||
*/
|
||||
|
||||
namespace Plugin\ActivityPub\Util\Type\Extended\Actor;
|
||||
|
||||
use Plugin\ActivityPub\Util\Type\Extended\AbstractActor;
|
||||
|
||||
/**
|
||||
* \Plugin\ActivityPub\Util\Type\Extended\Actor\Group is an implementation of
|
||||
* one of the Activity Streams Extended Types.
|
||||
*
|
||||
* Represents a formal or informal collective of Actors.
|
||||
*
|
||||
* @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-group
|
||||
*/
|
||||
class Group extends AbstractActor
|
||||
{
|
||||
protected string $type = 'Group';
|
||||
}
|
@ -1,29 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
/*
|
||||
* This file is part of the ActivityPhp package.
|
||||
*
|
||||
* Copyright (c) landrok at github.com/landrok
|
||||
*
|
||||
* For the full copyright and license information, please see
|
||||
* <https://github.com/landrok/activitypub/blob/master/LICENSE>.
|
||||
*/
|
||||
|
||||
namespace Plugin\ActivityPub\Util\Type\Extended\Actor;
|
||||
|
||||
use Plugin\ActivityPub\Util\Type\Extended\AbstractActor;
|
||||
|
||||
/**
|
||||
* \Plugin\ActivityPub\Util\Type\Extended\Actor\Organization is an implementation of
|
||||
* one of the Activity Streams Extended Types.
|
||||
*
|
||||
* Represents a formal or informal collective of Actors.
|
||||
*
|
||||
* @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-organization
|
||||
*/
|
||||
class Organization extends AbstractActor
|
||||
{
|
||||
protected string $type = 'Organization';
|
||||
}
|
@ -1,29 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
/*
|
||||
* This file is part of the ActivityPhp package.
|
||||
*
|
||||
* Copyright (c) landrok at github.com/landrok
|
||||
*
|
||||
* For the full copyright and license information, please see
|
||||
* <https://github.com/landrok/activitypub/blob/master/LICENSE>.
|
||||
*/
|
||||
|
||||
namespace Plugin\ActivityPub\Util\Type\Extended\Actor;
|
||||
|
||||
use Plugin\ActivityPub\Util\Type\Extended\AbstractActor;
|
||||
|
||||
/**
|
||||
* \Plugin\ActivityPub\Util\Type\Extended\Actor\Person is an implementation of
|
||||
* one of the Activity Streams Extended Types.
|
||||
*
|
||||
* Represents an individual person.
|
||||
*
|
||||
* @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-person
|
||||
*/
|
||||
class Person extends AbstractActor
|
||||
{
|
||||
protected string $type = 'Person';
|
||||
}
|
@ -1,29 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
/*
|
||||
* This file is part of the ActivityPhp package.
|
||||
*
|
||||
* Copyright (c) landrok at github.com/landrok
|
||||
*
|
||||
* For the full copyright and license information, please see
|
||||
* <https://github.com/landrok/activitypub/blob/master/LICENSE>.
|
||||
*/
|
||||
|
||||
namespace Plugin\ActivityPub\Util\Type\Extended\Actor;
|
||||
|
||||
use Plugin\ActivityPub\Util\Type\Extended\AbstractActor;
|
||||
|
||||
/**
|
||||
* \Plugin\ActivityPub\Util\Type\Extended\Actor\Service is an implementation of
|
||||
* one of the Activity Streams Extended Types.
|
||||
*
|
||||
* Represents a service of any kind.
|
||||
*
|
||||
* @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-service
|
||||
*/
|
||||
class Service extends AbstractActor
|
||||
{
|
||||
protected string $type = 'Service';
|
||||
}
|
@ -1,29 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
/*
|
||||
* This file is part of the ActivityPhp package.
|
||||
*
|
||||
* Copyright (c) landrok at github.com/landrok
|
||||
*
|
||||
* For the full copyright and license information, please see
|
||||
* <https://github.com/landrok/activitypub/blob/master/LICENSE>.
|
||||
*/
|
||||
|
||||
namespace Plugin\ActivityPub\Util\Type\Extended\Object;
|
||||
|
||||
use Plugin\ActivityPub\Util\Type\Core\ObjectType;
|
||||
|
||||
/**
|
||||
* \Plugin\ActivityPub\Util\Type\Extended\Object\Article is an implementation of
|
||||
* one of the Activity Streams Extended Types.
|
||||
*
|
||||
* Represents any kind of multi-paragraph written work.
|
||||
*
|
||||
* @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-article
|
||||
*/
|
||||
class Article extends ObjectType
|
||||
{
|
||||
protected string $type = 'Article';
|
||||
}
|
@ -1,27 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
/*
|
||||
* This file is part of the ActivityPhp package.
|
||||
*
|
||||
* Copyright (c) landrok at github.com/landrok
|
||||
*
|
||||
* For the full copyright and license information, please see
|
||||
* <https://github.com/landrok/activitypub/blob/master/LICENSE>.
|
||||
*/
|
||||
|
||||
namespace Plugin\ActivityPub\Util\Type\Extended\Object;
|
||||
|
||||
/**
|
||||
* \Plugin\ActivityPub\Util\Type\Extended\Object\Audio is an implementation of
|
||||
* one of the Activity Streams Extended Types.
|
||||
*
|
||||
* Represents a document of any kind.
|
||||
*
|
||||
* @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-audio
|
||||
*/
|
||||
class Audio extends Document
|
||||
{
|
||||
protected string $type = 'Audio';
|
||||
}
|
@ -1,29 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
/*
|
||||
* This file is part of the ActivityPhp package.
|
||||
*
|
||||
* Copyright (c) landrok at github.com/landrok
|
||||
*
|
||||
* For the full copyright and license information, please see
|
||||
* <https://github.com/landrok/activitypub/blob/master/LICENSE>.
|
||||
*/
|
||||
|
||||
namespace Plugin\ActivityPub\Util\Type\Extended\Object;
|
||||
|
||||
use Plugin\ActivityPub\Util\Type\Core\ObjectType;
|
||||
|
||||
/**
|
||||
* \Plugin\ActivityPub\Util\Type\Extended\Object\Document is an implementation of
|
||||
* one of the Activity Streams Extended Types.
|
||||
*
|
||||
* Represents an audio document of any kind.
|
||||
*
|
||||
* @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-document
|
||||
*/
|
||||
class Document extends ObjectType
|
||||
{
|
||||
protected string $type = 'Document';
|
||||
}
|
@ -1,29 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
/*
|
||||
* This file is part of the ActivityPhp package.
|
||||
*
|
||||
* Copyright (c) landrok at github.com/landrok
|
||||
*
|
||||
* For the full copyright and license information, please see
|
||||
* <https://github.com/landrok/activitypub/blob/master/LICENSE>.
|
||||
*/
|
||||
|
||||
namespace Plugin\ActivityPub\Util\Type\Extended\Object;
|
||||
|
||||
use Plugin\ActivityPub\Util\Type\Core\ObjectType;
|
||||
|
||||
/**
|
||||
* \Plugin\ActivityPub\Util\Type\Extended\Object\Event is an implementation of
|
||||
* one of the Activity Streams Extended Types.
|
||||
*
|
||||
* Represents any kind of event.
|
||||
*
|
||||
* @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-event
|
||||
*/
|
||||
class Event extends ObjectType
|
||||
{
|
||||
protected string $type = 'Event';
|
||||
}
|
@ -1,27 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
/*
|
||||
* This file is part of the ActivityPhp package.
|
||||
*
|
||||
* Copyright (c) landrok at github.com/landrok
|
||||
*
|
||||
* For the full copyright and license information, please see
|
||||
* <https://github.com/landrok/activitypub/blob/master/LICENSE>.
|
||||
*/
|
||||
|
||||
namespace Plugin\ActivityPub\Util\Type\Extended\Object;
|
||||
|
||||
/**
|
||||
* \Plugin\ActivityPub\Util\Type\Extended\Object\Image is an implementation of
|
||||
* one of the Activity Streams Extended Types.
|
||||
*
|
||||
* An image document of any kind.
|
||||
*
|
||||
* @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-image
|
||||
*/
|
||||
class Image extends Document
|
||||
{
|
||||
protected string $type = 'Image';
|
||||
}
|
@ -1,29 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
/*
|
||||
* This file is part of the ActivityPhp package.
|
||||
*
|
||||
* Copyright (c) landrok at github.com/landrok
|
||||
*
|
||||
* For the full copyright and license information, please see
|
||||
* <https://github.com/landrok/activitypub/blob/master/LICENSE>.
|
||||
*/
|
||||
|
||||
namespace Plugin\ActivityPub\Util\Type\Extended\Object;
|
||||
|
||||
use Plugin\ActivityPub\Util\Type\Core\Link;
|
||||
|
||||
/**
|
||||
* \Plugin\ActivityPub\Util\Type\Extended\Object\Mention is an implementation of
|
||||
* one of the Activity Streams Extended Types.
|
||||
*
|
||||
* A specialized Link that represents an @mention.
|
||||
*
|
||||
* @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-mention
|
||||
*/
|
||||
class Mention extends Link
|
||||
{
|
||||
protected string $type = 'Mention';
|
||||
}
|
@ -1,30 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
/*
|
||||
* This file is part of the ActivityPhp package.
|
||||
*
|
||||
* Copyright (c) landrok at github.com/landrok
|
||||
*
|
||||
* For the full copyright and license information, please see
|
||||
* <https://github.com/landrok/activitypub/blob/master/LICENSE>.
|
||||
*/
|
||||
|
||||
namespace Plugin\ActivityPub\Util\Type\Extended\Object;
|
||||
|
||||
use Plugin\ActivityPub\Util\Type\Core\ObjectType;
|
||||
|
||||
/**
|
||||
* \Plugin\ActivityPub\Util\Type\Extended\Object\Note is an implementation of
|
||||
* one of the Activity Streams Extended Types.
|
||||
*
|
||||
* Represents a short written work typically less than a single
|
||||
* paragraph in length.
|
||||
*
|
||||
* @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-note
|
||||
*/
|
||||
class Note extends ObjectType
|
||||
{
|
||||
protected string $type = 'Note';
|
||||
}
|
@ -1,27 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
/*
|
||||
* This file is part of the ActivityPhp package.
|
||||
*
|
||||
* Copyright (c) landrok at github.com/landrok
|
||||
*
|
||||
* For the full copyright and license information, please see
|
||||
* <https://github.com/landrok/activitypub/blob/master/LICENSE>.
|
||||
*/
|
||||
|
||||
namespace Plugin\ActivityPub\Util\Type\Extended\Object;
|
||||
|
||||
/**
|
||||
* \Plugin\ActivityPub\Util\Type\Extended\Object\Page is an implementation of
|
||||
* one of the Activity Streams Extended Types.
|
||||
*
|
||||
* Represents a Web Page.
|
||||
*
|
||||
* @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-page
|
||||
*/
|
||||
class Page extends Document
|
||||
{
|
||||
protected string $type = 'Page';
|
||||
}
|
@ -1,83 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
/*
|
||||
* This file is part of the ActivityPhp package.
|
||||
*
|
||||
* Copyright (c) landrok at github.com/landrok
|
||||
*
|
||||
* For the full copyright and license information, please see
|
||||
* <https://github.com/landrok/activitypub/blob/master/LICENSE>.
|
||||
*/
|
||||
|
||||
namespace Plugin\ActivityPub\Util\Type\Extended\Object;
|
||||
|
||||
use Plugin\ActivityPub\Util\Type\Core\ObjectType;
|
||||
|
||||
/**
|
||||
* \Plugin\ActivityPub\Util\Type\Extended\Object\Place is an implementation of
|
||||
* one of the Activity Streams Extended Types.
|
||||
*
|
||||
* Represents a logical or physical location.
|
||||
*
|
||||
* @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-place
|
||||
*/
|
||||
class Place extends ObjectType
|
||||
{
|
||||
protected string $type = 'Place';
|
||||
|
||||
/**
|
||||
* Indicates the accuracy of position coordinates on a Place
|
||||
* objects. Expressed in properties of percentage.
|
||||
* e.g. "94.0" means "94.0% accurate".
|
||||
*
|
||||
* @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-accuracy
|
||||
*/
|
||||
protected ?float $accuracy;
|
||||
|
||||
/**
|
||||
* The altitude of a place.
|
||||
* The measurement units is indicated using the units' property.
|
||||
* If units is not specified, the default is assumed to be "m"
|
||||
* indicating meters.
|
||||
*
|
||||
* @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-altitude
|
||||
*/
|
||||
protected ?float $altitude;
|
||||
|
||||
/**
|
||||
* The latitude of a place.
|
||||
*
|
||||
* @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-latitude
|
||||
*/
|
||||
protected int|null|float $latitude;
|
||||
|
||||
/**
|
||||
* The longitude of a place.
|
||||
*
|
||||
* @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-longitude
|
||||
*/
|
||||
protected int|null|float $longitude;
|
||||
|
||||
/**
|
||||
* The radius from the given latitude and longitude for a Place.
|
||||
* The units are expressed by the units' property.
|
||||
* If units is not specified, the default is assumed to be "m"
|
||||
* indicating "meters".
|
||||
*
|
||||
* @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-radius
|
||||
*/
|
||||
protected int|null|float $radius;
|
||||
|
||||
/**
|
||||
* Specifies the measurement units for the radius and altitude
|
||||
* properties on a Place object.
|
||||
* If not specified, the default is assumed to be "m" for "meters".
|
||||
*
|
||||
* @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-units
|
||||
*
|
||||
* "cm" | " feet" | " inches" | " km" | " m" | " miles" | xsd:anyURI
|
||||
*/
|
||||
protected string $units;
|
||||
}
|
@ -1,37 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
/*
|
||||
* This file is part of the ActivityPhp package.
|
||||
*
|
||||
* Copyright (c) landrok at github.com/landrok
|
||||
*
|
||||
* For the full copyright and license information, please see
|
||||
* <https://github.com/landrok/activitypub/blob/master/LICENSE>.
|
||||
*/
|
||||
|
||||
namespace Plugin\ActivityPub\Util\Type\Extended\Object;
|
||||
|
||||
use Plugin\ActivityPub\Util\Type\Core\ObjectType;
|
||||
|
||||
/**
|
||||
* \Plugin\ActivityPub\Util\Type\Extended\Object\Profile is an implementation of
|
||||
* one of the Activity Streams Extended Types.
|
||||
*
|
||||
* A Profile is a content object that describes another Object,
|
||||
* typically used to describe Actor Type objects.
|
||||
* The describes property is used to reference the object being
|
||||
* described by the profile.
|
||||
*
|
||||
* @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-profile
|
||||
*/
|
||||
class Profile extends ObjectType
|
||||
{
|
||||
protected string $type = 'Profile';
|
||||
|
||||
/**
|
||||
* Identify the object described by the Profile.
|
||||
*/
|
||||
protected ObjectType $describes;
|
||||
}
|
@ -1,47 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
/*
|
||||
* This file is part of the ActivityPhp package.
|
||||
*
|
||||
* Copyright (c) landrok at github.com/landrok
|
||||
*
|
||||
* For the full copyright and license information, please see
|
||||
* <https://github.com/landrok/activitypub/blob/master/LICENSE>.
|
||||
*/
|
||||
|
||||
namespace Plugin\ActivityPub\Util\Type\Extended\Object;
|
||||
|
||||
use Plugin\ActivityPub\Util\Type\Core\ObjectType;
|
||||
|
||||
/**
|
||||
* \Plugin\ActivityPub\Util\Type\Extended\Object\Tombstone is an implementation of
|
||||
* one of the Activity Streams Extended Types.
|
||||
*
|
||||
* A Tombstone represents a content object that has been deleted. It can
|
||||
* be used in Collections to signify that there used to be an object at
|
||||
* this position, but it has been deleted.
|
||||
*
|
||||
* @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-tombstone
|
||||
*/
|
||||
class Tombstone extends ObjectType
|
||||
{
|
||||
protected string $type = 'Tombstone';
|
||||
|
||||
/**
|
||||
* The type of the object that was deleted.
|
||||
*
|
||||
* @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-formertype
|
||||
*/
|
||||
protected ?string $formerType;
|
||||
|
||||
/**
|
||||
* A timestamp for when the object was deleted.
|
||||
*
|
||||
* @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-deleted
|
||||
*
|
||||
* @var null|string xsd:dateTime formatted
|
||||
*/
|
||||
protected ?string $deleted;
|
||||
}
|
@ -1,27 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
/*
|
||||
* This file is part of the ActivityPhp package.
|
||||
*
|
||||
* Copyright (c) landrok at github.com/landrok
|
||||
*
|
||||
* For the full copyright and license information, please see
|
||||
* <https://github.com/landrok/activitypub/blob/master/LICENSE>.
|
||||
*/
|
||||
|
||||
namespace Plugin\ActivityPub\Util\Type\Extended\Object;
|
||||
|
||||
/**
|
||||
* \Plugin\ActivityPub\Util\Type\Extended\Object\Video is an implementation of
|
||||
* one of the Activity Streams Extended Types.
|
||||
*
|
||||
* Represents a video document of any kind.
|
||||
*
|
||||
* @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-video
|
||||
*/
|
||||
class Video extends Document
|
||||
{
|
||||
protected string $type = 'Video';
|
||||
}
|
@ -1,134 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
/*
|
||||
* This file is part of the ActivityPhp package.
|
||||
*
|
||||
* Copyright (c) landrok at github.com/landrok
|
||||
*
|
||||
* For the full copyright and license information, please see
|
||||
* <https://github.com/landrok/activitypub/blob/master/LICENSE>.
|
||||
*/
|
||||
|
||||
namespace Plugin\ActivityPub\Util\Type;
|
||||
|
||||
use Exception;
|
||||
|
||||
/**
|
||||
* \Plugin\ActivityPub\Util\Type\TypeResolver is an abstract class for
|
||||
* resolving class names called by their short names (AS types).
|
||||
*/
|
||||
abstract class TypeResolver
|
||||
{
|
||||
/**
|
||||
* A list of core types
|
||||
*/
|
||||
protected static array $coreTypes = [
|
||||
'Activity', 'Collection', 'CollectionPage',
|
||||
'IntransitiveActivity', 'Link', 'ObjectType',
|
||||
'OrderedCollection', 'OrderedCollectionPage',
|
||||
'Object',
|
||||
];
|
||||
|
||||
/**
|
||||
* A list of actor types
|
||||
*/
|
||||
protected static array $actorTypes = [
|
||||
'Application', 'Group', 'Organization', 'Person', 'Service',
|
||||
];
|
||||
|
||||
/**
|
||||
* A list of activity types
|
||||
*/
|
||||
protected static array $activityTypes = [
|
||||
'Accept', 'Add', 'Announce', 'Block',
|
||||
'Create', 'Delete', 'Follow', 'Ignore',
|
||||
'Invite', 'Join', 'Leave', 'Like',
|
||||
'Question', 'Reject', 'Remove', 'Undo',
|
||||
];
|
||||
|
||||
/**
|
||||
* A list of object types
|
||||
*/
|
||||
protected static array $objectTypes = [
|
||||
'Article', 'Audio', 'Document', 'Event', 'Image',
|
||||
'Mention', 'Note', 'Page', 'Place', 'Profile',
|
||||
'Tombstone', 'Video',
|
||||
];
|
||||
|
||||
/**
|
||||
* Get namespaced class for a given short type
|
||||
*
|
||||
* @throws Exception
|
||||
*
|
||||
* @return string Related namespace
|
||||
* @throw \Exception if a namespace was not found.
|
||||
*/
|
||||
public static function getClass(string $type): string
|
||||
{
|
||||
$ns = __NAMESPACE__;
|
||||
|
||||
if ($type == 'Object') {
|
||||
$type .= 'Type';
|
||||
}
|
||||
|
||||
switch ($type) {
|
||||
case \in_array($type, self::$coreTypes):
|
||||
$ns .= '\Core';
|
||||
break;
|
||||
case \in_array($type, self::$activityTypes):
|
||||
$ns .= '\Extended\Activity';
|
||||
break;
|
||||
case \in_array($type, self::$actorTypes):
|
||||
$ns .= '\Extended\Actor';
|
||||
break;
|
||||
case \in_array($type, self::$objectTypes):
|
||||
$ns .= '\Extended\Object';
|
||||
break;
|
||||
default:
|
||||
throw new Exception(
|
||||
"Undefined scope for type '{$type}'",
|
||||
);
|
||||
}
|
||||
|
||||
return $ns . '\\' . $type;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate an object pool type with type attribute
|
||||
*
|
||||
* @param string $poolname An expected pool name
|
||||
*/
|
||||
public static function isScope(object $item, string $poolname = 'all'): bool
|
||||
{
|
||||
if (!\is_object($item)
|
||||
|| !isset($item->type)
|
||||
|| !\is_string($item->type)
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return match (mb_strtolower($poolname)) {
|
||||
'all' => self::exists($item->type),
|
||||
'actor' => \in_array($item->type, self::$actorTypes),
|
||||
default => false,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify that a type exists
|
||||
*/
|
||||
public static function exists(string $name): bool
|
||||
{
|
||||
return \in_array(
|
||||
$name,
|
||||
array_merge(
|
||||
self::$coreTypes,
|
||||
self::$activityTypes,
|
||||
self::$actorTypes,
|
||||
self::$objectTypes,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
@ -1,472 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
/*
|
||||
* This file is part of the ActivityPhp package.
|
||||
*
|
||||
* Copyright (c) landrok at github.com/landrok
|
||||
*
|
||||
* For the full copyright and license information, please see
|
||||
* <https://github.com/landrok/activitypub/blob/master/LICENSE>.
|
||||
*/
|
||||
|
||||
namespace Plugin\ActivityPub\Util\Type;
|
||||
|
||||
use DateInterval;
|
||||
use DateTime;
|
||||
use Exception;
|
||||
use Plugin\ActivityPub\Util\Type;
|
||||
|
||||
/**
|
||||
* \Plugin\ActivityPub\Util\Type\Util is an abstract class for
|
||||
* supporting validators checks & transformations.
|
||||
*/
|
||||
abstract class Util
|
||||
{
|
||||
/**
|
||||
* Allowed units
|
||||
*
|
||||
* @var array<string>
|
||||
*/
|
||||
protected static array $units = [
|
||||
'cm', 'feet', 'inches', 'km', 'm', 'miles',
|
||||
];
|
||||
|
||||
/**
|
||||
* Transform an array into an ActivityStreams type
|
||||
*
|
||||
* @throws Exception
|
||||
*
|
||||
* @return AbstractObject|array an ActivityStreams
|
||||
* type or given array if type key is not defined
|
||||
*/
|
||||
public static function arrayToType(array $item): AbstractObject|array
|
||||
{
|
||||
// Maybe an array representing an AS object
|
||||
// It must have a type key
|
||||
if (isset($item['type'])) {
|
||||
return Type::create($item['type'], $item);
|
||||
}
|
||||
|
||||
return $item;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate an URL
|
||||
*/
|
||||
public static function validateUrl(mixed $value): bool
|
||||
{
|
||||
return \is_string($value)
|
||||
&& filter_var($value, \FILTER_VALIDATE_URL) !== false
|
||||
&& \in_array(
|
||||
parse_url($value, \PHP_URL_SCHEME),
|
||||
['http', 'https', 'magnet'],
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate a magnet link
|
||||
*
|
||||
* @see https://en.wikipedia.org/wiki/Magnet_URI_scheme
|
||||
*
|
||||
* @todo Make a better validation as xs is not the only parameter
|
||||
*/
|
||||
public static function validateMagnet(mixed $value): bool
|
||||
{
|
||||
return \is_string($value)
|
||||
&& mb_strlen($value) < 262144
|
||||
&& preg_match(
|
||||
'#^magnet:\?xs=(https?)://.*$#iu',
|
||||
urldecode($value),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate an OStatus tag string
|
||||
*/
|
||||
public static function validateOstatusTag(mixed $value): bool
|
||||
{
|
||||
return \is_string($value)
|
||||
&& mb_strlen($value) < 262144
|
||||
&& preg_match(
|
||||
'#^tag:([\w\-\.]+),([\d]{4}-[\d]{2}-[\d]{2}):([\w])+Id=([\d]+):objectType=([\w]+)#iu',
|
||||
$value,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate a rel attribute value.
|
||||
*
|
||||
* @see https://tools.ietf.org/html/rfc5988
|
||||
*/
|
||||
public static function validateRel(string $value): bool
|
||||
{
|
||||
return \is_string($value)
|
||||
&& preg_match("/^[^\\s\r\n\\,]+\\z/i", $value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate a non negative integer.
|
||||
*/
|
||||
public static function validateNonNegativeInteger(int $value): bool
|
||||
{
|
||||
return \is_int($value)
|
||||
&& $value >= 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate a non negative number.
|
||||
*/
|
||||
public static function validateNonNegativeNumber(float|int $value): bool
|
||||
{
|
||||
return is_numeric($value)
|
||||
&& $value >= 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate units format.
|
||||
*/
|
||||
public static function validateUnits(string $value): bool
|
||||
{
|
||||
if (\is_string($value)) {
|
||||
if (\in_array($value, self::$units)
|
||||
|| self::validateUrl($value)
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate an Object type
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
public static function validateObject(object $item): bool
|
||||
{
|
||||
return self::hasProperties($item, ['type'])
|
||||
&& \is_string($item->type)
|
||||
&& $item->type === 'Object';
|
||||
}
|
||||
|
||||
/**
|
||||
* Decode a JSON string
|
||||
*
|
||||
* @throws Exception if JSON decoding process has failed
|
||||
*/
|
||||
public static function decodeJson(string $value): array
|
||||
{
|
||||
$json = json_decode($value, true);
|
||||
|
||||
if (json_last_error() !== \JSON_ERROR_NONE) {
|
||||
throw new Exception(
|
||||
'JSON decoding failed for string: ' . $value,
|
||||
);
|
||||
}
|
||||
|
||||
return $json;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks that all properties exist for a stdClass
|
||||
*
|
||||
* @param bool $strict If true throws an \Exception,
|
||||
* otherwise, returns false
|
||||
*
|
||||
* @throws Exception if a property is not set
|
||||
*/
|
||||
public static function hasProperties(
|
||||
object $item,
|
||||
array $properties,
|
||||
bool $strict = false,
|
||||
): bool {
|
||||
foreach ($properties as $property) {
|
||||
if (!property_exists($item, $property)) {
|
||||
if ($strict) {
|
||||
throw new Exception(
|
||||
sprintf(
|
||||
'Attribute "%s" MUST be set for item: %s',
|
||||
$property,
|
||||
print_r($item, true),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate a reference with a Link or an Object with a URL
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
public static function isLinkOrUrlObject(object $item): bool
|
||||
{
|
||||
self::hasProperties($item, ['type'], true);
|
||||
|
||||
// Validate Link type
|
||||
if ($item->type === 'Link') {
|
||||
return self::validateLink($item);
|
||||
}
|
||||
|
||||
// Validate Object type
|
||||
self::hasProperties($item, ['url'], true);
|
||||
|
||||
return self::validateUrl($item->url);
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate a reference as Link
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
public static function validateLink(object|array $item): bool
|
||||
{
|
||||
if (\is_array($item)) {
|
||||
$item = (object) $item;
|
||||
}
|
||||
|
||||
if (!\is_object($item)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
self::hasProperties($item, ['type'], true);
|
||||
|
||||
// Validate Link type
|
||||
if ($item->type !== 'Link') {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Validate Object type
|
||||
self::hasProperties($item, ['href'], true);
|
||||
|
||||
return self::validateUrl($item->href)
|
||||
|| self::validateMagnet($item->href);
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate a datetime
|
||||
*/
|
||||
public static function validateDatetime($value): bool
|
||||
{
|
||||
if (!\is_string($value)
|
||||
|| !preg_match(
|
||||
'/^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2})(.*)$/',
|
||||
$value,
|
||||
)
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
$dt = new DateTime($value);
|
||||
return true;
|
||||
} catch (Exception $e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check that container class is a subclass of a given class
|
||||
*
|
||||
* @param bool $strict If true, throws an exception
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
public static function subclassOf(object $container, array|string $classes, bool $strict = false): bool
|
||||
{
|
||||
if (!\is_array($classes)) {
|
||||
$classes = [$classes];
|
||||
}
|
||||
|
||||
foreach ($classes as $class) {
|
||||
if (\get_class($container) === $class
|
||||
|| is_subclass_of($container, $class)
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if ($strict) {
|
||||
throw new Exception(
|
||||
sprintf(
|
||||
'Class "%s" MUST be a subclass of "%s"',
|
||||
\get_class($container),
|
||||
implode(', ', $classes),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks that a numeric value is part of a range.
|
||||
* If a minimal value is null, value has to be inferior to max value
|
||||
* If a maximum value is null, value has to be superior to min value
|
||||
*/
|
||||
public static function between(float|int $value, float|int|null $min, float|int|null $max): bool
|
||||
{
|
||||
if (!is_numeric($value)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return match (true) {
|
||||
\is_null($min) && \is_null($max) => false,
|
||||
\is_null($min) => $value <= $max,
|
||||
\is_null($max) => $value >= $min,
|
||||
default => $value >= $min
|
||||
&& $value <= $max,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Check that a given string is a valid XML Schema xsd:duration
|
||||
*
|
||||
* @param bool $strict If true, throws an exception
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
public static function isDuration(string $duration, bool $strict = false): bool
|
||||
{
|
||||
try {
|
||||
new DateInterval($duration);
|
||||
return true;
|
||||
} catch (Exception $e) {
|
||||
if ($strict) {
|
||||
throw new Exception(
|
||||
sprintf(
|
||||
'Duration "%s" MUST respect xsd:duration',
|
||||
$duration,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks that it's an object type
|
||||
*/
|
||||
public static function isObjectType(object $item): bool
|
||||
{
|
||||
return TypeResolver::isScope($item);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks that it's an actor type
|
||||
*/
|
||||
public static function isActorType(object $item): bool
|
||||
{
|
||||
return TypeResolver::isScope($item, 'actor');
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate an object type with type attribute
|
||||
*
|
||||
* @param string $type An expected type
|
||||
*/
|
||||
public static function isType(object $item, string $type): bool
|
||||
{
|
||||
// Validate that container is a certain type
|
||||
if (!\is_object($item)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return (bool) (
|
||||
property_exists($item, 'type')
|
||||
&& \is_string($item->type)
|
||||
&& $item->type === $type
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate a BCP 47 language value
|
||||
*/
|
||||
public static function validateBcp47(string $value): bool
|
||||
{
|
||||
return \is_string($value)
|
||||
&& preg_match(
|
||||
'/^(((en-GB-oed|i-ami|i-bnn|i-default|i-enochian|i-hak|i-klingon|i-lux|i-mingo|i-navajo|i-pwn|i-tao|i-tay|i-tsu|sgn-BE-FR|sgn-BE-NL|sgn-CH-DE)|(art-lojban|cel-gaulish|no-bok|no-nyn|zh-guoyu|zh-hakka|zh-min|zh-min-nan|zh-xiang))|((([A-Za-z]{2,3}(-([A-Za-z]{3}(-[A-Za-z]{3}){0,2}))?)|[A-Za-z]{4}|[A-Za-z]{5,8})(-([A-Za-z]{4}))?(-([A-Za-z]{2}|[0-9]{3}))?(-([A-Za-z0-9]{5,8}|[0-9][A-Za-z0-9]{3}))*(-([0-9A-WY-Za-wy-z](-[A-Za-z0-9]{2,8})+))*(-(x(-[A-Za-z0-9]{1,8})+))?)|(x(-[A-Za-z0-9]{1,8})+))$/',
|
||||
$value,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate a plain text value
|
||||
*/
|
||||
public static function validatePlainText(string $value): bool
|
||||
{
|
||||
return \is_string($value)
|
||||
&& preg_match(
|
||||
'/^([^<]+)$/',
|
||||
$value,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate mediaType format
|
||||
*/
|
||||
public static function validateMediaType(string $value): bool
|
||||
{
|
||||
return \is_string($value)
|
||||
&& preg_match(
|
||||
'#^(([\w]+[\w\-]+[\w+])/(([\w]+[\w\-\.\+]+[\w]+)|(\*));?)+$#',
|
||||
$value,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate a Collection type
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
public static function validateCollection(object $item): bool
|
||||
{
|
||||
if (is_scalar($item)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!\is_object($item)) {
|
||||
$item = (object) $item;
|
||||
}
|
||||
|
||||
self::hasProperties(
|
||||
$item,
|
||||
[/*totalItems', 'current', 'first', 'last', */ 'items'],
|
||||
true,
|
||||
);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate a CollectionPage type
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
public static function validateCollectionPage(object $item): bool
|
||||
{
|
||||
|
||||
// Must be a Collection
|
||||
if (!self::validateCollection($item)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
self::hasProperties(
|
||||
$item,
|
||||
['partOf'/*, 'next', 'prev'*/],
|
||||
true,
|
||||
);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
@ -1,98 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
/*
|
||||
* This file is part of the ActivityPhp package.
|
||||
*
|
||||
* Copyright (c) landrok at github.com/landrok
|
||||
*
|
||||
* For the full copyright and license information, please see
|
||||
* <https://github.com/landrok/activitypub/blob/master/LICENSE>.
|
||||
*/
|
||||
|
||||
namespace Plugin\ActivityPub\Util\Type;
|
||||
|
||||
use Exception;
|
||||
|
||||
/**
|
||||
* \Plugin\ActivityPub\Util\Type\Validator is an abstract class for
|
||||
* attribute validation.
|
||||
*/
|
||||
abstract class Validator
|
||||
{
|
||||
/**
|
||||
* Contains all custom validators
|
||||
*
|
||||
* @var array<string, ValidatorInterface>
|
||||
*
|
||||
* [ 'attributeName' => CustomValidatorClassName::class ]
|
||||
*/
|
||||
protected static array $validators = [];
|
||||
|
||||
/**
|
||||
* Validate an attribute value for given attribute name and
|
||||
* container object.
|
||||
*
|
||||
* @param mixed $container An object
|
||||
*
|
||||
* @throws Exception if $container is not an object
|
||||
*/
|
||||
public static function validate(string $name, mixed $value, mixed $container): bool
|
||||
{
|
||||
if (!\is_object($container)) {
|
||||
throw new Exception(
|
||||
'Given container is not an object',
|
||||
);
|
||||
}
|
||||
|
||||
// Perform validation
|
||||
if (isset(self::$validators[$name])) {
|
||||
return self::$validators[$name]->validate(
|
||||
$value,
|
||||
$container,
|
||||
);
|
||||
}
|
||||
|
||||
// Try to load a default validator
|
||||
$validatorName = sprintf(
|
||||
'\Plugin\ActivityPub\Util\Type\Validator\%sValidator',
|
||||
ucfirst($name),
|
||||
);
|
||||
|
||||
if (class_exists($validatorName)) {
|
||||
self::add($name, $validatorName);
|
||||
return self::validate($name, $value, $container);
|
||||
}
|
||||
|
||||
// There is no validator for this attribute
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a new validator in the pool.
|
||||
* It checks that it implements Validator\Interface
|
||||
*
|
||||
* @param string $name an attribute name to validate
|
||||
* @param object|string $class A validator class name
|
||||
*
|
||||
* @throws Exception if validator class does not implement
|
||||
* \Plugin\ActivityPub\Util\Type\Helper\ValidatorInterface
|
||||
*/
|
||||
public static function add(string $name, object|string $class): void
|
||||
{
|
||||
$validator = new $class();
|
||||
|
||||
if (!($validator instanceof ValidatorInterface)) {
|
||||
throw new Exception(
|
||||
sprintf(
|
||||
'Validator "%s" MUST implement "%s" interface',
|
||||
\get_class($validator),
|
||||
ValidatorInterface::class,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
self::$validators[$name] = $validator;
|
||||
}
|
||||
}
|
@ -1,35 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
/*
|
||||
* This file is part of the ActivityPhp package.
|
||||
*
|
||||
* Copyright (c) landrok at github.com/landrok
|
||||
*
|
||||
* For the full copyright and license information, please see
|
||||
* <https://github.com/landrok/activitypub/blob/master/LICENSE>.
|
||||
*/
|
||||
|
||||
namespace Plugin\ActivityPub\Util\Type\Validator;
|
||||
|
||||
use Plugin\ActivityPub\Util\Type\ValidatorInterface;
|
||||
|
||||
/**
|
||||
* \Plugin\ActivityPub\Util\Type\Validator\AccuracyValidator is a dedicated
|
||||
* validator for accuracy attribute.
|
||||
*/
|
||||
class AccuracyValidator implements ValidatorInterface
|
||||
{
|
||||
/**
|
||||
* Validate an ACCURACY attribute value
|
||||
*
|
||||
* @param mixed $container An object
|
||||
*/
|
||||
public function validate(mixed $value, mixed $container): bool
|
||||
{
|
||||
return is_numeric($value)
|
||||
&& (float) $value >= 0
|
||||
&& (float) $value <= 100.0;
|
||||
}
|
||||
}
|
@ -1,112 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
/*
|
||||
* This file is part of the ActivityPhp package.
|
||||
*
|
||||
* Copyright (c) landrok at github.com/landrok
|
||||
*
|
||||
* For the full copyright and license information, please see
|
||||
* <https://github.com/landrok/activitypub/blob/master/LICENSE>.
|
||||
*/
|
||||
|
||||
namespace Plugin\ActivityPub\Util\Type\Validator;
|
||||
|
||||
use Exception;
|
||||
use Plugin\ActivityPub\Util\Type\Core\Collection;
|
||||
use Plugin\ActivityPub\Util\Type\Core\Link;
|
||||
use Plugin\ActivityPub\Util\Type\Extended\AbstractActor;
|
||||
use Plugin\ActivityPub\Util\Type\Util;
|
||||
use Plugin\ActivityPub\Util\Type\ValidatorInterface;
|
||||
|
||||
/**
|
||||
* \Plugin\ActivityPub\Util\Type\Validator\ActorValidator is a dedicated
|
||||
* validator for actor attribute.
|
||||
*/
|
||||
class ActorValidator implements ValidatorInterface
|
||||
{
|
||||
/**
|
||||
* Validate an ACTOR attribute value
|
||||
*
|
||||
* @param mixed $container An object
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
public function validate(mixed $value, mixed $container): bool
|
||||
{
|
||||
// Can be an indirect link
|
||||
if (\is_string($value) && Util::validateUrl($value)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (\is_array($value)) {
|
||||
$value = Util::arrayToType($value);
|
||||
}
|
||||
|
||||
// A collection
|
||||
if (\is_array($value)) {
|
||||
return $this->validateObjectCollection($value);
|
||||
}
|
||||
|
||||
// Must be an object
|
||||
if (!\is_object($value)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// A single actor
|
||||
return $this->validateObject($value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate an Actor object type
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
protected function validateObject(object|array $item): bool
|
||||
{
|
||||
if (\is_array($item)) {
|
||||
$item = Util::arrayToType($item);
|
||||
}
|
||||
|
||||
Util::subclassOf(
|
||||
$item,
|
||||
[
|
||||
AbstractActor::class,
|
||||
Link::class,
|
||||
Collection::class,
|
||||
],
|
||||
true,
|
||||
);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate a list of object
|
||||
* Collection can contain:
|
||||
* - Indirect URL
|
||||
* - An actor object
|
||||
*
|
||||
* @throws Exception
|
||||
* @throws Exception
|
||||
*/
|
||||
protected function validateObjectCollection(array $collection): bool
|
||||
{
|
||||
foreach ($collection as $item) {
|
||||
if (\is_array($item) && $this->validateObject($item)) {
|
||||
continue;
|
||||
}
|
||||
if (\is_object($item) && $this->validateObject($item)) {
|
||||
continue;
|
||||
}
|
||||
if (\is_string($item) && Util::validateUrl($item)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return \count($collection) > 0;
|
||||
}
|
||||
}
|
@ -1,33 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
/*
|
||||
* This file is part of the ActivityPhp package.
|
||||
*
|
||||
* Copyright (c) landrok at github.com/landrok
|
||||
*
|
||||
* For the full copyright and license information, please see
|
||||
* <https://github.com/landrok/activitypub/blob/master/LICENSE>.
|
||||
*/
|
||||
|
||||
namespace Plugin\ActivityPub\Util\Type\Validator;
|
||||
|
||||
use Plugin\ActivityPub\Util\Type\ValidatorInterface;
|
||||
|
||||
/**
|
||||
* \Plugin\ActivityPub\Util\Type\Validator\AltitudeValidator is a dedicated
|
||||
* validator for altitude attribute.
|
||||
*/
|
||||
class AltitudeValidator implements ValidatorInterface
|
||||
{
|
||||
/**
|
||||
* Validate an ALTITUDE attribute value
|
||||
*
|
||||
* @param mixed $container An object
|
||||
*/
|
||||
public function validate(mixed $value, mixed $container): bool
|
||||
{
|
||||
return (bool) (\is_float($value) || \is_int($value));
|
||||
}
|
||||
}
|
@ -1,56 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
/*
|
||||
* This file is part of the ActivityPhp package.
|
||||
*
|
||||
* Copyright (c) landrok at github.com/landrok
|
||||
*
|
||||
* For the full copyright and license information, please see
|
||||
* <https://github.com/landrok/activitypub/blob/master/LICENSE>.
|
||||
*/
|
||||
|
||||
namespace Plugin\ActivityPub\Util\Type\Validator;
|
||||
|
||||
use Exception;
|
||||
use Plugin\ActivityPub\Util\Type\Extended\Activity\Question;
|
||||
use Plugin\ActivityPub\Util\Type\Util;
|
||||
use Plugin\ActivityPub\Util\Type\ValidatorTools;
|
||||
|
||||
/**
|
||||
* \Plugin\ActivityPub\Util\Type\Validator\AnyOfValidator is a dedicated
|
||||
* validator for anyOf attribute.
|
||||
*/
|
||||
class AnyOfValidator extends ValidatorTools
|
||||
{
|
||||
/**
|
||||
* Validate an ANYOF attribute value
|
||||
*
|
||||
* @param mixed $container An object
|
||||
*
|
||||
* @throws Exception
|
||||
*
|
||||
* @todo Choices can contain Indirect references.
|
||||
* This validation should validate this kind of usage.
|
||||
*/
|
||||
public function validate(mixed $value, mixed $container): bool
|
||||
{
|
||||
// Validate that container is a Question type
|
||||
Util::subclassOf($container, Question::class, true);
|
||||
|
||||
// A collection
|
||||
if (!\is_array($value)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!\count($value)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return $this->validateObjectCollection(
|
||||
$value,
|
||||
$this->getQuestionAnswerValidator(),
|
||||
);
|
||||
}
|
||||
}
|
@ -1,44 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
/*
|
||||
* This file is part of the ActivityPhp package.
|
||||
*
|
||||
* Copyright (c) landrok at github.com/landrok
|
||||
*
|
||||
* For the full copyright and license information, please see
|
||||
* <https://github.com/landrok/activitypub/blob/master/LICENSE>.
|
||||
*/
|
||||
|
||||
namespace Plugin\ActivityPub\Util\Type\Validator;
|
||||
|
||||
use Exception;
|
||||
use Plugin\ActivityPub\Util\Type\ValidatorTools;
|
||||
|
||||
/**
|
||||
* \Plugin\ActivityPub\Util\Type\Validator\AttachmentValidator is a dedicated
|
||||
* validator for attachment attribute.
|
||||
*/
|
||||
class AttachmentValidator extends ValidatorTools
|
||||
{
|
||||
/**
|
||||
* Validate an attachment value
|
||||
*
|
||||
* @param mixed $container An Object type
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
public function validate(mixed $value, mixed $container): bool
|
||||
{
|
||||
if (\is_array($value) && !\count($value)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return $this->validateListOrObject(
|
||||
$value,
|
||||
$container,
|
||||
$this->getAttachmentValidator(),
|
||||
);
|
||||
}
|
||||
}
|
@ -1,40 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
/*
|
||||
* This file is part of the ActivityPhp package.
|
||||
*
|
||||
* Copyright (c) landrok at github.com/landrok
|
||||
*
|
||||
* For the full copyright and license information, please see
|
||||
* <https://github.com/landrok/activitypub/blob/master/LICENSE>.
|
||||
*/
|
||||
|
||||
namespace Plugin\ActivityPub\Util\Type\Validator;
|
||||
|
||||
use Exception;
|
||||
use Plugin\ActivityPub\Util\Type\ValidatorTools;
|
||||
|
||||
/**
|
||||
* \Plugin\ActivityPub\Util\Type\Validator\AttributedToValidator is a dedicated
|
||||
* validator for attributedTo attribute.
|
||||
*/
|
||||
class AttributedToValidator extends ValidatorTools
|
||||
{
|
||||
/**
|
||||
* Validate an attributedTo value
|
||||
*
|
||||
* @param mixed $container An Object type
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
public function validate(mixed $value, mixed $container): bool
|
||||
{
|
||||
return $this->validateListOrObject(
|
||||
$value,
|
||||
$container,
|
||||
$this->getCollectionActorsValidator(),
|
||||
);
|
||||
}
|
||||
}
|
@ -1,40 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
/*
|
||||
* This file is part of the ActivityPhp package.
|
||||
*
|
||||
* Copyright (c) landrok at github.com/landrok
|
||||
*
|
||||
* For the full copyright and license information, please see
|
||||
* <https://github.com/landrok/activitypub/blob/master/LICENSE>.
|
||||
*/
|
||||
|
||||
namespace Plugin\ActivityPub\Util\Type\Validator;
|
||||
|
||||
use Exception;
|
||||
use Plugin\ActivityPub\Util\Type\ValidatorTools;
|
||||
|
||||
/**
|
||||
* \Plugin\ActivityPub\Util\Type\Validator\AudienceValidator is a dedicated
|
||||
* validator for audience attribute.
|
||||
*/
|
||||
class AudienceValidator extends ValidatorTools
|
||||
{
|
||||
/**
|
||||
* Validate an audience value
|
||||
*
|
||||
* @param mixed $container An Object type
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
public function validate(mixed $value, mixed $container): bool
|
||||
{
|
||||
return $this->validateListOrObject(
|
||||
$value,
|
||||
$container,
|
||||
$this->getLinkOrNamedObjectValidator(),
|
||||
);
|
||||
}
|
||||
}
|
@ -1,40 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
/*
|
||||
* This file is part of the ActivityPhp package.
|
||||
*
|
||||
* Copyright (c) landrok at github.com/landrok
|
||||
*
|
||||
* For the full copyright and license information, please see
|
||||
* <https://github.com/landrok/activitypub/blob/master/LICENSE>.
|
||||
*/
|
||||
|
||||
namespace Plugin\ActivityPub\Util\Type\Validator;
|
||||
|
||||
use Exception;
|
||||
use Plugin\ActivityPub\Util\Type\ValidatorTools;
|
||||
|
||||
/**
|
||||
* \Plugin\ActivityPub\Util\Type\Validator\BccValidator is a dedicated
|
||||
* validator for bcc attribute.
|
||||
*/
|
||||
class BccValidator extends ValidatorTools
|
||||
{
|
||||
/**
|
||||
* Validate a bcc value
|
||||
*
|
||||
* @param mixed $container An Object type
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
public function validate(mixed $value, mixed $container): bool
|
||||
{
|
||||
return $this->validateListOrObject(
|
||||
$value,
|
||||
$container,
|
||||
$this->getLinkOrUrlObjectValidator(),
|
||||
);
|
||||
}
|
||||
}
|
@ -1,40 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
/*
|
||||
* This file is part of the ActivityPhp package.
|
||||
*
|
||||
* Copyright (c) landrok at github.com/landrok
|
||||
*
|
||||
* For the full copyright and license information, please see
|
||||
* <https://github.com/landrok/activitypub/blob/master/LICENSE>.
|
||||
*/
|
||||
|
||||
namespace Plugin\ActivityPub\Util\Type\Validator;
|
||||
|
||||
use Exception;
|
||||
use Plugin\ActivityPub\Util\Type\ValidatorTools;
|
||||
|
||||
/**
|
||||
* \Plugin\ActivityPub\Util\Type\Validator\BtoValidator is a dedicated
|
||||
* validator for bto attribute.
|
||||
*/
|
||||
class BtoValidator extends ValidatorTools
|
||||
{
|
||||
/**
|
||||
* Validate a bto value
|
||||
*
|
||||
* @param mixed $container An Object type
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
public function validate(mixed $value, mixed $container): bool
|
||||
{
|
||||
return $this->validateListOrObject(
|
||||
$value,
|
||||
$container,
|
||||
$this->getLinkOrUrlObjectValidator(),
|
||||
);
|
||||
}
|
||||
}
|
@ -1,40 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
/*
|
||||
* This file is part of the ActivityPhp package.
|
||||
*
|
||||
* Copyright (c) landrok at github.com/landrok
|
||||
*
|
||||
* For the full copyright and license information, please see
|
||||
* <https://github.com/landrok/activitypub/blob/master/LICENSE>.
|
||||
*/
|
||||
|
||||
namespace Plugin\ActivityPub\Util\Type\Validator;
|
||||
|
||||
use Exception;
|
||||
use Plugin\ActivityPub\Util\Type\ValidatorTools;
|
||||
|
||||
/**
|
||||
* \Plugin\ActivityPub\Util\Type\Validator\CcValidator is a dedicated
|
||||
* validator for cc attribute.
|
||||
*/
|
||||
class CcValidator extends ValidatorTools
|
||||
{
|
||||
/**
|
||||
* Validate a cc value
|
||||
*
|
||||
* @param mixed $container An Object type
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
public function validate(mixed $value, mixed $container): bool
|
||||
{
|
||||
return $this->validateListOrObject(
|
||||
$value,
|
||||
$container,
|
||||
$this->getLinkOrUrlObjectValidator(),
|
||||
);
|
||||
}
|
||||
}
|
@ -1,68 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
/*
|
||||
* This file is part of the ActivityPhp package.
|
||||
*
|
||||
* Copyright (c) landrok at github.com/landrok
|
||||
*
|
||||
* For the full copyright and license information, please see
|
||||
* <https://github.com/landrok/activitypub/blob/master/LICENSE>.
|
||||
*/
|
||||
|
||||
namespace Plugin\ActivityPub\Util\Type\Validator;
|
||||
|
||||
use Exception;
|
||||
use Plugin\ActivityPub\Util\Type\Extended\Activity\Question;
|
||||
use Plugin\ActivityPub\Util\Type\Util;
|
||||
use Plugin\ActivityPub\Util\Type\ValidatorInterface;
|
||||
|
||||
/**
|
||||
* \Plugin\ActivityPub\Util\Type\Validator\ClosedValidator is a dedicated
|
||||
* validator for closed attribute.
|
||||
*/
|
||||
class ClosedValidator implements ValidatorInterface
|
||||
{
|
||||
/**
|
||||
* Validate an CLOSED attribute value
|
||||
*
|
||||
* @param mixed $container A Question type
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
public function validate(mixed $value, mixed $container): bool
|
||||
{
|
||||
// Validate that container is a Question type
|
||||
Util::subclassOf($container, Question::class, true);
|
||||
|
||||
// Can be a boolean
|
||||
if (\is_bool($value)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (\is_string($value)) {
|
||||
// Can be a datetime
|
||||
if (Util::validateDatetime($value)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Can be a URL
|
||||
if (Util::validateUrl($value)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (\is_array($value)) {
|
||||
$value = Util::arrayToType($value);
|
||||
}
|
||||
|
||||
// An Object or a Link
|
||||
if (\is_object($value)) {
|
||||
return Util::validateLink($value)
|
||||
|| Util::validateObject($value);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
@ -1,34 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
/*
|
||||
* This file is part of the ActivityPhp package.
|
||||
*
|
||||
* Copyright (c) landrok at github.com/landrok
|
||||
*
|
||||
* For the full copyright and license information, please see
|
||||
* <https://github.com/landrok/activitypub/blob/master/LICENSE>.
|
||||
*/
|
||||
|
||||
namespace Plugin\ActivityPub\Util\Type\Validator;
|
||||
|
||||
use Exception;
|
||||
use Plugin\ActivityPub\Util\Type\ValidatorTools;
|
||||
|
||||
/**
|
||||
* \Plugin\ActivityPub\Util\Type\Validator\ContentMapValidator is a dedicated
|
||||
* validator for contentMap attribute.
|
||||
*/
|
||||
class ContentMapValidator extends ValidatorTools
|
||||
{
|
||||
/**
|
||||
* Validate a contentMap value
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
public function validate(mixed $value, mixed $container): bool
|
||||
{
|
||||
return $this->validateMap('content', $value, $container);
|
||||
}
|
||||
}
|
@ -1,32 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
/*
|
||||
* This file is part of the ActivityPhp package.
|
||||
*
|
||||
* Copyright (c) landrok at github.com/landrok
|
||||
*
|
||||
* For the full copyright and license information, please see
|
||||
* <https://github.com/landrok/activitypub/blob/master/LICENSE>.
|
||||
*/
|
||||
|
||||
namespace Plugin\ActivityPub\Util\Type\Validator;
|
||||
|
||||
use Plugin\ActivityPub\Util\Type\ValidatorInterface;
|
||||
|
||||
/**
|
||||
* \Plugin\ActivityPub\Util\Type\Validator\ContentValidator is a dedicated
|
||||
* validator for content attribute.
|
||||
*/
|
||||
class ContentValidator implements ValidatorInterface
|
||||
{
|
||||
/**
|
||||
* Validate a content attribute value
|
||||
*/
|
||||
public function validate(mixed $value, mixed $container): bool
|
||||
{
|
||||
// Must be a string or null
|
||||
return (bool) (\is_null($value) || \is_string($value));
|
||||
}
|
||||
}
|
@ -1,50 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
/*
|
||||
* This file is part of the ActivityPhp package.
|
||||
*
|
||||
* Copyright (c) landrok at github.com/landrok
|
||||
*
|
||||
* For the full copyright and license information, please see
|
||||
* <https://github.com/landrok/activitypub/blob/master/LICENSE>.
|
||||
*/
|
||||
|
||||
namespace Plugin\ActivityPub\Util\Type\Validator;
|
||||
|
||||
use Exception;
|
||||
use Plugin\ActivityPub\Util\Type\Util;
|
||||
use Plugin\ActivityPub\Util\Type\ValidatorInterface;
|
||||
|
||||
/**
|
||||
* \Plugin\ActivityPub\Util\Type\Validator\ContextValidator is a dedicated
|
||||
* validator for context attribute.
|
||||
*/
|
||||
class ContextValidator implements ValidatorInterface
|
||||
{
|
||||
/**
|
||||
* Validate a context attribute value
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
public function validate(mixed $value, mixed $container): bool
|
||||
{
|
||||
// URL
|
||||
if (Util::validateUrl($value)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (\is_array($value)) {
|
||||
$value = Util::arrayToType($value);
|
||||
}
|
||||
|
||||
// Link or Object
|
||||
if (\is_object($value)) {
|
||||
return Util::validateLink($value)
|
||||
|| Util::validateObject($value);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
@ -1,46 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
/*
|
||||
* This file is part of the ActivityPhp package.
|
||||
*
|
||||
* Copyright (c) landrok at github.com/landrok
|
||||
*
|
||||
* For the full copyright and license information, please see
|
||||
* <https://github.com/landrok/activitypub/blob/master/LICENSE>.
|
||||
*/
|
||||
|
||||
namespace Plugin\ActivityPub\Util\Type\Validator;
|
||||
|
||||
use Exception;
|
||||
use Plugin\ActivityPub\Util\Type\Core\Collection;
|
||||
use Plugin\ActivityPub\Util\Type\Util;
|
||||
use Plugin\ActivityPub\Util\Type\ValidatorInterface;
|
||||
|
||||
/**
|
||||
* \Plugin\ActivityPub\Util\Type\Validator\CurrentValidator is a dedicated
|
||||
* validator for current attribute.
|
||||
*/
|
||||
class CurrentValidator implements ValidatorInterface
|
||||
{
|
||||
/**
|
||||
* Validate a current attribute value
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
public function validate(mixed $value, mixed $container): bool
|
||||
{
|
||||
// Container must be a Collection
|
||||
Util::subclassOf($container, Collection::class, true);
|
||||
|
||||
// URL
|
||||
if (Util::validateUrl($value)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Link or CollectionPage
|
||||
return Util::validateLink($value)
|
||||
|| Util::validateCollectionPage($value);
|
||||
}
|
||||
}
|
@ -1,48 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
/*
|
||||
* This file is part of the ActivityPhp package.
|
||||
*
|
||||
* Copyright (c) landrok at github.com/landrok
|
||||
*
|
||||
* For the full copyright and license information, please see
|
||||
* <https://github.com/landrok/activitypub/blob/master/LICENSE>.
|
||||
*/
|
||||
|
||||
namespace Plugin\ActivityPub\Util\Type\Validator;
|
||||
|
||||
use Exception;
|
||||
use Plugin\ActivityPub\Util\Type\Extended\Object\Tombstone;
|
||||
use Plugin\ActivityPub\Util\Type\Util;
|
||||
use Plugin\ActivityPub\Util\Type\ValidatorInterface;
|
||||
|
||||
/**
|
||||
* \Plugin\ActivityPub\Util\Type\Validator\DeletedValidator is a dedicated
|
||||
* validator for deleted attribute.
|
||||
*/
|
||||
class DeletedValidator implements ValidatorInterface
|
||||
{
|
||||
/**
|
||||
* Validate a DELETED attribute value
|
||||
*
|
||||
* @param mixed $container A Tombstone type
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
public function validate(mixed $value, mixed $container): bool
|
||||
{
|
||||
// Validate that container is a Tombstone type
|
||||
Util::subclassOf($container, Tombstone::class, true);
|
||||
|
||||
if (\is_string($value)) {
|
||||
// MUST be a datetime
|
||||
if (Util::validateDatetime($value)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
@ -1,47 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
/*
|
||||
* This file is part of the ActivityPhp package.
|
||||
*
|
||||
* Copyright (c) landrok at github.com/landrok
|
||||
*
|
||||
* For the full copyright and license information, please see
|
||||
* <https://github.com/landrok/activitypub/blob/master/LICENSE>.
|
||||
*/
|
||||
|
||||
namespace Plugin\ActivityPub\Util\Type\Validator;
|
||||
|
||||
use Exception;
|
||||
use Plugin\ActivityPub\Util\Type\Core\ObjectType;
|
||||
use Plugin\ActivityPub\Util\Type\Extended\Object\Profile;
|
||||
use Plugin\ActivityPub\Util\Type\Util;
|
||||
use Plugin\ActivityPub\Util\Type\ValidatorInterface;
|
||||
|
||||
/**
|
||||
* \Plugin\ActivityPub\Util\Type\Validator\DescribesValidator is a dedicated
|
||||
* validator for describes attribute.
|
||||
*/
|
||||
class DescribesValidator implements ValidatorInterface
|
||||
{
|
||||
/**
|
||||
* Validate an DESCRIBES attribute value
|
||||
*
|
||||
* @param mixed $container A Profile type
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
public function validate(mixed $value, mixed $container): bool
|
||||
{
|
||||
// Validate that container is a Tombstone type
|
||||
Util::subclassOf($container, Profile::class, true);
|
||||
|
||||
if (\is_object($value)) {
|
||||
// MUST be an Object
|
||||
return Util::subclassOf($value, ObjectType::class, true);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
@ -1,44 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
/*
|
||||
* This file is part of the ActivityPhp package.
|
||||
*
|
||||
* Copyright (c) landrok at github.com/landrok
|
||||
*
|
||||
* For the full copyright and license information, please see
|
||||
* <https://github.com/landrok/activitypub/blob/master/LICENSE>.
|
||||
*/
|
||||
|
||||
namespace Plugin\ActivityPub\Util\Type\Validator;
|
||||
|
||||
use Exception;
|
||||
use Plugin\ActivityPub\Util\Type\Core\ObjectType;
|
||||
use Plugin\ActivityPub\Util\Type\Util;
|
||||
use Plugin\ActivityPub\Util\Type\ValidatorInterface;
|
||||
|
||||
/**
|
||||
* \Plugin\ActivityPub\Util\Type\Validator\DurationValidator is a dedicated
|
||||
* validator for duration attribute.
|
||||
*/
|
||||
class DurationValidator implements ValidatorInterface
|
||||
{
|
||||
/**
|
||||
* Validate an DURATION attribute value
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
public function validate(mixed $value, mixed $container): bool
|
||||
{
|
||||
// Validate that container has an ObjectType type
|
||||
Util::subclassOf($container, ObjectType::class, true);
|
||||
|
||||
if (\is_string($value)) {
|
||||
// MUST be an XML 8601 Duration formatted string
|
||||
return Util::isDuration($value, true);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
@ -1,40 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
/*
|
||||
* This file is part of the ActivityPhp package.
|
||||
*
|
||||
* Copyright (c) landrok at github.com/landrok
|
||||
*
|
||||
* For the full copyright and license information, please see
|
||||
* <https://github.com/landrok/activitypub/blob/master/LICENSE>.
|
||||
*/
|
||||
|
||||
namespace Plugin\ActivityPub\Util\Type\Validator;
|
||||
|
||||
use Exception;
|
||||
use Plugin\ActivityPub\Util\Type\Core\ObjectType;
|
||||
use Plugin\ActivityPub\Util\Type\Util;
|
||||
use Plugin\ActivityPub\Util\Type\ValidatorInterface;
|
||||
|
||||
/**
|
||||
* \Plugin\ActivityPub\Util\Type\Validator\EndTimeValidator is a dedicated
|
||||
* validator for endTime attribute.
|
||||
*/
|
||||
class EndTimeValidator implements ValidatorInterface
|
||||
{
|
||||
/**
|
||||
* Validate an ENDTIME attribute value
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
public function validate(mixed $value, mixed $container): bool
|
||||
{
|
||||
// Validate that container has an ObjectType type
|
||||
Util::subclassOf($container, ObjectType::class, true);
|
||||
|
||||
// MUST be a valid xsd:dateTime
|
||||
return Util::validateDatetime($value);
|
||||
}
|
||||
}
|
@ -1,75 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
/*
|
||||
* This file is part of the ActivityPhp package.
|
||||
*
|
||||
* Copyright (c) landrok at github.com/landrok
|
||||
*
|
||||
* For the full copyright and license information, please see
|
||||
* <https://github.com/landrok/activitypub/blob/master/LICENSE>.
|
||||
*/
|
||||
|
||||
namespace Plugin\ActivityPub\Util\Type\Validator;
|
||||
|
||||
use Exception;
|
||||
use Plugin\ActivityPub\Util\Type\Extended\AbstractActor;
|
||||
use Plugin\ActivityPub\Util\Type\Util;
|
||||
use Plugin\ActivityPub\Util\Type\ValidatorInterface;
|
||||
|
||||
/**
|
||||
* \Plugin\ActivityPub\Util\Type\Validator\EndpointsValidator is a dedicated
|
||||
* validator for endpoints attribute.
|
||||
*/
|
||||
class EndpointsValidator implements ValidatorInterface
|
||||
{
|
||||
/**
|
||||
* Validate ENDPOINTS value
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
public function validate(mixed $value, mixed $container): bool
|
||||
{
|
||||
// Validate that container is an AbstractActor type
|
||||
Util::subclassOf($container, AbstractActor::class, true);
|
||||
|
||||
// A link to a JSON-LD document
|
||||
if (Util::validateUrl($value)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// A map
|
||||
return \is_array($value) && $this->validateObject($value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate endpoints mapping
|
||||
*/
|
||||
protected function validateObject(array $item): bool
|
||||
{
|
||||
foreach ($item as $key => $value) {
|
||||
switch ($key) {
|
||||
case 'proxyUrl':
|
||||
case 'oauthAuthorizationEndpoint':
|
||||
case 'oauthTokenEndpoint':
|
||||
case 'provideClientKey':
|
||||
case 'signClientKey':
|
||||
case 'sharedInbox':
|
||||
if (!Util::validateUrl($value)) {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
// All other keys are not allowed
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
if (is_numeric($key)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
@ -1,22 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
/*
|
||||
* This file is part of the ActivityPhp package.
|
||||
*
|
||||
* Copyright (c) landrok at github.com/landrok
|
||||
*
|
||||
* For the full copyright and license information, please see
|
||||
* <https://github.com/landrok/activitypub/blob/master/LICENSE>.
|
||||
*/
|
||||
|
||||
namespace Plugin\ActivityPub\Util\Type\Validator;
|
||||
|
||||
/**
|
||||
* \Plugin\ActivityPub\Util\Type\Validator\FirstValidator is a dedicated
|
||||
* validator for first attribute.
|
||||
*/
|
||||
class FirstValidator extends CurrentValidator
|
||||
{
|
||||
}
|
@ -1,65 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
/*
|
||||
* This file is part of the ActivityPhp package.
|
||||
*
|
||||
* Copyright (c) landrok at github.com/landrok
|
||||
*
|
||||
* For the full copyright and license information, please see
|
||||
* <https://github.com/landrok/activitypub/blob/master/LICENSE>.
|
||||
*/
|
||||
|
||||
namespace Plugin\ActivityPub\Util\Type\Validator;
|
||||
|
||||
use Exception;
|
||||
use Plugin\ActivityPub\Util\Type\Core\Collection;
|
||||
use Plugin\ActivityPub\Util\Type\Core\OrderedCollection;
|
||||
use Plugin\ActivityPub\Util\Type\Extended\AbstractActor;
|
||||
use Plugin\ActivityPub\Util\Type\Util;
|
||||
use Plugin\ActivityPub\Util\Type\ValidatorInterface;
|
||||
|
||||
/**
|
||||
* \Plugin\ActivityPub\Util\Type\Validator\FollowersValidator is a dedicated
|
||||
* validator for followers attribute.
|
||||
*/
|
||||
class FollowersValidator implements ValidatorInterface
|
||||
{
|
||||
/**
|
||||
* Validate a FOLLOWERS attribute value
|
||||
*
|
||||
* @throws Exception
|
||||
*
|
||||
* @todo Support indirect reference for followers attribute?
|
||||
*/
|
||||
public function validate(mixed $value, mixed $container): bool
|
||||
{
|
||||
// Validate that container is an AbstractActor type
|
||||
Util::subclassOf($container, AbstractActor::class, true);
|
||||
|
||||
if (\is_string($value)) {
|
||||
return Util::validateUrl($value);
|
||||
}
|
||||
|
||||
// A collection
|
||||
return \is_object($value) && $this->validateObject($value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate that it is an OrderedCollection or a Collection
|
||||
*
|
||||
* @throws Exception
|
||||
* @throws Exception
|
||||
*/
|
||||
protected function validateObject(object $collection): bool
|
||||
{
|
||||
return Util::subclassOf(
|
||||
$collection,
|
||||
OrderedCollection::class,
|
||||
) || Util::subclassOf(
|
||||
$collection,
|
||||
Collection::class,
|
||||
);
|
||||
}
|
||||
}
|
@ -1,22 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
/*
|
||||
* This file is part of the ActivityPhp package.
|
||||
*
|
||||
* Copyright (c) landrok at github.com/landrok
|
||||
*
|
||||
* For the full copyright and license information, please see
|
||||
* <https://github.com/landrok/activitypub/blob/master/LICENSE>.
|
||||
*/
|
||||
|
||||
namespace Plugin\ActivityPub\Util\Type\Validator;
|
||||
|
||||
/**
|
||||
* \Plugin\ActivityPub\Util\Type\Validator\FollowingValidator is a dedicated
|
||||
* validator for followers attribute.
|
||||
*/
|
||||
class FollowingValidator extends FollowersValidator
|
||||
{
|
||||
}
|
@ -1,44 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
/*
|
||||
* This file is part of the ActivityPhp package.
|
||||
*
|
||||
* Copyright (c) landrok at github.com/landrok
|
||||
*
|
||||
* For the full copyright and license information, please see
|
||||
* <https://github.com/landrok/activitypub/blob/master/LICENSE>.
|
||||
*/
|
||||
|
||||
namespace Plugin\ActivityPub\Util\Type\Validator;
|
||||
|
||||
use Exception;
|
||||
use Plugin\ActivityPub\Util\Type\Extended\Object\Tombstone;
|
||||
use Plugin\ActivityPub\Util\Type\Util;
|
||||
use Plugin\ActivityPub\Util\Type\ValidatorInterface;
|
||||
|
||||
/**
|
||||
* \Plugin\ActivityPub\Util\Type\Validator\FormerTypeValidator is a dedicated
|
||||
* validator for formerType attribute.
|
||||
*/
|
||||
class FormerTypeValidator implements ValidatorInterface
|
||||
{
|
||||
/**
|
||||
* Validate a formerType attribute value
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
public function validate(mixed $value, mixed $container): bool
|
||||
{
|
||||
// Validate that container has a Tombstone type
|
||||
Util::subclassOf($container, Tombstone::class, true);
|
||||
|
||||
if (\is_array($value)) {
|
||||
$value = Util::arrayToType($value);
|
||||
}
|
||||
|
||||
// MUST be a valid Object type
|
||||
return Util::isObjectType($value);
|
||||
}
|
||||
}
|
@ -1,48 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
/*
|
||||
* This file is part of the ActivityPhp package.
|
||||
*
|
||||
* Copyright (c) landrok at github.com/landrok
|
||||
*
|
||||
* For the full copyright and license information, please see
|
||||
* <https://github.com/landrok/activitypub/blob/master/LICENSE>.
|
||||
*/
|
||||
|
||||
namespace Plugin\ActivityPub\Util\Type\Validator;
|
||||
|
||||
use Exception;
|
||||
use Plugin\ActivityPub\Util\Type\Core\ObjectType;
|
||||
use Plugin\ActivityPub\Util\Type\Util;
|
||||
use Plugin\ActivityPub\Util\Type\ValidatorInterface;
|
||||
|
||||
/**
|
||||
* \Plugin\ActivityPub\Util\Type\Validator\GeneratorValidator is a dedicated
|
||||
* validator for generator attribute.
|
||||
*/
|
||||
class GeneratorValidator implements ValidatorInterface
|
||||
{
|
||||
/**
|
||||
* Validate a generator attribute value
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
public function validate(mixed $value, mixed $container): bool
|
||||
{
|
||||
// Validate that container has an ObjectType type
|
||||
Util::subclassOf($container, ObjectType::class, true);
|
||||
|
||||
if (Util::validateUrl($value)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (\is_array($value)) {
|
||||
$value = Util::arrayToType($value);
|
||||
}
|
||||
|
||||
// MUST be a valid Actor type
|
||||
return Util::isActorType($value) || Util::validateLink($value);
|
||||
}
|
||||
}
|
@ -1,43 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
/*
|
||||
* This file is part of the ActivityPhp package.
|
||||
*
|
||||
* Copyright (c) landrok at github.com/landrok
|
||||
*
|
||||
* For the full copyright and license information, please see
|
||||
* <https://github.com/landrok/activitypub/blob/master/LICENSE>.
|
||||
*/
|
||||
|
||||
namespace Plugin\ActivityPub\Util\Type\Validator;
|
||||
|
||||
use Exception;
|
||||
use Plugin\ActivityPub\Util\Type\Core\Link;
|
||||
use Plugin\ActivityPub\Util\Type\Extended\Object\Image;
|
||||
use Plugin\ActivityPub\Util\Type\Util;
|
||||
use Plugin\ActivityPub\Util\Type\ValidatorInterface;
|
||||
|
||||
/**
|
||||
* \Plugin\ActivityPub\Util\Type\Validator\HeightValidator is a dedicated
|
||||
* validator for height attribute.
|
||||
*/
|
||||
class HeightValidator implements ValidatorInterface
|
||||
{
|
||||
/**
|
||||
* Validate height value
|
||||
*
|
||||
* @param mixed $container An object
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
public function validate(mixed $value, mixed $container): bool
|
||||
{
|
||||
// Validate that container is a Link
|
||||
Util::subclassOf($container, [Link::class, Image::class], true);
|
||||
|
||||
// Must be a non-negative integer
|
||||
return Util::validateNonNegativeInteger($value);
|
||||
}
|
||||
}
|
@ -1,48 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
/*
|
||||
* This file is part of the ActivityPhp package.
|
||||
*
|
||||
* Copyright (c) landrok at github.com/landrok
|
||||
*
|
||||
* For the full copyright and license information, please see
|
||||
* <https://github.com/landrok/activitypub/blob/master/LICENSE>.
|
||||
*/
|
||||
|
||||
namespace Plugin\ActivityPub\Util\Type\Validator;
|
||||
|
||||
use Exception;
|
||||
use Plugin\ActivityPub\Util\Type\Core\Link;
|
||||
use Plugin\ActivityPub\Util\Type\Core\ObjectType;
|
||||
use Plugin\ActivityPub\Util\Type\Util;
|
||||
use Plugin\ActivityPub\Util\Type\ValidatorInterface;
|
||||
|
||||
/**
|
||||
* \Plugin\ActivityPub\Util\Type\Validator\HrefValidator is a dedicated
|
||||
* validator for href attribute.
|
||||
*/
|
||||
class HrefValidator implements ValidatorInterface
|
||||
{
|
||||
/**
|
||||
* Validate href value
|
||||
*
|
||||
* @param mixed $container An object
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
public function validate(mixed $value, mixed $container): bool
|
||||
{
|
||||
// Validate that container is a Link or an Object
|
||||
Util::subclassOf(
|
||||
$container,
|
||||
[Link::class, ObjectType::class],
|
||||
true,
|
||||
);
|
||||
|
||||
// Must be a valid URL or a valid magnet link
|
||||
return Util::validateUrl($value)
|
||||
|| Util::validateMagnet($value);
|
||||
}
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user