Adiciona sub-módulo site_users_blog e melhora negociador de tema

Sub-módulo site_users_blog:
- Tipo de conteúdo blog_post (título, corpo, imagem, assuntos)
- Vocabulário blog_tags para categorias
- Listagem em /user/{uid}/blog via Views com filtro contextual por autor
- Padrão Pathauto: user/[node:author:uid]/blog/[node:title]
- hook_node_presave: preenche field_site_section com o autor
- hook_node_access: restringe criação às roles configuradas
- hook_preprocess_structural_pages_menu: injeta item "Blog" quando
  usuário tem posts publicados
- Plugin BlogUserHandler: resolve usuário ancestral para rotas de blog
  (post individual e listagem Views)
- Link "Post de blog" no menu "Adicionar" da conta
- Página de configuração de roles permitidas
- Update 10001: adiciona field_site_section a posts existentes

MicrositeThemeNegotiator:
- Injeta path.current para cobrir rotas sem parâmetro 'user' (ex.: Views)
- Qualquer path /user/{uid}/... recebe o tema do microsite

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-24 07:32:10 -03:00
parent 39de6a7493
commit d72f41de97
24 changed files with 931 additions and 2 deletions

View File

@@ -0,0 +1,235 @@
langcode: pt-br
status: true
dependencies:
config:
- node.type.blog_post
module:
- node
- user
id: user_blog
label: 'Blog do usuário'
module: views
description: 'Lista posts do blog de um usuário, acessível em /user/{uid}/blog.'
tag: ''
base_table: node_field_data
base_field: nid
display:
default:
id: default
display_title: Default
display_plugin: default
position: 0
display_options:
title: Blog
pager:
type: full
options:
items_per_page: 10
offset: 0
id: 0
total_pages: null
tags:
previous: ' Anterior'
next: 'Próximo '
first: '« Primeira'
last: 'Última »'
expose:
items_per_page: false
items_per_page_label: 'Itens por página'
items_per_page_options: '5, 10, 25, 50'
items_per_page_options_all: false
items_per_page_options_all_label: '- Todos -'
offset: false
offset_label: Deslocamento
quantity: 9
style:
type: default
options:
grouping: []
row_class: ''
default_row_class: true
row:
type: 'entity:node'
options:
relationship: none
view_mode: teaser
fields: {}
filters:
status:
id: status
table: node_field_data
field: status
relationship: none
group_type: group
admin_label: ''
entity_type: node
entity_field: status
plugin_id: boolean
operator: '='
value: '1'
group: 1
exposed: false
expose:
operator: ''
is_grouped: false
type:
id: type
table: node_field_data
field: type
relationship: none
group_type: group
admin_label: ''
entity_type: node
entity_field: type
plugin_id: bundle
operator: in
value:
blog_post: blog_post
group: 1
exposed: false
expose:
operator_id: ''
label: ''
description: ''
use_operator: false
operator: ''
operator_limit_selection: false
operator_list: {}
identifier: ''
required: false
remember: false
multiple: false
remember_roles:
authenticated: authenticated
is_grouped: false
group_info:
label: ''
description: ''
identifier: ''
optional: true
widget: select
multiple: false
remember: false
default_group: All
default_group_multiple: {}
group_items: {}
sorts:
created:
id: created
table: node_field_data
field: created
relationship: none
group_type: group
admin_label: ''
entity_type: node
entity_field: created
plugin_id: date
order: DESC
expose:
label: ''
granularity: second
arguments:
uid:
id: uid
table: node_field_data
field: uid
relationship: none
group_type: group
admin_label: Usuário
entity_type: node
entity_field: uid
plugin_id: node_uid
default_action: 'not found'
exception:
value: all
title_enable: false
title: All
title_enable: false
title: ''
default_argument_type: raw
default_argument_options:
index: 1
use_alias: false
summary_options:
base_path: ''
count: true
items_per_page: 25
override: false
summary:
sort_order: asc
number_of_records: 0
format: default_summary
specify_validation: true
validate:
type: 'entity:user'
fail: 'not found'
validate_options:
access: false
operation: view
multiple: '0'
roles: {}
break_phrase: false
not: false
access:
type: perm
options:
perm: 'access content'
cache:
type: tag
options: {}
empty:
area_text_custom:
id: area_text_custom
table: views
field: area_text_custom
relationship: none
group_type: group
admin_label: ''
plugin_id: text_custom
content: 'Nenhum post publicado ainda.'
tokenize: false
empty: true
header: {}
footer: {}
relationships: {}
use_ajax: false
query:
type: views_query
options:
query_comment: ''
disable_sql_rewrite: false
distinct: false
replica: false
query_tags: []
exposed_form:
type: basic
options:
submit_button: Aplicar
reset_button: false
reset_button_label: Resetar
exposed_sorts_label: 'Ordenar por'
expose_sort_order: true
sort_asc_label: Crescente
sort_desc_label: Decrescente
use_more: false
use_more_always: true
use_more_text: mais
display_extenders: {}
rendering_language: '***LANGUAGE_language_interface***'
page_user_blog:
id: page_user_blog
display_title: 'Página do blog'
display_plugin: page
position: 1
display_options:
display_extenders: {}
path: 'user/%/blog'
menu:
type: none
title: ''
description: ''
expanded: false
parent: ''
weight: 0
context: '0'
menu_name: main