landrok/activitypub

基于 ActivityStreams 2.0 数据格式的 ActivityPub 协议的 PHP 实现。

0.7.2 2024-04-03 07:32 UTC

This package is auto-updated.

Last update: 2024-09-07 17:49:16 UTC


README

Build Status Maintainability Test Coverage

ActivityPhp 是 PHP 中 ActivityPub 层的实现。

它提供两层:

  • 一个 客户端到服务器协议,或称为 "社交 API"。此协议允许客户端代表用户进行操作。
  • 一个 服务器到服务器协议,或称为 "联盟协议"。此协议用于在不同服务器上的参与者之间分发活动,将它们绑定到同一个社交图谱中。

随着这两层的实现,它旨在成为符合 ActivityPub 的联邦服务器

所有规范化的类型都已实现。如果您需要创建一个新的类型,只需扩展现有类型即可。

查看完整文档 或下面的概述。

目录

要求

  • 支持 PHP 7.4 | 8.0+

安装

composer require landrok/activitypub

ActivityStreams 核心类型

提供所有核心类型

use ActivityPhp\Type\Core\Activity;
use ActivityPhp\Type\Core\Collection;
use ActivityPhp\Type\Core\CollectionPage;
use ActivityPhp\Type\Core\IntransitiveActivity;
use ActivityPhp\Type\Core\Link;
use ActivityPhp\Type\Core\ObjectType;
use ActivityPhp\Type\Core\OrderedCollection;
use ActivityPhp\Type\Core\OrderedCollectionPage;

ActivityStreams 扩展类型

提供所有扩展类型

参与者类型

use ActivityPhp\Type\Extended\Actor\Application;
use ActivityPhp\Type\Extended\Actor\Group;
use ActivityPhp\Type\Extended\Actor\Organization;
use ActivityPhp\Type\Extended\Actor\Person;
use ActivityPhp\Type\Extended\Actor\Service;

活动类型

use ActivityPhp\Type\Extended\Activity\Accept;
use ActivityPhp\Type\Extended\Activity\Add;
use ActivityPhp\Type\Extended\Activity\Announce;
use ActivityPhp\Type\Extended\Activity\Arrive;
use ActivityPhp\Type\Extended\Activity\Block;
use ActivityPhp\Type\Extended\Activity\Create;
use ActivityPhp\Type\Extended\Activity\Delete;
use ActivityPhp\Type\Extended\Activity\Dislike;
use ActivityPhp\Type\Extended\Activity\Flag;
use ActivityPhp\Type\Extended\Activity\Follow;
use ActivityPhp\Type\Extended\Activity\Ignore;
use ActivityPhp\Type\Extended\Activity\Invite;
use ActivityPhp\Type\Extended\Activity\Join;
use ActivityPhp\Type\Extended\Activity\Leave;
use ActivityPhp\Type\Extended\Activity\Like;
use ActivityPhp\Type\Extended\Activity\Listen;
use ActivityPhp\Type\Extended\Activity\Move;
use ActivityPhp\Type\Extended\Activity\Offer;
use ActivityPhp\Type\Extended\Activity\Question;
use ActivityPhp\Type\Extended\Activity\Read;
use ActivityPhp\Type\Extended\Activity\Reject;
use ActivityPhp\Type\Extended\Activity\Remove;
use ActivityPhp\Type\Extended\Activity\TentativeAccept;
use ActivityPhp\Type\Extended\Activity\TentativeReject;
use ActivityPhp\Type\Extended\Activity\Travel;
use ActivityPhp\Type\Extended\Activity\Undo;
use ActivityPhp\Type\Extended\Activity\Update;
use ActivityPhp\Type\Extended\Activity\View;

对象类型

use ActivityPhp\Type\Extended\Object\Article;
use ActivityPhp\Type\Extended\Object\Audio;
use ActivityPhp\Type\Extended\Object\Document;
use ActivityPhp\Type\Extended\Object\Event;
use ActivityPhp\Type\Extended\Object\Image;
use ActivityPhp\Type\Extended\Object\Mention;
use ActivityPhp\Type\Extended\Object\Note;
use ActivityPhp\Type\Extended\Object\Page;
use ActivityPhp\Type\Extended\Object\Place;
use ActivityPhp\Type\Extended\Object\Profile;
use ActivityPhp\Type\Extended\Object\Relationship;
use ActivityPhp\Type\Extended\Object\Tombstone;
use ActivityPhp\Type\Extended\Object\Video;

类型

类型工厂

您可以使用它们的短名称实例化 ActivityStreams 类型。

use ActivityPhp\Type;

$link = Type::create('Link');
$note = Type::create('Note');

使用第二个参数,您可以实例化一个类型并设置属性。

use ActivityPhp\Type;

$note = Type::create('Note', [
    'content' => 'A content for my note'
]);

从具有 'type' 键的数组开始,甚至可以直接实例化您的类型。

use ActivityPhp\Type;

$array = [
    'type'    => 'Note',
    'content' => 'A content for my note'
];

$note = Type::create($array);

属性名称

对于任何对象或链接,您都可以使用 getProperties() 方法获取所有属性名称。

use ActivityPhp\Type;

$link = Type::create('Link');

print_r(
    $link->getProperties()
);

输出类似以下内容

Array
(
    [0] => type
    [1] => id
    [2] => name
    [3] => nameMap
    [4] => href
    [5] => hreflang
    [6] => mediaType
    [7] => rel
    [8] => height
    [9] => preview
    [10] => width
)

所有属性及其值

要转储所有属性及其关联的值,请使用 toArray() 方法。

use ActivityPhp\Type;

$link = Type::create('Link');
$link->setName('An example');
$link->setHref('http://example.com');

print_r(
    $link->toArray()
);

输出类似以下内容

Array
(
    [type] => Link
    [name] => An example
    [href] => http://example.com
)

获取一个属性

有 3 种等效的方式来获取值。

use ActivityPhp\Type;

$note = Type::create('Note');

// Each method returns the same value
echo $note->id;
echo $note->get('id');
echo $note->getId();

设置一个属性

有 3 种等效的方式来设置值。

use ActivityPhp\Type;

$note = Type::create('Note');

$note->id = 'https://example.com/custom-notes/1';
$note->set('id', 'https://example.com/custom-notes/1');
$note->setId('https://example.com/custom-notes/1');

在您分配值时,将检查此值的格式。

此操作由验证器执行。如果不遵守规则,将抛出异常。

当属性不存在时,在严格模式下会抛出异常。您可以定义 3 种不同的行为

  • 抛出异常(默认=严格)
  • 忽略属性(忽略)
  • 设置属性(包含)
use ActivityPhp\Type;
use ActivityPhp\Type\TypeConfiguration;

$note = Type::create('Note');

// Ignore mode
TypeConfiguration::set('undefined_properties', 'ignore');
$note->undefinedProperty = 'https://example.com/custom-notes/1';
echo $note->undefinedProperty; // null

// Include mode
TypeConfiguration::set('undefined_properties', 'include');
$note->undefinedProperty = 'https://example.com/custom-notes/1';
echo $note->undefinedProperty; // https://example.com/custom-notes/1

// Strict mode
TypeConfiguration::set('undefined_properties', 'strict');
$note->undefinedProperty = 'https://example.com/custom-notes/1'; // Exception

设置多个属性

使用 类型工厂,您可以实例化一个类型并设置多个属性。

use ActivityPhp\Type;

$note = Type::create('Note', [
    'id'   => 'https://example.com/custom-notes/1',
    'name' => 'An important note',
]);

创建一个副本

有时您可能使用副本以不影响原始类型的值。

use ActivityPhp\Type;

$note = Type::create('Note', ['name' => 'Original name']);

$copy = $note->copy()->setName('Copy name');

echo $copy->name; // Copy name
echo $note->name; // Original name

您可以复制并链式调用方法来仅影响副本类型的值。

检查属性是否存在

use ActivityPhp\Type;

$note = Type::create('Note');

echo $note->has('id'); // true
echo $note->has('anotherProperty'); // false

使用原生类型

所有核心和扩展类型都使用经典实例化。

use ActivityPhp\Type\Extended\Object\Note;

$note = new Note();

与类型工厂相同的方式

use ActivityPhp\Type;

$note = Type::create('Note');

使用您自己的扩展类型

如果您需要一些自定义属性,可以扩展预定义的类型。

  • 创建您自己的类型
use ActivityPhp\Type\Extended\Object\Note;

class MyNote extends Note
{
    // Override basic type
    protected $type = 'CustomNote';

    // Custom property
    protected $myProperty;
}

有两种方式来实例化一个类型

  • 一个经典的 PHP 调用
$note = new MyNote();
$note->id = 'https://example.com/custom-notes/1';
$note->myProperty = 'Custom Value';

echo $note->getMyProperty(); // Custom Value
  • 使用类型工厂
use ActivityPhp\Type;

$note = Type::create('MyNote', [
    'id' => 'https://example.com/custom-notes/1',
    'myProperty' => 'Custom Value'
]);

扩展类型可以保留获取器、设置器和它们的验证器的优势。

创建您自己的属性验证器

当您定义自定义属性或想要覆盖ActivityPub属性的默认验证时,请使用自定义属性验证器。

关于前面的自定义属性示例 $myProperty,如果您尝试设置此属性,它将不会对您提供的值进行任何检查。

您可以通过使用 Validator 实现自定义验证器来轻松应对。

use ActivityPhp\Type\ValidatorInterface;
use ActivityPhp\Type\Validator;

// Create a custom validator that implements ValidatorInterface
class MyPropertyValidator implements ValidatorInterface
{
    // A public validate() method is mandatory
    public function validate($value, $container)
    {
        return true;
    }
}

// Attach this custom validator to a property
Validator::add('myProperty', MyPropertyValidator::class);

// Now all values are checked with the validate() method
// 'myProperty' is passed to the first argument
// $note is passed to the second one.

$note->myProperty = 'Custom Value';

另一种等效的方法是使用类型工厂和 addValidator() 方法。

use ActivityPhp\Type;

// Attach this custom validator to a property
Type::addValidator('myProperty', MyPropertyValidator::class);

服务器

服务器实例是联邦的入口点。

其目的是适当接收、发送和转发活动。

最小化方法如下

use ActivityPhp\Server;

$server = new Server();

有关更多配置参数,请参阅完整文档

WebFinger

WebFinger 是一种允许发现有关人员的信息的协议。

给定一个处理程序,ActivityPub 实例可以使用此协议发现配置文件。

use ActivityPhp\Server;

$server = new Server();

$handle = 'bob@example.org';

// Get a WebFinger instance
$webfinger = $server->actor($handle)->webfinger();

在此实现中,我们可以使用对象标识符(URI)而不是 WebFinger 处理程序。

use ActivityPhp\Server;

$server = new Server();

$handle = 'https://example.org/users/bob';

// Get a WebFinger instance
$webfinger = $server->actor($handle)->webfinger();

WebFinger::toArray()

获取所有 WebFinger 数据作为数组。

use ActivityPhp\Server;

$server = new Server();

$handle = 'bob@example.org';

// Get a WebFinger instance
$webfinger = $server->actor($handle)->webfinger();

// Dumps all properties
print_r($webfinger->toArray());

// A one line call
print_r(
    $server->actor($handle)->webfinger()->toArray()
);

输出类似以下内容

Array
(
    [subject] => acct:bob@example.org
    [aliases] => Array
        (
            [0] => http://example.org/users/bob
        )
    [links] => Array
        (
            [0] => Array
                (
                    [rel] => self
                    [type] => application/activity+json
                    [href] => http://example.org/users/bob
                )
        )
)

WebFinger::getSubject()

获取 WebFinger 资源。

echo $webfinger->getSubject();

// Would output 'acct:bob@example.org'

WebFinger::getProfileId()

获取 ActivityPub 对象标识符(URI)。

echo $webfinger->getProfileId();

// Would output 'http://example.org/users/bob'

WebFinger::getHandle()

获取配置文件处理程序。

echo $webfinger->getHandle();

// Would output 'bob@example.org'

WebFinger::getAliases()

获取此配置文件的全部别名条目。

print_r(
    $webfinger->getAliases()
);

输出类似以下内容

Array
(
    [0] => http://example.org/users/bob
)

WebFinger::getLinks()

获取此配置文件的全部链接条目。

print_r(
    $webfinger->getLinks()
);

输出类似以下内容

Array
(
    [0] => Array
        (
            [rel] => self
            [type] => application/activity+json
            [href] => http://example.org/users/bob
        )
)

更多