cerpus/edlib-resource-kit

为 Edlib 创建资源类型

v0.5.0 2022-12-08 14:03 UTC

README

codecov

Edlib 创建自定义内容类型。

要求

  • PHP 8.2
  • A PSR-17 实现,例如 guzzlehttp/psr7
  • A PSR-18 兼容的 HTTP 客户端,例如 Guzzle 7
  • 对 Edlib 内部服务的网络访问
  • 与 Edlib 共享的 RabbitMQ 实例(可选)

安装

composer require cerpus/edlib-resource-kit guzzlehttp/guzzle:^7 guzzlehttp/psr7

使用(Edlib 3)

Edlib 3 通过 LTI Content-Item Message 标准(LTI Content-Item Message standard)通知新内容,而不是通过专用 API 在私有网络连接中进行通信。Edlib Resource Kit 提供用于处理 Content-Item 消息的消息对象、映射器和序列化器。

映射

将序列化 Content-Item 图映射到消息对象

use Cerpus\EdlibResourceKit\Lti\Lti11\Mapper\DeepLinking\ContentItemsMapper;

$mapper = new ContentItemsMapper();
$items = $mapper->map(<<<EOJSON
{
    "@context": "http://purl.imsglobal.org/ctx/lti/v1/ContentItem",
    "@graph": [
        {
            "@type": "LtiLinkItem",
            "mediaType": "application/vnd.ims.lti.v1.ltilink",
            "title": "My Cool LTI Content",
            "url": "https://example.com/my-lti-content"
        }
    ]
}
EOJSON);

echo count($items), "\n"; // 1
echo $items[0]->getTitle(), "\n"; // My Cool LTI Content

JSON 输入必须匹配压缩的 JSON-LD 表示形式,如 LTI Deep Linking 1.0 规范 中所示。如果输入不匹配,则可以使用 JSON-LD 处理器使输入符合规范。

序列化

将 Content-Item 消息对象转换为它们的序列化 JSON 表示形式

use Cerpus\EdlibResourceKit\Lti\Message\DeepLinking\LtiLinkItem;
use Cerpus\EdlibResourceKit\Lti\Lti11\Serializer\DeepLinking\ContentItemsSerializer;

$items = [
    new LtiLinkItem(
        mediaType: 'application/vnd.ims.lti.v1.ltilink',
        title: 'My Cool LTI Content',
        url: 'https://example.com/my-lti-content',
    ),
];

$serializer = new ContentItemsSerializer();
$serialized = $serializer->serialize($items);

echo json_encode($serialized);

输出

{
    "@context": "http://purl.imsglobal.org/ctx/lti/v1/ContentItem",
    "@graph": [
        {
            "@type": "LtiLinkItem",
            "mediaType": "application/vnd.ims.lti.v1.ltilink",
            "title": "My Cool LTI Content",
            "url": "https://example.com/my-lti-content"
        }
    ]
}

使用(旧 Edlib)

框架集成

我们提供了 Laravel 集成,简化了该包的使用。

配置

有两种方式使 Edlib 了解新资源

  • 使用消息总线
  • 同步 HTTP 请求

HTTP 方法较慢,但等待资源发布完成,允许进行错误处理。

使用消息总线方法时,必须提供 RabbitMQ 连接

use Cerpus\EdlibResourceKit\ResourceKit;
use Cerpus\PubSub\Connection\ConnectionFactory;

$connectionFactory = new ConnectionFactory('localhost', 5672, 'guest', 'guest');
$resourceKit = new ResourceKit($connectionFactory);

对于 HTTP 方法,除了提供 synchronousResourceManager 标志外,没有强制配置

use Cerpus\EdlibResourceKit\ResourceKit;

$resourceKit = new ResourceKit(synchronousResourceManager: true);

一旦您有了 ResourceKit 实例,就可以开始访问其各个组件

$resourceManager = $resourceKit->getResourceManager();
$versionManager = $resourecKit->getResourceVersionManager();

通知 Edlib 内容更新

给定一个表示您的自定义内容类型项(在本例中为文章)的模型类

namespace App\Models;

use Cerpus\EdlibResourceKit\Contract\EdlibResource;

class Article
{
    // Database-mapped article ID
    private string $id;

    public function toEdlibResource(): EdlibResource
    {
        return new ArticleEdlibResource($this->id, /* ... */);
    }
}

创建相应的 EdlibResource

namespace App\DataObjects;

use Cerpus\EdlibResourceKit\Contract\EdlibResource;

class ArticleEdlibResource implements EdlibResource
{
    public function __construct(private string $systemId, /* ... */)
    {
    }

    public function getSystemName(): string
    {
        return 'my-unique-and-persistent-system-name';
    }

    public function getSystemId(): string
    {
        return $this->systemId;
    }

    public function getContentType(): string|null
    {
        return 'article';
    }

    // ... implement the remaining EdlibResource methods here
}

当文章创建或更新时,必须对资源管理器进行相应的调用。该过程将根据您选择的框架而有所不同,但以下示例使用观察者模式演示了该过程

use Cerpus\EdlibResourceKit\Contract\EdlibResource;
use Cerpus\EdlibResourceKit\Resource\ResourceManagerInterface;

class ArticleObserver
{
    public function __construct(private ResourceManagerInterface $manager)
    {
    }

    public function onCreate(Article $article): void
    {
        $this->save($article->toEdlibResource());
    }

    public function onUpdate(Article $article): void
    {
        $this->save($article->toEdlibResource());
    }

    private function save(EdlibResource $resource): void
    {
        try {
            return $this->manager->save($resource);
        } catch (ResourceSaveFailedException $e) {
            // handle the failure somehow
        }
    }
}

如果一切顺利,资源现在应可以从 Edlib 内部访问。

高级使用

覆盖 HTTP 客户端 & 消息工厂

此库将寻找并使用任何已安装的 PSR-17 兼容消息工厂和 PSR-18 兼容 HTTP 客户端(通过 HTTPlug Discovery)。您可以使用您选择的工厂和客户端来覆盖它们

use App\Http\MyClient;
use App\Http\MyRequestFactory;
use App\Http\MyStreamFactory;
use Cerpus\EdlibResourceKit\ResourceKit;

$resourceKit = new ResourceKit(
    httpClient: new MyClient(),
    requestFactory: new MyRequestFactory(),
    streamFactory: new MyStreamFactory(),
    synchronousResourceManager: true,
);

通过连接您 Web 框架提供的 HTTP 客户端,您可以获得更好的日志记录和调试功能。

发布资源时添加额外数据

在发布资源之前,可能需要向其添加额外数据。这可以通过自定义序列化器来完成。

use Cerpus\EdlibResourceKit\Contract\EdlibResource;
use Cerpus\EdlibResourceKit\ResourceKit;
use Cerpus\EdlibResourceKit\Serializer\ResourceSerializer;

class MySerializer extends ResourceSerializer
{
    public function serialize(EdlibResource $resource): array
    {
        $data = parent::serialize($resource);

        if ($resource instanceof MyEdlibResource) {
            $data['some_custom_key'] => $resource->getMyCustomData();
        }

        return $data;
    }
}

$resourceKit = new ResourceKit($pubSub, resourceSerializer: new MySerializer());

许可证

本软件包采用GNU通用公共许可证3.0版发布。有关更多信息,请参阅LICENSE文件。