Skip to content

Conversation

@mnocon
Copy link
Contributor

@mnocon mnocon commented Dec 3, 2025

Target: 5.0 only

@github-actions
Copy link

github-actions bot commented Dec 3, 2025

@github-actions
Copy link

github-actions bot commented Dec 4, 2025

code_samples/ change report

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

code_samples/back_office/dashboard/src/Command/DashboardCommand.php


code_samples/back_office/dashboard/src/Command/DashboardCommand.php

docs/administration/dashboard/php_api_dashboard_service.md@28:``` php hl_lines="63"
docs/administration/dashboard/php_api_dashboard_service.md@28:``` php hl_lines="61"
docs/administration/dashboard/php_api_dashboard_service.md@29:[[= include_file('code_samples/back_office/dashboard/src/Command/DashboardCommand.php') =]]
docs/administration/dashboard/php_api_dashboard_service.md@30:```

001⫶<?php declare(strict_types=1);
002⫶
003⫶namespace App\Command;
004⫶
005⫶use Ibexa\Contracts\Core\Repository\ContentService;
006⫶use Ibexa\Contracts\Core\Repository\LocationService;
007⫶use Ibexa\Contracts\Core\Repository\PermissionResolver;
008⫶use Ibexa\Contracts\Core\Repository\Repository;
009⫶use Ibexa\Contracts\Core\Repository\UserService;
010⫶use Ibexa\Contracts\Dashboard\DashboardServiceInterface;
011⫶use Symfony\Component\Console\Attribute\AsCommand;
012⫶use Symfony\Component\Console\Command\Command;
013⫶use Symfony\Component\Console\Input\InputArgument;
014⫶use Symfony\Component\Console\Input\InputInterface;
015⫶use Symfony\Component\Console\Output\OutputInterface;
016⫶
017⫶#[AsCommand(
018⫶ name: 'doc:dashboard',
019⫶ description: 'Set a custom dashboard to user group.'
020⫶)]
021⫶class DashboardCommand extends Command
022⫶{
023⫶ private readonly Locationservice $locationService;
024⫶
025⫶ private readonly ContentService $contentService;
026⫶
027⫶ private readonly UserService $userService;
028⫶
029⫶ private readonly PermissionResolver $permissionResolver;
030⫶
031⫶ public function __construct(
032⫶ private readonly DashboardServiceInterface $dashboardService,
033⫶ Repository $repository
034⫶ ) {
035⫶ $this->locationService = $repository->getLocationService();
036⫶ $this->contentService = $repository->getContentService();
037⫶ $this->userService = $repository->getUserService();
038⫶ $this->permissionResolver = $repository->getPermissionResolver();
039⫶
040⫶ parent::__construct();
041⫶ }
042⫶
043⫶ public function configure(): void
044⫶ {
045⫶ $this
046⫶ ->addArgument('dashboard', InputArgument::REQUIRED, 'Location ID of the dashboard model')
047⫶ ->addArgument('group', InputArgument::REQUIRED | InputArgument::IS_ARRAY, 'User Group Content ID(s)');
048⫶ }
049⫶
050⫶ protected function execute(InputInterface $input, OutputInterface $output): int
051⫶ {
052⫶ $dashboardModelLocationId = (int)$input->getArgument('dashboard');
docs/administration/dashboard/php_api_dashboard_service.md@29:[[= include_file('code_samples/back_office/dashboard/src/Command/DashboardCommand.php') =]]
docs/administration/dashboard/php_api_dashboard_service.md@30:```

001⫶<?php declare(strict_types=1);
002⫶
003⫶namespace App\Command;
004⫶
005⫶use Ibexa\Contracts\Core\Repository\ContentService;
006⫶use Ibexa\Contracts\Core\Repository\LocationService;
007⫶use Ibexa\Contracts\Core\Repository\PermissionResolver;
008⫶use Ibexa\Contracts\Core\Repository\Repository;
009⫶use Ibexa\Contracts\Core\Repository\UserService;
010⫶use Ibexa\Contracts\Dashboard\DashboardServiceInterface;
011⫶use Symfony\Component\Console\Attribute\AsCommand;
012⫶use Symfony\Component\Console\Command\Command;
013⫶use Symfony\Component\Console\Input\InputArgument;
014⫶use Symfony\Component\Console\Input\InputInterface;
015⫶use Symfony\Component\Console\Output\OutputInterface;
016⫶
017⫶#[AsCommand(
018⫶ name: 'doc:dashboard',
019⫶ description: 'Set a custom dashboard to user group.'
020⫶)]
021⫶class DashboardCommand extends Command
022⫶{
023⫶ private readonly Locationservice $locationService;
024⫶
025⫶ private readonly ContentService $contentService;
026⫶
027⫶ private readonly UserService $userService;
028⫶
029⫶ private readonly PermissionResolver $permissionResolver;
030⫶
031⫶ public function __construct(
032⫶ private readonly DashboardServiceInterface $dashboardService,
033⫶ Repository $repository
034⫶ ) {
035⫶ $this->locationService = $repository->getLocationService();
036⫶ $this->contentService = $repository->getContentService();
037⫶ $this->userService = $repository->getUserService();
038⫶ $this->permissionResolver = $repository->getPermissionResolver();
039⫶
040⫶ parent::__construct();
041⫶ }
042⫶
043⫶ public function configure(): void
044⫶ {
045⫶ $this
046⫶ ->addArgument('dashboard', InputArgument::REQUIRED, 'Location ID of the dashboard model')
047⫶ ->addArgument('group', InputArgument::REQUIRED | InputArgument::IS_ARRAY, 'User Group Content ID(s)');
048⫶ }
049⫶
050⫶ protected function execute(InputInterface $input, OutputInterface $output): int
051⫶ {
052⫶ $dashboardModelLocationId = (int)$input->getArgument('dashboard');
053⫶        $userGroupLocationIdList = array_map('intval', $input->getArgument('group'));
053⫶        $userGroupLocationIdList = array_map(intval(...), $input->getArgument('group'));
054⫶
055⫶ foreach ($userGroupLocationIdList as $userGroupLocationId) {
056⫶ try {
057⫶ $admin = $this->userService->loadUserByLogin('admin');
058⫶ $this->permissionResolver->setCurrentUserReference($admin);
059⫶ foreach ($this->userService->loadUsersOfUserGroup($this->userService->loadUserGroup($userGroupLocationId)) as $user) {
060⫶ $this->permissionResolver->setCurrentUserReference($user);
054⫶
055⫶ foreach ($userGroupLocationIdList as $userGroupLocationId) {
056⫶ try {
057⫶ $admin = $this->userService->loadUserByLogin('admin');
058⫶ $this->permissionResolver->setCurrentUserReference($admin);
059⫶ foreach ($this->userService->loadUsersOfUserGroup($this->userService->loadUserGroup($userGroupLocationId)) as $user) {
060⫶ $this->permissionResolver->setCurrentUserReference($user);
061⫶                    $dashboardDraft = $this->dashboardService->createCustomDashboardDraft($this->locationService->loadLocation($dashboardModelLocationId));
061❇️                    $dashboardDraft = $this->dashboardService->createCustomDashboardDraft($this->locationService->loadLocation($dashboardModelLocationId));
062⫶                    $this->contentService->publishVersion($dashboardDraft->getVersionInfo());
062⫶                    $this->contentService->publishVersion($dashboardDraft->getVersionInfo());
063❇️                }
063⫶                }
064⫶            } catch (\Throwable $throwable) {
065⫶ dump($throwable);
066⫶ }
067⫶ }
068⫶
069⫶ return self::SUCCESS;
070⫶ }
071⫶}


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

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

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⫶ /** @param array<string, scalar> $transformationParameters */
011⫶ public function build(?string $transformationName = null, array $transformationParameters = []): Transformation
012⫶ {
013⫶ if (null === $transformationName) {
064⫶            } catch (\Throwable $throwable) {
065⫶ dump($throwable);
066⫶ }
067⫶ }
068⫶
069⫶ return self::SUCCESS;
070⫶ }
071⫶}


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

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

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⫶ /** @param array<string, scalar> $transformationParameters */
011⫶ public function build(?string $transformationName = null, array $transformationParameters = []): Transformation
012⫶ {
013⫶ if (null === $transformationName) {
014⫶            return new Transformation(null, array_map('strval', $transformationParameters));
014⫶            return new Transformation(null, array_map(strval(...), $transformationParameters));
015⫶        }
016⫶
017⫶ $transformations = $this->buildAll();
018⫶
019⫶ if (array_key_exists($transformationName, $transformations)) {
020⫶ return $transformations[$transformationName];
021⫶ }
022⫶
023⫶ throw new \InvalidArgumentException(sprintf('Unknown transformation "%s".', $transformationName));
024⫶ }
025⫶
026⫶ public function buildAll(): array
027⫶ {
028⫶ return [
029⫶ 'reference' => new Transformation('reference', []),
030⫶ 'tiny' => new Transformation('tiny', ['width' => '30']),
031⫶ 'small' => new Transformation('small', ['width' => '100']),
032⫶ 'medium' => new Transformation('medium', ['width' => '200']),
033⫶ 'large' => new Transformation('large', ['width' => '300']),
034⫶ ];
035⫶ }
036⫶}


code_samples/multisite/siteaccess/Configuration.php

015⫶        }
016⫶
017⫶ $transformations = $this->buildAll();
018⫶
019⫶ if (array_key_exists($transformationName, $transformations)) {
020⫶ return $transformations[$transformationName];
021⫶ }
022⫶
023⫶ throw new \InvalidArgumentException(sprintf('Unknown transformation "%s".', $transformationName));
024⫶ }
025⫶
026⫶ public function buildAll(): array
027⫶ {
028⫶ return [
029⫶ 'reference' => new Transformation('reference', []),
030⫶ 'tiny' => new Transformation('tiny', ['width' => '30']),
031⫶ 'small' => new Transformation('small', ['width' => '100']),
032⫶ 'medium' => new Transformation('medium', ['width' => '200']),
033⫶ 'large' => new Transformation('large', ['width' => '300']),
034⫶ ];
035⫶ }
036⫶}


code_samples/multisite/siteaccess/Configuration.php

docs/multisite/siteaccess/siteaccess_aware_configuration.md@38:``` php hl_lines="16"
docs/multisite/siteaccess/siteaccess_aware_configuration.md@38:``` php hl_lines="19"
docs/multisite/siteaccess/siteaccess_aware_configuration.md@39:[[= include_file('code_samples/multisite/siteaccess/Configuration.php') =]]
docs/multisite/siteaccess/siteaccess_aware_configuration.md@40:```

001⫶<?php declare(strict_types=1);
002⫶
003⫶namespace Acme\ExampleBundle\DependencyInjection;
004⫶
005⫶use Ibexa\Bundle\Core\DependencyInjection\Configuration\SiteAccessAware\Configuration as SiteAccessConfiguration;
006⫶use Symfony\Component\Config\Definition\Builder\TreeBuilder;
007⫶
008⫶class Configuration extends SiteAccessConfiguration
009⫶{
docs/multisite/siteaccess/siteaccess_aware_configuration.md@39:[[= include_file('code_samples/multisite/siteaccess/Configuration.php') =]]
docs/multisite/siteaccess/siteaccess_aware_configuration.md@40:```

001⫶<?php declare(strict_types=1);
002⫶
003⫶namespace Acme\ExampleBundle\DependencyInjection;
004⫶
005⫶use Ibexa\Bundle\Core\DependencyInjection\Configuration\SiteAccessAware\Configuration as SiteAccessConfiguration;
006⫶use Symfony\Component\Config\Definition\Builder\TreeBuilder;
007⫶
008⫶class Configuration extends SiteAccessConfiguration
009⫶{
010⫶    public function getConfigTreeBuilder(): TreeBuilder
011⫶ {
012⫶ $treeBuilder = new TreeBuilder('acme_example');
013⫶ $rootNode = $treeBuilder->getRootNode();
014⫶
015⫶ // $systemNode is the root of SiteAccess-aware settings.
016❇️ $systemNode = $this->generateScopeBaseNode($rootNode);
017⫶ $systemNode
018⫶ ->scalarNode('name')->isRequired()->end()
019⫶ ->arrayNode('custom_setting')
020⫶ ->children()
021⫶ ->scalarNode('string')->end()
022⫶ ->integerNode('number')->end()
023⫶ ->booleanNode('enabled')->end()
024⫶ ->end()
025⫶ ->end();
026⫶
027⫶ return $treeBuilder;
028⫶ }
029⫶}
010⫶    /**
011⫶ * @phpstan-return \Symfony\Component\Config\Definition\Builder\TreeBuilder<'array'> The tree builder
012⫶ */
013⫶ public function getConfigTreeBuilder(): TreeBuilder
014⫶ {
015⫶ $treeBuilder = new TreeBuilder('acme_example');
016⫶ $rootNode = $treeBuilder->getRootNode();
017⫶
018⫶ // $systemNode is the root of SiteAccess-aware settings.
019❇️ $systemNode = $this->generateScopeBaseNode($rootNode);
020⫶ $systemNode
021⫶ ->scalarNode('name')->isRequired()->end()
022⫶ ->arrayNode('custom_setting')
023⫶ ->children()
024⫶ ->scalarNode('string')->end()
025⫶ ->integerNode('number')->end()
026⫶ ->booleanNode('enabled')->end()
027⫶ ->end()
028⫶ ->end();
029⫶
030⫶ return $treeBuilder;
031⫶ }
032⫶}


code_samples/pim/Symbol/Format/Checksum/LuhnChecksum.php

docs/pim/attributes/symbol_attribute_type.md@68:``` php
docs/pim/attributes/symbol_attribute_type.md@69:[[= include_file('code_samples/pim/Symbol/Format/Checksum/LuhnChecksum.php') =]]
docs/pim/attributes/symbol_attribute_type.md@70:```

001⫶<?php
002⫶
003⫶declare(strict_types=1);
004⫶
005⫶namespace App\PIM\Symbol\Format\Checksum;
006⫶
007⫶use Ibexa\Contracts\ProductCatalog\Values\AttributeDefinitionInterface;
008⫶use Ibexa\Contracts\ProductCatalogSymbolAttribute\Value\ChecksumInterface;
009⫶
010⫶final class LuhnChecksum implements ChecksumInterface
011⫶{
012⫶ public function validate(AttributeDefinitionInterface $attributeDefinition, string $value): bool
013⫶ {
014⫶ $digits = $this->getDigits($value);
015⫶
016⫶ $count = count($digits);
017⫶ $total = 0;
018⫶ for ($i = $count - 2; $i >= 0; $i -= 2) {
019⫶ $digit = $digits[$i];
020⫶ if ($i % 2 === 0) {
021⫶ $digit *= 2;
022⫶ }
023⫶
024⫶ $total += $digit > 9 ? $digit - 9 : $digit;
025⫶ }
026⫶
027⫶ $checksum = $digits[$count - 1];
028⫶
029⫶ return $total + $checksum === 0;
030⫶ }
031⫶
032⫶ /**
033⫶ * Returns an array of digits from the given value (skipping any formatting characters).
034⫶ *
035⫶ * @return int[]
036⫶ */
037⫶ private function getDigits(string $value): array
038⫶ {
039⫶ $chars = array_filter(
040⫶ str_split($value),
041⫶ static fn (string $char): bool => $char !== '-'
042⫶ );
043⫶


code_samples/pim/Symbol/Format/Checksum/LuhnChecksum.php

docs/pim/attributes/symbol_attribute_type.md@68:``` php
docs/pim/attributes/symbol_attribute_type.md@69:[[= include_file('code_samples/pim/Symbol/Format/Checksum/LuhnChecksum.php') =]]
docs/pim/attributes/symbol_attribute_type.md@70:```

001⫶<?php
002⫶
003⫶declare(strict_types=1);
004⫶
005⫶namespace App\PIM\Symbol\Format\Checksum;
006⫶
007⫶use Ibexa\Contracts\ProductCatalog\Values\AttributeDefinitionInterface;
008⫶use Ibexa\Contracts\ProductCatalogSymbolAttribute\Value\ChecksumInterface;
009⫶
010⫶final class LuhnChecksum implements ChecksumInterface
011⫶{
012⫶ public function validate(AttributeDefinitionInterface $attributeDefinition, string $value): bool
013⫶ {
014⫶ $digits = $this->getDigits($value);
015⫶
016⫶ $count = count($digits);
017⫶ $total = 0;
018⫶ for ($i = $count - 2; $i >= 0; $i -= 2) {
019⫶ $digit = $digits[$i];
020⫶ if ($i % 2 === 0) {
021⫶ $digit *= 2;
022⫶ }
023⫶
024⫶ $total += $digit > 9 ? $digit - 9 : $digit;
025⫶ }
026⫶
027⫶ $checksum = $digits[$count - 1];
028⫶
029⫶ return $total + $checksum === 0;
030⫶ }
031⫶
032⫶ /**
033⫶ * Returns an array of digits from the given value (skipping any formatting characters).
034⫶ *
035⫶ * @return int[]
036⫶ */
037⫶ private function getDigits(string $value): array
038⫶ {
039⫶ $chars = array_filter(
040⫶ str_split($value),
041⫶ static fn (string $char): bool => $char !== '-'
042⫶ );
043⫶
044⫶        return array_map('intval', array_values($chars));
044⫶        return array_map(intval(...), array_values($chars));
045⫶    }
046⫶}

045⫶    }
046⫶}

Download colorized diff

@mnocon mnocon requested a review from a team December 4, 2025 09:05
@ibexa-workflow-automation-1 ibexa-workflow-automation-1 bot requested review from adriendupuis, dabrt and julitafalcondusza and removed request for a team December 4, 2025 09:05
Copy link
Contributor

@adriendupuis adriendupuis left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ooh, nice https://www.php.net/manual/en/functions.first_class_callable_syntax.php

Good catch for the php_api_dashboard_service highlight issue

@mnocon mnocon merged commit 03da4fd into 5.0 Dec 4, 2025
11 checks passed
@mnocon mnocon deleted the make-ci-green branch December 4, 2025 09:50
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