sgalinski/sg-vimeo

A solution for embedding Vimeo videos, playlists, or channels easily into TYPO3 pages.

Installs: 58

Dependents: 0

Suggesters: 0

Security: 0

Type:typo3-cms-extension

4.2.0 2024-06-06 12:59 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

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();

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:

  1. BeforeVimeoCallEvent
  2. AfterVimeoCallEvent
  3. AfterFilterVideosEvent
  4. 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]);