From 1c658eb908cce59c019d43e6fcc32d826075c90b Mon Sep 17 00:00:00 2001 From: aritz Date: Wed, 27 May 2026 09:12:48 +0200 Subject: [PATCH] ADD module related articles --- .../block_articles_related/config.yaml | 44 +++++++++++++++ .../block_articles_related/edit.html.twig | 37 ++++++++++++ .../block_articles_related/form.html.twig | 23 ++++++++ .../block_articles_related/render.html.twig | 33 +++++++++++ .../translations/sfs_cms_modules.en.yaml | 24 ++++++++ .../translations/sfs_cms_modules.es.yaml | 24 ++++++++ config/services/services.yaml | 4 ++ src/Form/Type/BlogArticleTagType.php | 33 +++++++++++ src/Twig/Extension/BlogArticleExtension.php | 56 +++++++++++++++++++ 9 files changed, 278 insertions(+) create mode 100644 cms/modules/block_articles_related/config.yaml create mode 100644 cms/modules/block_articles_related/edit.html.twig create mode 100644 cms/modules/block_articles_related/form.html.twig create mode 100644 cms/modules/block_articles_related/render.html.twig create mode 100644 cms/modules/block_articles_related/translations/sfs_cms_modules.en.yaml create mode 100644 cms/modules/block_articles_related/translations/sfs_cms_modules.es.yaml create mode 100644 src/Form/Type/BlogArticleTagType.php create mode 100644 src/Twig/Extension/BlogArticleExtension.php diff --git a/cms/modules/block_articles_related/config.yaml b/cms/modules/block_articles_related/config.yaml new file mode 100644 index 0000000..32cb191 --- /dev/null +++ b/cms/modules/block_articles_related/config.yaml @@ -0,0 +1,44 @@ +module: + group: blog + revision: 1 + compatible_contents: ['page'] + edit_template: '@module/block_articles_related/edit.html.twig' + form_template: '@module/block_articles_related/form.html.twig' + render_template: '@module/block_articles_related/render.html.twig' + module_options: + form_fields: + id: + type: 'id' + + class: + type: 'class' + + title: + type: 'text' + type_options: + required: false + + tag: + type: 'Softspring\CmsBlogPlugin\Form\Type\BlogArticleTagType' + type_options: + required: true + + limit: + type: 'integer' + type_options: + required: false + empty_data: 3 + default_value: 3 + attr: + min: 1 + + order: + type: 'choice' + type_options: + required: false + default_value: 'published_at_desc' + choices: + 'block_articles_related.form.order.values.published_at_desc': 'published_at_desc' + 'block_articles_related.form.order.values.published_at_asc': 'published_at_asc' + 'block_articles_related.form.order.values.name_asc': 'name_asc' + 'block_articles_related.form.order.values.name_desc': 'name_desc' diff --git a/cms/modules/block_articles_related/edit.html.twig b/cms/modules/block_articles_related/edit.html.twig new file mode 100644 index 0000000..277c1cf --- /dev/null +++ b/cms/modules/block_articles_related/edit.html.twig @@ -0,0 +1,37 @@ +{% trans_default_domain 'sfs_cms_modules' %} +{% import '@SfsCms/macros/modules_edit.html.twig' as module %} +{% set articles = sfs_cms_related_blog_articles(form.tag.vars.data|default(''), form.vars.content|default(null), form.limit.vars.data|default(3), form.order.vars.data|default('published_at_desc')) %} + +
+ {{ form.title.vars.data|default('block_articles_related.render.title'|trans) }} + {% if form.tag.vars.data|default %} +
{{ form.tag.vars.data }}
+ {% endif %} + {% if form.order.vars.data|default %} +
{{ ('block_articles_related.form.order.values.' ~ form.order.vars.data)|trans({}, 'sfs_cms_modules') }}
+ {% endif %} + + {% if articles is not empty %} + + {% elseif form.tag.vars.data|default %} +
{{ 'block_articles_related.edit.no_results'|trans }}
+ {% endif %} +
diff --git a/cms/modules/block_articles_related/form.html.twig b/cms/modules/block_articles_related/form.html.twig new file mode 100644 index 0000000..d855b71 --- /dev/null +++ b/cms/modules/block_articles_related/form.html.twig @@ -0,0 +1,23 @@ +{{ sfs_cms_admin_module_accordion_block_start(form, accordion, 'attributes') }} +
+ {{ form_row(form.id) }} +
+
+ {{ form_row(form.class) }} +
+{{ sfs_cms_admin_module_accordion_block_end() }} + +{{ sfs_cms_admin_module_accordion_block_start(form, accordion, 'content', true) }} +
+ {{ form_row(form.title) }} +
+
+ {{ form_row(form.tag) }} +
+
+ {{ form_row(form.limit) }} +
+
+ {{ form_row(form.order) }} +
+{{ sfs_cms_admin_module_accordion_block_end() }} diff --git a/cms/modules/block_articles_related/render.html.twig b/cms/modules/block_articles_related/render.html.twig new file mode 100644 index 0000000..d36f2e5 --- /dev/null +++ b/cms/modules/block_articles_related/render.html.twig @@ -0,0 +1,33 @@ +{% trans_default_domain "sfs_cms_modules" %} +{% import "@SfsCms/macros/modules_render.html.twig" as module %} + +{% set articles = sfs_cms_related_blog_articles(tag|default(""), content, limit|default(3), order|default("published_at_desc")) %} + +{% if articles is not empty %} +
+

{{ title|default("block_articles_related.render.title"|trans({}, "sfs_cms_modules")) }}

+ + +
+{% endif %} diff --git a/cms/modules/block_articles_related/translations/sfs_cms_modules.en.yaml b/cms/modules/block_articles_related/translations/sfs_cms_modules.en.yaml new file mode 100644 index 0000000..dc68dc6 --- /dev/null +++ b/cms/modules/block_articles_related/translations/sfs_cms_modules.en.yaml @@ -0,0 +1,24 @@ +block_articles_related: + label: "Related articles" + prototype_button: "Related articles" + prototype_button_icon: '' + form: + _group: + attributes: "Attributes" + content: "Content" + id.label: "Id" + class.label: "Classes" + title.label: "Title" + tag.label: "Tag" + tag.placeholder: "Select a tag" + limit.label: "Number of articles" + order.label: "Order" + order.values: + published_at_desc: "Newest first" + published_at_asc: "Oldest first" + name_asc: "Name A-Z" + name_desc: "Name Z-A" + render: + title: "Related articles" + edit: + no_results: "There are no published articles for this tag." diff --git a/cms/modules/block_articles_related/translations/sfs_cms_modules.es.yaml b/cms/modules/block_articles_related/translations/sfs_cms_modules.es.yaml new file mode 100644 index 0000000..ba0e870 --- /dev/null +++ b/cms/modules/block_articles_related/translations/sfs_cms_modules.es.yaml @@ -0,0 +1,24 @@ +block_articles_related: + label: "Artículos relacionados" + prototype_button: "Artículos relacionados" + prototype_button_icon: '' + form: + _group: + attributes: "Atributos" + content: "Contenido" + id.label: "Id" + class.label: "Clases" + title.label: "Título" + tag.label: "Etiqueta" + tag.placeholder: "Selecciona una etiqueta" + limit.label: "Número de artículos" + order.label: "Orden" + order.values: + published_at_desc: "Más recientes primero" + published_at_asc: "Más antiguos primero" + name_asc: "Nombre A-Z" + name_desc: "Nombre Z-A" + render: + title: "Artículos relacionados" + edit: + no_results: "No hay artículos publicados para esta etiqueta." diff --git a/config/services/services.yaml b/config/services/services.yaml index a8ece70..aa764bc 100644 --- a/config/services/services.yaml +++ b/config/services/services.yaml @@ -16,6 +16,10 @@ services: resource: '../../src/Form/*' tags: ['form.type'] + Softspring\CmsBlogPlugin\Twig\Extension\: + resource: '../../src/Twig/Extension/*' + tags: ['twig.extension'] + Softspring\CmsBlogPlugin\Form\Admin\Article\ArticleCreateForm: arguments: $translatableContext: '@Softspring\CmsBundle\Translator\TranslatableContext' diff --git a/src/Form/Type/BlogArticleTagType.php b/src/Form/Type/BlogArticleTagType.php new file mode 100644 index 0000000..e40ebbb --- /dev/null +++ b/src/Form/Type/BlogArticleTagType.php @@ -0,0 +1,33 @@ +articleTagManager->getExistingTags(); + $choices = array_combine($tags, $tags) ?: []; + + $resolver->setDefaults([ + 'required' => false, + 'placeholder' => 'block_articles_related.form.tag.placeholder', + 'choices' => $choices, + 'choice_translation_domain' => false, + ]); + } +} diff --git a/src/Twig/Extension/BlogArticleExtension.php b/src/Twig/Extension/BlogArticleExtension.php new file mode 100644 index 0000000..3ff9640 --- /dev/null +++ b/src/Twig/Extension/BlogArticleExtension.php @@ -0,0 +1,56 @@ +getRelatedBlogArticles(...)), + ]; + } + + public function getRelatedBlogArticles(string $tag, mixed $content = null, int $limit = 3, string $order = 'published_at_desc'): array + { + $tag = trim($tag); + $locale = $this->requestStack->getCurrentRequest()?->getLocale() ?: 'en'; + + if ('' === $tag) { + return []; + } + + $repo = $this->contentManager->getRepository('article'); + $qb = $repo->createQueryBuilder('a'); + + $qb->andWhere('a.publishedVersion IS NOT NULL'); + $qb->andWhere('a.publishedAt <= :publishedAt')->setParameter('publishedAt', time()); + $qb->andWhere('a.locales LIKE :locale')->setParameter('locale', '%"'.$locale.'"%'); + $qb->andWhere('a.tags LIKE :tag')->setParameter('tag', '%"'.$tag.'"%'); + + if ($content instanceof ArticleContent && null !== $content->getId()) { + $qb->andWhere('a.id != :current')->setParameter('current', $content->getId()); + } + + match ($order) { + 'published_at_asc' => $qb->addOrderBy('a.publishedAt', 'ASC'), + 'name_asc' => $qb->addOrderBy('a.name', 'ASC'), + 'name_desc' => $qb->addOrderBy('a.name', 'DESC'), + default => $qb->addOrderBy('a.publishedAt', 'DESC'), + }; + + $qb->setMaxResults(max(1, $limit)); + + return $qb->getQuery()->getResult(); + } +}