Skip to content
New issue

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

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

Already on GitHub? # 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.

@dabrt dabrt requested a review from adriendupuis March 17, 2025 12:07
# for free to join this conversation on GitHub. Already have an account? # to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants