sgalinski / sg-vimeo
A solution for embedding Vimeo videos, playlists, or channels easily into TYPO3 pages.
Requires
- typo3/cms-core: ^12.4.0
- vimeo/vimeo-api: ^3.0
Replaces
- sgalinski/sg_vimeo: 5.0.0
This package is not auto-updated.
Last update: 2024-11-01 21:17:27 UTC
README
License: GNU GPL, Version 2
Repository: https://gitlab.sgalinski.de/typo3/sg_vimeo
Please report bugs here: https://gitlab.sgalinski.de/typo3/sg_vimeo
Installation / Integration
First install the extension and activate it in the Extension Manager.
Vimeo app
- Create a new vimeo app: https://developer.vimeo.com/apps/new
- Answer the question
Will people besides you be able to access your app?
with:No. The only Vimeo accounts that will have access to the app are my own.
- Go to your vimeo app on https://developer.vimeo.com/apps and copy your client identifier & client secret.
TypoScript integration
- Include the TypoScript in Configuration/TypoScript/setup.typoscript and constants.typoscript in your theme.
- Add your Vimeo client identifier & client secret (and optionally your personal access token):
plugin.tx_sgvimeo {
settings {
# cat=plugin.tx_sgvimeo/file; type=string; label=Vimeo client identifier
clientId = <your-client-id>
# cat=plugin.tx_sgvimeo/file; type=string; label=Vimeo client secret
clientSecret = <your-client-secret>
# cat=plugin.tx_sgvimeo/file; type=string; label=Vimeo Personal access token
personalAccessToken =
}
}
Private videos
If you have a video which is not available to the public, but you want to show it on your website, you need an authenticated personal access token. You can find a guide, on how to generate such a token here: https://vimeo.zendesk.com/hc/en-us/articles/360042445032-How-do-I-generate-a-personal-access-token-
The following requirements have to be met, for the private video to show up:
- the video has to be hosted on the same vimeo account, that was used to configure the clientSecret & clientId (vimeo app)
- a personal access token with access scope "private" has to be configured in the typoscript settings ( personalAccessToken)
Working with Rate Limits
As with almost every API, there is a usage limit, which depends on the vimeo user membership of the user, that makes the API requests (the owner of the vimeo app).
sg_vimeo uses the following endpoints:
- Video - api.vimeo.com/videos/{video_id}
- Channel Videos - api.vimeo.com/channels/{channel_id}/videos
sg_vimeo uses field filtering to request only the fields that are needed.
Caching behaviour
Because of the quota costs, we implemented a caching for the calls for each day. The response from the APIs will be saved and used for 24 hours. Normally, the site cache would do it, but it could be, that the cache will be cleared multiple times in a row, or that the plugin is on an uncached page. The TYPO3 registry is used as a cache. The cleanup is handled on the fly.
If the ?disableVimeoCache=1
parameter is added to the URL, this cache will be ignored as well.
.htaccess - Content-Security-Policy
Requires img-src https://i.vimeocdn.com;
, script-src https://player.vimeo.com;
.
Making changes in JavaScript/CSS
We are shipping the extension with source files and already minified assets. By default, we the minified assets are loaded in the Layout, so that the extension works out of the box just with plug and play. Should you want to change this behavior, you can do the following:
- Override the layout path in TypoScript local/project_theme/Configuration/TypoScript/Extensions/SgVimeo/Constants.typoscript
plugin.tx_sgvimeo {
settings {
clientId = MY_CLIENT_ID
clientSecret = MY_CLIENT_SECRET
}
view {
layoutRootPath = EXT:project_theme/Resources/Private/Layouts/SgVimeo/
}
}
- Create a new layout file omitting the assets that you would like to change (for example, loading without CSS)
<div class="tx-sg-vimeo">
<f:asset.script identifier="sgVideoJs" src="EXT:sg_vimeo/Resources/Public/JavaScript/Dist/main.bundled.min.js" />
<f:render section="main"/>
</div>
- Import the CSS or JavaScript source files in your respective asset pipeline and add them externally.
Compiling CSS/JS assets with SGC
- Install the sgalinski/sgc-core library via composer
- Add the sg-vimeo extension paths in the .sgc-config.json
- Remove the loading of the compiled CSS/JS assets from Resources/Private/Templates/Vimeo/Index.html
- Add import the scss and js module file in the corresponding main.scss and main.js
- Initialize the javascript modules in your main.js:
new SgVideoLightbox(); SgVideo.initDefault();
- If you want to recompile the JS with SGC, you must add
excludeFromQa: ['!**/Backend/**/*']
to your .sgc-config.js and also set your main extension in extensions to sg-vimeoextensions: ['sg-vimeo']
Compiling SASS only without SGC
Example:
npm install -g sass
npx sass ./Resources/Public/Sass/Bootstrap5/main.scss ./Resources/Public/StyleSheets/Bootstrap5/main.min.css --style compressed --no-source-map
Using the Bootstrap 5 templates
If you want to use the Bootstrap 5 templates, you have to first install Bootstrap 5 in your theme to use its styles and JavaScript.
Afterwards simply set the plugin.tx_project_theme.config.bootstrapVersion
TypoScript setup variable to 5.
Using Events to Customize Vimeo API Results in TYPO3
This documentation explains how to leverage custom events in your TYPO3 extension to manipulate the results of Vimeo API calls. By using these events, you can modify the API parameters, filter results, and further customize the JSON data returned from Vimeo.
Available Events
The following events are dispatched in the Vimeo video rendering process:
BeforeVimeoCallEvent
AfterVimeoCallEvent
AfterFilterVideosEvent
AfterMapCustomThumbnailsEvent
Event Listeners
1. BeforeVimeoCallEvent
Description: This event is triggered before making the Vimeo API call, allowing you to modify the API parameters.
Example Use Case: Change API Key or manipulate other paramters
<?php
namespace Vendor\Extension\EventListener;
use SGalinski\SgVimeo\Event\BeforeVimeoCallEvent;
class BeforeVimeoCallEventListener
{
public function __invoke(BeforeVimeoCallEvent $event): void
{
// Change the API key
$event->setApiKey('your-new-api-key');
// Extend the max results limit by 10 videos
$event->setMaxResultsWithFilters($event->getMaxResultsWithFilters() + 10);
}
}
2. AfterVimeoCallEvent
Description: Add Custom Data to JSON Array
Example Use Case: Change API Key or manipulate other paramters
<?php
namespace SGalinski\SgVimeo\EventListeners;
use SGalinski\SgVimeo\Event\AfterVimeoCallEvent;
class AfterVimeoCallEventListener
{
public function __invoke(AfterVimeoCallEvent $event): void
{
$response = $event->getResponse();
// Add custom data
$response['customData'] = 'This is some custom data';
$event->setResponse($response);
}
}
3. AfterFilterVideosEvent
Description: This event is triggered after the videos have been filtered, allowing you to further manipulate the filtered results.
Example Use Case: Remove the 10 videos that we added initially with the first event
<?php
namespace SGalinski\SgVimeo\EventListeners;
use SGalinski\SgVimeo\Event\AfterFilterVideosEvent;
class AfterFilterVideosEventListener
{
public function __invoke(AfterFilterVideosEvent $event): void
{
// Modify the response if needed
$response = $event->getResponse();
// Add some custom processing here
// For example let's remove the extra 10 videos that we added in the other event
if (count($response['items']) > 10) {
array_splice($response['items'], 0, 10);
}
$event->setResponse($response);
}
}
4. AfterMapCustomThumbnailsEvent
Description: This event is triggered after custom thumbnails have been mapped, allowing you to modify the JSON array one last time before rendering.
Example Use Case: Use a custom thumbnail for all videos in the list
<?php
namespace SGalinski\SgVimeo\EventListeners;
use SGalinski\SgVimeo\Event\AfterMapCustomThumbnailsEvent;
class AfterMapCustomThumbnailsEventListener
{
public function __invoke(AfterMapCustomThumbnailsEvent $event): void
{
$response = $event->geRresponse();
// Add a custom thumbnail URL
foreach ($response['items'] as &$item) {
$item['customThumbnail'] = 'https://example.com/custom-thumbnail.jpg';
}
$event->setResponse($response);
}
}
To enable the events just register them in your Services.php as follows (you can use yaml instead if you prefer):
$services->set(BeforeVimeoCallEventListener::class)
->tag('event.listener', ['event' => BeforeVimeoCallEvent::class]);
$services->set(AfterVimeoCallEventListener::class)
->tag('event.listener', ['event' => AfterVimeoCallEvent::class]);
$services->set(AfterFilterVideosEventListener::class)
->tag('event.listener', ['event' => AfterFilterVideosEvent::class]);
$services->set(AfterMapCustomThumbnailsEventListener::class)
->tag('event.listener', ['event' => AfterMapCustomThumbnailsEvent::class]);
Usage in non-composer mode (Classic, Legacy)
This extentension has depdendencies from 3rd party sources that we import through composer. Should you have an installation in legacy mode (non-composer), we need to import these libraries. For this purpose we have the Libraries/ directory where we put the dependencies as PHAR files. You can check how they are used in Services/VimeoService.php.
If the dependencies are updated in composer though, we need to regenerate the PHAR file and commit it again. For this we first pull the new version with composer and then we need to create the PHAR archive by using the following PHP code:
<?php
$pharFile = __DIR__ . '/../sg_vimeo.phar';
// Remove previous PHAR file if it exists
if (file_exists($pharFile)) {
unlink($pharFile);
}
$phar = new Phar($pharFile);
$phar->startBuffering();
// Add your extension's files
$phar->buildFromDirectory(__DIR__ . '/../sg_vimeo');
// Optionally, add files from the vendor directory
$phar->buildFromDirectory(__DIR__ . '/../sg_vimeo');
// Optionally, set the default stub to load an entry script
$stub = <<<EOD
<?php
Phar::mapPhar();
require 'phar://' . __FILE__ . '/Classes/Main.php';
__HALT_COMPILER();
EOD;
$phar->setStub($stub);
// Stop buffering and save the PHAR file
$phar->stopBuffering();
echo "PHAR file created successfully!";
Once it runs it will create the file and we can commit the new version and use it.
Setting Up the Frontend Filers
Step 1: Adding the Plugin to a Page
- In the TYPO3 backend, create or edit the page where you want to display Vimeo videos.
- Add a new content element and select the Vimeo plugin from the list.
- Provide the necessary Vimeo details in the plugin settings (like Vimeo API key, video/channel/playlist ID, max results, etc.).
Step 2: Disable caching for the extension and Cache validation for your web page
- In the TYPO3 backend, go to Settings -> Extensions and open the sg_vimeo settings. Tick the box that says 'uncached' and save.
- This way the the extension will not cache the results and the the data will be loaded dynamically based on the filter settings
- Set
$GLOBALS['TYPO3_CONF_VARS']['FE']['cacheHash']['enforceValidation'] = false
in your TYPO3 configuration, otherwise using the frontend filters may result in a 404 page in some instances.
Step 3: Configuring Filters via FlexForm
- In the plugin's FlexForm settings, you will see a section for "Filters."
- Depending on your site configuration, filters will be available in a select field. You can select the filters you want to display (like search term, video duration, etc.).
- Save your settings and publish the page.
- IMPORTANT! You must make sure that the user associated with the clientId and clientSecret API keys has the right permissions to search in the channel where the filters are being used. Otherwise searching for a query string will always result in an empty result set.
3. Using Filters in the Frontend
Once filters are enabled, they will appear on the frontend in a form, allowing users to interact with the displayed videos dynamically. For example:
- Search Term: Allows users to input a search term to filter videos based on keywords.
- Duration Filter: Provides a dropdown to filter videos by length (short, medium, long, etc.).
The filter values are sent to the Vimeo API, and the video list updates based on the selected criteria.
4. TypoScript Configuration for Filters
To define custom filters, the plugin uses TypoScript. Below is an example configuration and an explanation of each section:
Example TypoScript Configuration
filters {
searchTerm {
label = LLL:EXT:sg_vimeo/Resources/Private/Language/locallang.xlf:filter.searchTerm
partial = Filters/TextField
filterClass = SGalinski\SgVimeo\Filter\QueryStringFilter
defaultValues {
# search = test
}
position = top
}
duration {
label = LLL:EXT:sg_vimeo/Resources/Private/Language/locallang.xlf:filter.duration
partial = Filters/Dropdown
filterClass = SGalinski\SgVimeo\Filter\DurationFilter
position = top
options {
0 {
label = LLL:EXT:sg_vimeo/Resources/Private/Language/locallang.xlf:filter.duration.0
value = 1
}
1 {
label = LLL:EXT:sg_vimeo/Resources/Private/Language/locallang.xlf:filter.duration.1
value = 2
}
}
}
}
submitButton {
position = top
cssClass = btn btn-default
label = LLL:EXT:sg_vimeo/Resources/Private/Language/locallang.xlf:filter.submitButton
}
Explanation of the Configuration
filters
This TypoScript object defines all the available filters for the Vimeo plugin. Each filter is a separate sub-object, like searchTerm
and duration
in the example.
Filter Fields
searchTerm
(Text Field)- label: The label for the filter form field. This can be translated using the TYPO3 language file (
locallang.xlf
). - partial: Specifies which partial file to use for rendering the filter. In this case, it points to a text field (
Filters/TextField
). - filterClass: This is the PHP class responsible for processing the filter and applying it to the Vimeo API request. For the
searchTerm
, it's aQueryStringFilter
. - defaultValues: You can specify default values for the filter (commented out in the example).
- position: Defines where the filter should be displayed on the page. It can be
top
(above the video list) orbottom
(below the video list).
- label: The label for the filter form field. This can be translated using the TYPO3 language file (
duration
(Dropdown)- label: The label for the filter form field.
- partial: Points to a dropdown partial (
Filters/Dropdown
). - filterClass: This is the PHP class responsible for processing the filter. For
duration
, it'sDurationFilter
. - options: This section defines the options for the dropdown, each with a
label
(for the user to see) and avalue
(sent to the API). - position: Indicates where the filter should be displayed on the page.
submitButton
- Defines the configuration for the submit button:
- position: Determines where the submit button is placed in the form (
top
in this case). It acceptstop
,bottom
orboth
- cssClass: Adds CSS classes for styling the button.
- label: Provides the text for the submit button (translatable using
locallang.xlf
).
- position: Determines where the submit button is placed in the form (
5. Adding Custom Filters
You can easily extend the plugin by defining your own filters in TypoScript:
Create a New Filter Add a new filter object under
filters
in your TypoScript setup. For example, if you want to filter by video quality, your configuration might look like this:filters { quality { label = LLL:EXT:sg_vimeo/Resources/Private/Language/locallang.xlf:filter.quality partial = Filters/Dropdown filterClass = SGalinski\SgVimeo\Filter\QualityFilter position = top options { 0 { label = HD value = hd } 1 { label = SD value = sd } } } }
Implement the Filter Logic You will need to define the corresponding PHP
filterClass
that handles the logic for applying the filter to the Vimeo API request. For example, theQualityFilter
class would process the selected video quality and add the appropriate parameters to the API request. It must implement the FilterInterface interface. The modifyRequest method is called before sending the reuqest, while the modifyResponse method is called after receiving the response.
6. Working with Filter Positions
You can choose where filters are displayed (above or below the video list) by setting the position
attribute in the TypoScript configuration. This allows you to create a flexible layout for filters:
- Filters with
position = top
will be displayed before the video list. - Filters with
position = bottom
will be displayed after the video list.
For example:
filters {
searchTerm {
position = top
}
duration {
position = bottom
}
}
7. Debugging and Error Handling
If something goes wrong (e.g., videos aren't displayed, or the API request fails), here are a few things to check:
- Make sure the Vimeo API key is correctly configured.
- Check the TypoScript configuration for errors (e.g., missing or incorrect filter definitions).
- Look for error messages in the TYPO3 backend log for issues related to the plugin.
8. Conclusion
With this flexible filter system, you can easily customize the Vimeo video list based on user input. By defining filters in TypoScript and adding them to the plugin's FlexForm, you provide an interactive and tailored experience for your site's visitors.
If you need to add more filters, just extend the TypoScript configuration, create the necessary filter classes, and you're ready to go!