Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

IBX-9594: Describe creating a custom DAM connector #2642

Open
wants to merge 16 commits into
base: master
Choose a base branch
from
Open

Conversation

dabrt
Copy link
Contributor

@dabrt dabrt commented Feb 26, 2025

Question Answer
JIRA Ticket IBX-9594
Versions 4.6 and up
Edition all

Describe creating a custom DAM connector based on an example from @adriendupuis :
https://github.com/adriendupuis/ezplatform-connector-commons

Checklist

  • Text renders correctly
  • Text has been checked with vale
  • Description metadata is up to date
  • Redirects cover removed/moved pages
  • Code samples are working
  • PHP code samples have been fixed with PHP CS fixer
  • Added link to this PR in relevant JIRA ticket or code PR

Copy link

github-actions bot commented Feb 26, 2025

@dabrt dabrt requested a review from vidarl March 4, 2025 08:19
@dabrt dabrt requested a review from ViniTou March 5, 2025 16:36
Copy link

code_samples/ change report

Before (on target branch)After (in current PR)

code_samples/back_office/images/config/packages/views.yaml


code_samples/back_office/images/config/packages/views.yaml

docs/content_management/images/add_image_asset_from_dam.md@159:```yaml
docs/content_management/images/add_image_asset_from_dam.md@160:[[= include_file('code_samples/back_office/images/config/packages/views.yaml') =]]
docs/content_management/images/add_image_asset_from_dam.md@161:```

001⫶parameters:
002⫶ ibexa.<site_access>.image_asset_view_defaults:
003⫶ full:
004⫶ commons:
005⫶ template: '@@ibexadesign/commons_asset_view.html.twig'
006⫶ match:
007⫶ SourceBasedViewMatcher: commons
008⫶ default:
009⫶ template: '@@ibexadesign/ui/field_type/image_asset_view.html.twig'
010⫶ match: []


code_samples/back_office/images/config/services.yaml


code_samples/back_office/images/config/services.yaml

docs/content_management/images/add_image_asset_from_dam.md@107:```yaml
docs/content_management/images/add_image_asset_from_dam.md@108:[[= include_file('code_samples/back_office/images/config/services.yaml', 9, 14) =]]
docs/content_management/images/add_image_asset_from_dam.md@109:```

001⫶ App\Connector\Dam\Handler\WikimediaCommonsHandler:
002⫶ arguments:
003⫶ $httpClient: '@http_client'
004⫶ tags:
005⫶ - { name: 'ibexa.platform.connector.dam.handler', source: 'commons' }

docs/content_management/images/add_image_asset_from_dam.md@124:```yaml
docs/content_management/images/add_image_asset_from_dam.md@125:[[= include_file('code_samples/back_office/images/config/services.yaml', 15, 20) =]]
docs/content_management/images/add_image_asset_from_dam.md@126:```

001⫶ App\Connector\Dam\Transformation\TransformationFactory:
002⫶ arguments:
003⫶ $httpClient: '@http_client'
004⫶ tags:
005⫶ - { name: 'ibexa.platform.connector.dam.transformation_factory', source: 'commons' }

docs/content_management/images/add_image_asset_from_dam.md@143:```yaml
docs/content_management/images/add_image_asset_from_dam.md@144:[[= include_file('code_samples/back_office/images/config/services.yaml', 21, 25) =]]
docs/content_management/images/add_image_asset_from_dam.md@145:```

001⫶ commons_asset_variation_generator:
002⫶ class: Ibexa\Connector\Dam\Variation\URLBasedVariationGenerator
003⫶ tags:
004⫶ - { name: ibexa.platform.connector.dam.variation_generator, source: commons }

docs/content_management/images/images.md@216:```yaml
docs/content_management/images/images.md@216:```yaml
docs/content_management/images/images.md@217:[[= include_file('code_samples/back_office/images/config/services.yaml') =]]
docs/content_management/images/images.md@217:[[= include_file('code_samples/back_office/images/config/services.yaml', 0, 8) =]]
docs/content_management/images/images.md@218:```

001⫶services:
002⫶ # ...
003⫶ App\Controller\SvgController:
004⫶ public: true
005⫶ arguments:
006⫶ - '@ibexa.api.service.content'
007⫶ - '@ibexa.field_type.ezbinaryfile.io_service'
008⫶ - '@Ibexa\Core\Helper\TranslationHelper'


code_samples/back_office/images/src/Connector/Dam/Handler/WikimediaCommonsHandler.php

docs/content_management/images/images.md@218:```

001⫶services:
002⫶ # ...
003⫶ App\Controller\SvgController:
004⫶ public: true
005⫶ arguments:
006⫶ - '@ibexa.api.service.content'
007⫶ - '@ibexa.field_type.ezbinaryfile.io_service'
008⫶ - '@Ibexa\Core\Helper\TranslationHelper'


code_samples/back_office/images/src/Connector/Dam/Handler/WikimediaCommonsHandler.php

docs/content_management/images/add_image_asset_from_dam.md@101:```php
docs/content_management/images/add_image_asset_from_dam.md@102:[[= include_file('code_samples/back_office/images/src/Connector/Dam/Handler/WikimediaCommonsHandler.php') =]]
docs/content_management/images/add_image_asset_from_dam.md@103:```

001⫶<?php declare(strict_types=1);
002⫶
003⫶namespace App\Connector\Dam\Handler;
004⫶
005⫶use Ibexa\Contracts\Connector\Dam\Asset;
006⫶use Ibexa\Contracts\Connector\Dam\AssetCollection;
007⫶use Ibexa\Contracts\Connector\Dam\AssetIdentifier;
008⫶use Ibexa\Contracts\Connector\Dam\AssetMetadata;
009⫶use Ibexa\Contracts\Connector\Dam\AssetSource;
010⫶use Ibexa\Contracts\Connector\Dam\AssetUri;
011⫶use Ibexa\Contracts\Connector\Dam\Handler\Handler as HandlerInterface;
012⫶use Ibexa\Contracts\Connector\Dam\Search\AssetSearchResult;
013⫶use Ibexa\Contracts\Connector\Dam\Search\Query;
014⫶
015⫶class WikimediaCommonsHandler implements HandlerInterface
016⫶{
017⫶ public function search(Query $query, int $offset = 0, int $limit = 20): AssetSearchResult
018⫶ {
019⫶ $searchUrl = 'https://commons.wikimedia.org/w/api.php?action=query&list=search&format=json&srnamespace=6'
020⫶ . '&srsearch=' . urlencode($query->getPhrase())
021⫶ . '&sroffset=' . $offset
022⫶ . '&srlimit=' . $limit
023⫶ ;
024⫶
025⫶ $jsonResponse = file_get_contents($searchUrl);
026⫶ if ($jsonResponse === false) {
027⫶ return new AssetSearchResult(0, new AssetCollection([]));
028⫶ }
029⫶
030⫶ $response = json_decode($jsonResponse, true);
031⫶ if (!isset($response['query']['search'])) {
032⫶ return new AssetSearchResult(0, new AssetCollection([]));
033⫶ }
034⫶
035⫶ $assets = [];
036⫶ foreach ($response['query']['search'] as $result) {
037⫶ $identifier = str_replace('File:', '', $result['title']);
038⫶ $asset = $this->fetchAsset($identifier);
039⫶ if ($asset) {
040⫶ $assets[] = $asset;
041⫶ }
042⫶ }
043⫶
044⫶ return new AssetSearchResult(
045⫶ (int) ($response['query']['searchinfo']['totalhits'] ?? 0),
046⫶ new AssetCollection($assets)
047⫶ );
048⫶ }
049⫶
050⫶ public function fetchAsset(string $id): ?Asset
051⫶ {
052⫶ $metadataUrl = 'https://commons.wikimedia.org/w/api.php?action=query&prop=imageinfo&iiprop=extmetadata&format=json'
053⫶ . '&titles=File%3a' . urlencode($id)
054⫶ ;
055⫶
056⫶ $jsonResponse = file_get_contents($metadataUrl);
057⫶ if ($jsonResponse === false) {
058⫶ return null;
059⫶ }
060⫶
061⫶ $response = json_decode($jsonResponse, true);
062⫶ if (!isset($response['query']['pages'])) {
063⫶ return null;
064⫶ }
065⫶
066⫶ $pageData = array_values($response['query']['pages'])[0] ?? null;
067⫶ if (!isset($pageData['imageinfo'][0]['extmetadata'])) {
068⫶ return null;
069⫶ }
070⫶
071⫶ $imageInfo = $pageData['imageinfo'][0]['extmetadata'];
072⫶
073⫶ return new Asset(
074⫶ new AssetIdentifier($id),
075⫶ new AssetSource('commons'),
076⫶ new AssetUri('https://commons.wikimedia.org/w/index.php?title=Special:Redirect/file/' . urlencode($id)),
077⫶ new AssetMetadata([
078⫶ 'page_url' => "https://commons.wikimedia.org/wiki/File:$id",
079⫶ 'author' => $imageInfo['Artist']['value'] ?? null,
080⫶ 'license' => $imageInfo['LicenseShortName']['value'] ?? null,
081⫶ 'license_url' => $imageInfo['LicenseUrl']['value'] ?? null,
082⫶ ])
083⫶ );
084⫶ }
085⫶}


code_samples/back_office/images/src/Connector/Dam/Transformation/WikimediaCommonsTransformationFactory.php


code_samples/back_office/images/src/Connector/Dam/Transformation/WikimediaCommonsTransformationFactory.php

docs/content_management/images/add_image_asset_from_dam.md@118:```php
docs/content_management/images/add_image_asset_from_dam.md@119:[[= include_file('code_samples/back_office/images/src/Connector/Dam/Transformation/WikimediaCommonsTransformationFactory.php') =]]
docs/content_management/images/add_image_asset_from_dam.md@120:```

001⫶<?php declare(strict_types=1);
002⫶
003⫶namespace App\Connector\Dam\Transformation;
004⫶
005⫶use Ibexa\Contracts\Connector\Dam\Variation\Transformation;
006⫶use Ibexa\Contracts\Connector\Dam\Variation\TransformationFactory as TransformationFactoryInterface;
007⫶
008⫶class WikimediaCommonsTransformationFactory implements TransformationFactoryInterface
009⫶{
010⫶ public function build(?string $transformationName = null, array $transformationParameters = []): ?Transformation
011⫶ {
012⫶ $transformations = $this->buildAll();
013⫶ return $transformations[$transformationName] ?? null;
014⫶ }
015⫶
016⫶ public function buildAll(): array
017⫶ {
018⫶ return [
019⫶ 'reference' => new Transformation('reference', []),
020⫶ 'tiny' => new Transformation('tiny', ['width' => '30']),
021⫶ 'small' => new Transformation('small', ['width' => '100']),
022⫶ 'medium' => new Transformation('medium', ['width' => '200']),
023⫶ 'large' => new Transformation('large', ['width' => '300']),
024⫶ ];
025⫶ }
026⫶}


code_samples/back_office/images/templates/themes/standard/commons_asset_view.html.twig


code_samples/back_office/images/templates/themes/standard/commons_asset_view.html.twig

docs/content_management/images/add_image_asset_from_dam.md@153:```html+twig
docs/content_management/images/add_image_asset_from_dam.md@154:[[= include_file('code_samples/back_office/images/templates/themes/standard/commons_asset_view.html.twig') =]]
docs/content_management/images/add_image_asset_from_dam.md@155:```

001⫶{% extends '@ibexadesign/ui/field_type/image_asset_view.html.twig' %}
002⫶
003⫶{% block asset_preview %}
004⫶ {{ parent() }}
005⫶ <div>
006⫶ <a href="{{ asset.assetMetadata.page_url }}">Image</a>
007⫶ {% if asset.assetMetadata.author %} by {{ asset.assetMetadata.author }}{% endif %}
008⫶ {% if asset.assetMetadata.license and asset.assetMetadata.license_url %}
009⫶ under <a href="{{ asset.assetMetadata.license_url }}">{{ asset.assetMetadata.license }}</a>
010⫶ {% endif %}.
011⫶ </div>
012⫶{% endblock %}

Download colorized diff

@dabrt dabrt requested a review from vidarl March 11, 2025 14:21
@dabrt
Copy link
Contributor Author

dabrt commented Mar 11, 2025

@adriendupuis I think I won't be able to fix php code without your help. PHP Stan signals that in the handler, the fetchAsset() method must not return null, same for the transformation, build() must return a transformation object but not null.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants