EmbedAPI module
This module provides the ability for other sites to embed content from this site. It follows the oEmbed standard.
Embed plugins
Content can be embeded by providing an embed plugin. This defines what paths it should respond to and how it is rendered.
To add a new Embed plugin
Create a Plugins/Embed/Plugins dir in your module and create a class that extends BaseEmbed. You should just need to override the properties provided in BaseEmbed but there is plenty of flexibility should you need to do something more tricky.
EmbedPlugin example
<?php
namespace Modules\MyModule\Plugins\Embed\Plugins;
use Modules\EmbedApi\Plugins\BaseEmbed;
use Modules\MyModule\Http\Resources\MyModelResource;
use Modules\MyModule\Models\MyModel;
class SurveyEmbed extends BaseEmbed
{
public const MACHINE_NAME = 'my_module_model';
protected string $label = 'My Module Model';
protected string $machine_name = self::MACHINE_NAME;
protected string $description = 'Embed my model';
protected string $component = '~MyModule/Components/MyModelEmbed';
protected array $matchingRouteNames = ['my_model.show'];
protected ?string $modelClassName = MyModel::class;
protected ?string $modelResource = MyModelResource::class;
protected ?string $modelParameter = 'my_model';
}
See EmbedInterface for more of a definition.
EmbedPlugin component example
You must also define how your embed will be rendered, the EmbedPlugin will be responsible for defining all the settings and props, you just need to create a vue component. Eg.
<template>
<district-embeddable class="survey-embed">
<h2>This is the content of my model {{ model.title }} embed</h2>
<p>{{ model.summary }}</p>
</district-embeddable>
</template>
<script>
import DistrictEmbeddable from '~EmbedApi/Components/Embeddable'
export default {
name: 'survey-embed',
components: {DistrictEmbeddable, SurveyForm},
props: {
model: Object,
},
}
</script>
Just be sure to wrap your component in district-embeddable as this will be responsible for sending resize events to the parent.
oEmbed endpont
The oEmbed endpoint works with embed plugins to translate a public url into oEmbed spec and html. You just need a GET request to the /oembed path with a url parameter set which is the url to the public page you want to embed.
NOTE: There must be an Embed Plugin which matches the url provided.
Example
To work with above embed plugin example, you have a public route my_model.show with a model parameter of my_model and the uri signature is /my_module/show/{my_model:slug}
Visit /oembed?url=http://localhost/my_module/show/model-slug
It should return something like
{
"title": "My model title",
"author_name": "District",
"author_url": "http://localhost",
"type": "my_model",
"width": "100%",
"height": "100%",
"version": "1.0",
"provider_name": "District",
"provider_url": "http://district.au",
"html": "<a src=\"http://localhost/my_module/show/model-slug\" data-embed-url=\"http://district-core.lndo.site/embed/my_model/model-slug\" class=\"district-embed\" data-width=\"100%\" data-height=\"100%\">My model title</a><script async src=\"http://district-core.lndo.site/js/embed.js\" charset=\"utf-8\"></script>"
}
The html prop will transform into an embedded and auto resizing iframe!
Testing embedding
You can see how an embed will look (and also test out the oEmbed endpoint works as expected) via a little demo site. See the README.md here for instructions.
TODOs and Gotchas
- Iframes have inherit security issues, we do some mitigation via the
EmbeddableMiddlewareand only allow the embed of specific/embed/plugin/keyroute but we probably want to dive deeper into security implications here. - A CSFR exception has been added for
/media_api/upload/checktoVerifyCsrfTokenmiddleware as there was csfr errors for this route when uploading files when embedded in iframe. TODO fix or at least only add that exception when parent on embed route. - Minify
embed.js