diff --git a/src/bundle/DependencyInjection/Configuration/Parser/ContentTypeGroup.php b/src/bundle/DependencyInjection/Configuration/Parser/ContentTypeGroup.php new file mode 100644 index 0000000000..6f9bcd170d --- /dev/null +++ b/src/bundle/DependencyInjection/Configuration/Parser/ContentTypeGroup.php @@ -0,0 +1,61 @@ +arrayNode('content_type_group') + ->useAttributeAsKey('identifier') + ->arrayPrototype() + ->children() + ->scalarNode('thumbnail')->defaultNull()->end() + ->end() + ->end() + ->end(); + } + + /** + * @param array $scopeSettings + */ + public function mapConfig(array &$scopeSettings, $currentScope, ContextualizerInterface $contextualizer): void + { + if (empty($scopeSettings['content_type_group'])) { + return; + } + + foreach ($scopeSettings['content_type_group'] as $identifier => $config) { + $contextualizer->setContextualParameter("content_type_group.$identifier", $currentScope, $config); + } + } +} diff --git a/src/bundle/IbexaAdminUiBundle.php b/src/bundle/IbexaAdminUiBundle.php index 0e0c296591..beff75700c 100644 --- a/src/bundle/IbexaAdminUiBundle.php +++ b/src/bundle/IbexaAdminUiBundle.php @@ -70,6 +70,7 @@ private function getConfigParsers(): array new Parser\ContentTranslateView(), new Parser\AdminUiForms(), new Parser\ContentType(), + new Parser\ContentTypeGroup(), new Parser\SubtreePath(), new Parser\LimitationValueTemplates(), new Parser\Assets(), diff --git a/src/bundle/Resources/config/default_parameters.yaml b/src/bundle/Resources/config/default_parameters.yaml index ce7f1c70d6..18c9d2e6b9 100644 --- a/src/bundle/Resources/config/default_parameters.yaml +++ b/src/bundle/Resources/config/default_parameters.yaml @@ -36,6 +36,15 @@ parameters: ibexa.site_access.config.default.content_type.default-config: thumbnail: '/bundles/ibexaadminui/img/ibexa-icons.svg#file' + ibexa.site_access.config.default.content_type_group.default-config: + thumbnail: '/bundles/ibexaadminui/img/ibexa-icons.svg#file' + ibexa.site_access.config.default.content_type_group.content: + thumbnail: '/bundles/ibexaadminui/img/ibexa-icons.svg#content-type-content' + ibexa.site_access.config.default.content_type_group.users: + thumbnail: '/bundles/ibexaadminui/img/ibexa-icons.svg#user-type' + ibexa.site_access.config.default.content_type_group.media: + thumbnail: '/bundles/ibexaadminui/img/ibexa-icons.svg#media-type' + ibexa.content_view.tabs.default_template: '@@ibexadesign/ui/tab/default.html.twig' ibexa.multifile_upload.location.mappings: [] diff --git a/src/bundle/Resources/config/services.yaml b/src/bundle/Resources/config/services.yaml index 75ca424bcb..f4d9534827 100644 --- a/src/bundle/Resources/config/services.yaml +++ b/src/bundle/Resources/config/services.yaml @@ -138,7 +138,14 @@ services: Ibexa\Bundle\AdminUi\Templating\Twig\UserPreferencesGlobalExtension: lazy: true - Ibexa\AdminUi\UI\Service\ContentTypeIconResolver: ~ + Ibexa\AdminUi\UI\Service\IconResolver: + abstract: true + + Ibexa\AdminUi\UI\Service\ContentTypeIconResolver: + parent: Ibexa\AdminUi\UI\Service\IconResolver + + Ibexa\AdminUi\UI\Service\ContentTypeGroupIconResolver: + parent: Ibexa\AdminUi\UI\Service\IconResolver Ibexa\ContentForms\ConfigResolver\MaxUploadSize: ~ diff --git a/src/bundle/Resources/config/services/ui_config/common.yaml b/src/bundle/Resources/config/services/ui_config/common.yaml index a8b6817f44..12885f3a6d 100644 --- a/src/bundle/Resources/config/services/ui_config/common.yaml +++ b/src/bundle/Resources/config/services/ui_config/common.yaml @@ -100,6 +100,8 @@ services: Ibexa\Bundle\AdminUi\Templating\Twig\ContentTypeIconExtension: ~ + Ibexa\Bundle\AdminUi\Templating\Twig\ContentTypeGroupIconExtension: ~ + Ibexa\Bundle\AdminUi\Templating\Twig\EmbeddedItemEditFormExtension: ~ Ibexa\AdminUi\UI\Config\Provider\UserContentTypes: diff --git a/src/bundle/Resources/views/themes/admin/content_type/content_type_group/list.html.twig b/src/bundle/Resources/views/themes/admin/content_type/content_type_group/list.html.twig index 4b3018ff7d..73d5038185 100644 --- a/src/bundle/Resources/views/themes/admin/content_type/content_type_group/list.html.twig +++ b/src/bundle/Resources/views/themes/admin/content_type/content_type_group/list.html.twig @@ -71,6 +71,16 @@ content: col_raw, raw: true, }]) %} + {% set col_raw %} + + + + {% endset %} + {% set body_row_cols = body_row_cols|merge([{ + has_icon: true, + content: col_raw, + raw: true, + }]) %} {% set col_raw %} {% set view_url = path('ibexa.content_type_group.view', { @@ -118,6 +128,7 @@ headline: custom_results_headline ?? results_headline(pager.getNbResults()), head_cols: [ { has_checkbox: true }, + { has_icon: true }, { content: 'content_type_group.view.list.column.identifier'|trans|desc('Name') }, { content: 'content_type_group.view.list.column.id'|trans|desc('ID') }, { content: 'content_type_group.view.list.column.content_types_count'|trans|desc('Number of content types') }, diff --git a/src/bundle/Templating/Twig/ContentTypeGroupIconExtension.php b/src/bundle/Templating/Twig/ContentTypeGroupIconExtension.php new file mode 100644 index 0000000000..e1da84c73c --- /dev/null +++ b/src/bundle/Templating/Twig/ContentTypeGroupIconExtension.php @@ -0,0 +1,39 @@ +contentTypeGroupIconResolver = $contentTypeGroupIconResolver; + } + + public function getFunctions(): array + { + return [ + new TwigFunction( + 'ibexa_content_type_group_icon', + [$this->contentTypeGroupIconResolver, 'getContentTypeGroupIcon'], + [ + 'is_safe' => ['html'], + ] + ), + ]; + } +} diff --git a/src/bundle/Templating/Twig/ContentTypeIconExtension.php b/src/bundle/Templating/Twig/ContentTypeIconExtension.php index 5dfa944678..a704304b6f 100644 --- a/src/bundle/Templating/Twig/ContentTypeIconExtension.php +++ b/src/bundle/Templating/Twig/ContentTypeIconExtension.php @@ -14,20 +14,13 @@ class ContentTypeIconExtension extends AbstractExtension { - /** @var \Ibexa\AdminUi\UI\Service\ContentTypeIconResolver */ - private $contentTypeIconResolver; + private ContentTypeIconResolver $contentTypeIconResolver; - /** - * @param \Ibexa\AdminUi\UI\Service\ContentTypeIconResolver $contentTypeIconResolver - */ public function __construct(ContentTypeIconResolver $contentTypeIconResolver) { $this->contentTypeIconResolver = $contentTypeIconResolver; } - /** - * {@inheritdoc} - */ public function getFunctions(): array { return [ diff --git a/src/lib/UI/Service/ContentTypeGroupIconResolver.php b/src/lib/UI/Service/ContentTypeGroupIconResolver.php new file mode 100644 index 0000000000..12f451e71a --- /dev/null +++ b/src/lib/UI/Service/ContentTypeGroupIconResolver.php @@ -0,0 +1,33 @@ +.content_type.). If there isn't + * corresponding entry for given content type, then path to default icon will be returned. + */ + public function getContentTypeGroupIcon(string $identifier): string + { + $slugger = new AsciiSlugger(); + $identifier = (string)$slugger->slug($identifier, '_')->lower(); + + return $this->getIcon(self::PARAM_NAME_FORMAT, $identifier); + } +} diff --git a/src/lib/UI/Service/ContentTypeIconResolver.php b/src/lib/UI/Service/ContentTypeIconResolver.php index 1ac1a4f3af..1d452999dc 100644 --- a/src/lib/UI/Service/ContentTypeIconResolver.php +++ b/src/lib/UI/Service/ContentTypeIconResolver.php @@ -8,77 +8,19 @@ namespace Ibexa\AdminUi\UI\Service; -use Ibexa\Contracts\Core\SiteAccess\ConfigResolverInterface; -use Symfony\Component\Asset\Packages; - -final class ContentTypeIconResolver +final class ContentTypeIconResolver extends IconResolver { - private const DEFAULT_IDENTIFIER = 'default-config'; private const PARAM_NAME_FORMAT = 'content_type.%s'; - private const ICON_KEY = 'thumbnail'; - - /** @var \Ibexa\Contracts\Core\SiteAccess\ConfigResolverInterface */ - private $configResolver; - - /** @var \Symfony\Component\Asset\Packages */ - private $packages; - - /** - * @param \Ibexa\Contracts\Core\SiteAccess\ConfigResolverInterface $configResolver - * @param \Symfony\Component\Asset\Packages $packages - */ - public function __construct(ConfigResolverInterface $configResolver, Packages $packages) - { - $this->configResolver = $configResolver; - $this->packages = $packages; - } - /** * Returns path to content type icon. * - * Path is resolved based on configuration (ezpublish.system..content_type.). If there isn't + * Path is resolved based on configuration (ibexa.system..content_type.). If there isn't * corresponding entry for given content type, then path to default icon will be returned. - * - * @throws \Ibexa\AdminUi\Exception\ContentTypeIconNotFoundException */ public function getContentTypeIcon(string $identifier): string { - $icon = $this->resolveIcon($identifier); - - $fragment = null; - if (strpos($icon, '#') !== false) { - [$icon, $fragment] = explode('#', $icon); - } - - return $this->packages->getUrl($icon) . ($fragment ? '#' . $fragment : ''); - } - - /** - * @throws \Ibexa\AdminUi\Exception\ContentTypeIconNotFoundException - */ - private function resolveIcon(string $identifier): string - { - $parameterName = $this->getConfigParameterName($identifier); - $defaultParameterName = $this->getConfigParameterName(self::DEFAULT_IDENTIFIER); - - if ($this->configResolver->hasParameter($parameterName)) { - $config = $this->configResolver->getParameter($parameterName); - } - - if ((empty($config) || empty($config[self::ICON_KEY])) && $this->configResolver->hasParameter($defaultParameterName)) { - $config = $this->configResolver->getParameter($defaultParameterName); - } - - return $config[self::ICON_KEY] ?? ''; - } - - /** - * Return configuration parameter name for given content type identifier. - */ - private function getConfigParameterName(string $identifier): string - { - return sprintf(self::PARAM_NAME_FORMAT, $identifier); + return $this->getIcon(self::PARAM_NAME_FORMAT, $identifier); } } diff --git a/src/lib/UI/Service/IconResolver.php b/src/lib/UI/Service/IconResolver.php new file mode 100644 index 0000000000..e0e9673b45 --- /dev/null +++ b/src/lib/UI/Service/IconResolver.php @@ -0,0 +1,66 @@ +configResolver = $configResolver; + $this->packages = $packages; + } + + protected function getIcon(string $format, string $identifier): string + { + $icon = $this->resolveIcon($format, $identifier); + $fragment = null; + if (strpos($icon, '#') !== false) { + [$icon, $fragment] = explode('#', $icon); + } + + return $this->packages->getUrl($icon) . ($fragment ? '#' . $fragment : ''); + } + + private function resolveIcon(string $format, string $identifier): string + { + $parameterName = $this->getConfigParameterName($format, $identifier); + $defaultParameterName = $this->getConfigParameterName($format, static::DEFAULT_IDENTIFIER); + + if ($this->configResolver->hasParameter($parameterName)) { + $config = $this->configResolver->getParameter($parameterName); + } + + if ( + (empty($config) || empty($config[static::ICON_KEY])) + && $this->configResolver->hasParameter($defaultParameterName) + ) { + $config = $this->configResolver->getParameter($defaultParameterName); + } + + return $config[static::ICON_KEY] ?? ''; + } + + /** + * Returns configuration parameter name for given content type identifier. + */ + private function getConfigParameterName(string $format, string $identifier): string + { + return sprintf($format, $identifier); + } +}