Files
structural_pages/structural_pages.install
Quintino A. G. Souza 276fd028f2 Add field_redirect_page to site_sections terms and fix root page hierarchy
- Add field_redirect_page to site_sections taxonomy terms, with a custom
  EntityReferenceSelection plugin that filters content_page nodes by section
- Redirect taxonomy term canonical URLs to the configured node (301)
- Fix root page detection in MenuBlock and views to also match nodes whose
  field_parent_page points to a taxonomy_term (not only empty parent)
- Move root taxonomy-term option to the top of the parent-page dropdown
- Add breadcrumb workaround for Gavias notech theme separator rendering
- Add imecc_menu_helper submodule
- Translate config labels and default terms from English to Portuguese

Co-Authored-By: Henrique Bauer <henrique@webcontent.com.br>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-05 07:52:49 -03:00

362 lines
11 KiB
Plaintext

<?php
/**
* @file
* Install, update and uninstall functions for the Structural Pages module.
*/
declare(strict_types=1);
use Drupal\taxonomy\Entity\Term;
/**
* Implements hook_install().
*/
function structural_pages_install(): void {
// Create default terms for the configured vocabulary.
_structural_pages_create_default_terms();
// Display success message.
\Drupal::messenger()->addStatus(t('Structural Pages module installed successfully. Configure Pathauto patterns at /admin/config/search/path/patterns'));
}
/**
* Creates default terms for the configured site section vocabulary.
*/
function _structural_pages_create_default_terms(): void {
$vocabulary = _structural_pages_get_vocabulary();
// Check if terms already exist (avoid duplication on reinstall).
$existing = \Drupal::entityQuery('taxonomy_term')
->accessCheck(FALSE)
->condition('vid', $vocabulary)
->count()
->execute();
if ($existing > 0) {
return;
}
// Structure: name => children.
$terms_structure = [
'Notícias' => [],
'Eventos' => [],
'Pessoas' => [],
'Institucional' => [
'Sobre',
'Comunicação',
'Informações e Serviços',
'Equipe',
'Gestão',
'Inclusão e Pertencimento',
],
'Graduação' => [
'Estatística',
'Matemática',
'Matemática Aplicada',
'Licenciatura em Matemática',
],
'Pós-Graduação' => [
'Programa de Estatística',
'Programa de Matemática',
'Programa de Matemática Aplicada',
],
'Pesquisa' => [],
'Extensão' => [],
'Administração' => [],
'Departamentos' => [
'Departamento de Estatística',
'Departamento de Matemática',
'Departamento de Matemática Aplicada',
],
'Biblioteca' => [],
'Informática' => [],
];
$created_terms = [];
$weight = 0;
foreach ($terms_structure as $parent_name => $children) {
// Create parent term.
$parent_term = Term::create([
'vid' => $vocabulary,
'name' => $parent_name,
'weight' => $weight++,
]);
$parent_term->save();
$created_terms[] = $parent_term;
// Create child terms.
$child_weight = 0;
foreach ($children as $child_name) {
$child_term = Term::create([
'vid' => $vocabulary,
'name' => $child_name,
'parent' => $parent_term->id(),
'weight' => $child_weight++,
]);
$child_term->save();
$created_terms[] = $child_term;
}
}
// Add content translations if available.
_structural_pages_add_term_translations($created_terms);
}
/**
* Adds content translations to taxonomy terms.
*
* @param \Drupal\taxonomy\Entity\Term[] $terms
* The terms to translate.
*/
function _structural_pages_add_term_translations(array $terms): void {
if (!\Drupal::moduleHandler()->moduleExists('content_translation')) {
return;
}
$translations = _structural_pages_term_translations();
$language_manager = \Drupal::languageManager();
foreach ($translations as $langcode => $name_map) {
if (!$language_manager->getLanguage($langcode)) {
continue;
}
foreach ($terms as $term) {
$name = $term->getName();
if (!isset($name_map[$name])) {
continue;
}
$translated_name = $name_map[$name];
if ($term->hasTranslation($langcode)) {
// Update existing translation if name doesn't match.
$translation = $term->getTranslation($langcode);
if ($translation->getName() !== $translated_name) {
$translation->setName($translated_name);
$translation->save();
}
}
else {
$term->addTranslation($langcode, ['name' => $translated_name]);
$term->save();
}
}
}
}
/**
* Returns term name translations keyed by langcode.
*
* @return array
* Nested array: langcode => [english_name => translated_name].
*/
function _structural_pages_term_translations(): array {
return [
'pt-br' => [
'News' => 'Notícias',
'Events' => 'Eventos',
'People' => 'Pessoas',
'Institutional' => 'Institucional',
'About' => 'Sobre',
'Communication' => 'Comunicação',
'Information and Services' => 'Informações e Serviços',
'Team' => 'Equipe',
'Management' => 'Gestão',
'Inclusion and Belonging' => 'Inclusão e Pertencimento',
'Undergraduate' => 'Graduação',
'Statistics' => 'Estatística',
'Mathematics' => 'Matemática',
'Applied Mathematics' => 'Matemática Aplicada',
'Mathematics Teaching' => 'Licenciatura em Matemática',
'Graduate' => 'Pós-Graduação',
'Statistics Program' => 'Programa de Estatística',
'Mathematics Program' => 'Programa de Matemática',
'Applied Mathematics Program' => 'Programa de Matemática Aplicada',
'Research' => 'Pesquisa',
'Extension' => 'Extensão',
'Administration' => 'Administração',
'Departments' => 'Departamentos',
'Statistics Department' => 'Departamento de Estatística',
'Mathematics Department' => 'Departamento de Matemática',
'Applied Mathematics Department' => 'Departamento de Matemática Aplicada',
'Library' => 'Biblioteca',
'IT Services' => 'Informática',
],
];
}
/**
* Implements hook_uninstall().
*/
function structural_pages_uninstall(): void {
$entity_type_manager = \Drupal::entityTypeManager();
// Remove nodes from module's content types.
foreach (['section_page', 'content_page'] as $bundle) {
$nids = \Drupal::entityQuery('node')
->accessCheck(FALSE)
->condition('type', $bundle)
->execute();
if ($nids) {
$nodes = $entity_type_manager->getStorage('node')->loadMultiple($nids);
$entity_type_manager->getStorage('node')->delete($nodes);
\Drupal::messenger()->addWarning(t('Deleted @count @bundle nodes.', [
'@count' => count($nids),
'@bundle' => $bundle,
]));
}
}
// Remove terms from the configured vocabulary.
$vocabulary = _structural_pages_get_vocabulary();
$tids = \Drupal::entityQuery('taxonomy_term')
->accessCheck(FALSE)
->condition('vid', $vocabulary)
->execute();
if ($tids) {
$terms = $entity_type_manager->getStorage('taxonomy_term')->loadMultiple($tids);
$entity_type_manager->getStorage('taxonomy_term')->delete($terms);
}
// Remove configurations in correct order (dependencies first).
$configs_to_delete = [
// Views.
'views.view.child_pages',
// Pathauto patterns.
'pathauto.pattern.section_page',
'pathauto.pattern.content_page',
'pathauto.pattern.' . $vocabulary . '_term',
// Entity displays.
'core.entity_form_display.node.section_page.default',
'core.entity_view_display.node.section_page.default',
'core.entity_form_display.node.content_page.default',
'core.entity_view_display.node.content_page.default',
// Field instances.
'field.field.node.section_page.field_site_section',
'field.field.node.section_page.body',
'field.field.node.content_page.field_parent_page',
'field.field.node.content_page.field_site_section',
'field.field.node.content_page.body',
// Field storages (only if not used by other bundles).
'field.storage.node.field_site_section',
'field.storage.node.field_parent_page',
// Node types.
'node.type.section_page',
'node.type.content_page',
// Vocabulary.
'taxonomy.vocabulary.' . $vocabulary,
];
$config_factory = \Drupal::configFactory();
foreach ($configs_to_delete as $config_name) {
$config = $config_factory->getEditable($config_name);
if (!$config->isNew()) {
$config->delete();
}
}
\Drupal::messenger()->addStatus(t('Structural Pages module uninstalled successfully.'));
}
/**
* Update content_page content type name from "Guide Page" to "Content Page".
*/
function structural_pages_update_10001(): void {
$config = \Drupal::configFactory()->getEditable('node.type.content_page');
if (!$config->isNew()) {
$current_name = $config->get('name');
// Update if still using old name.
if ($current_name === 'Guide Page') {
$config->set('name', 'Content Page');
$config->set('description', 'Pages with hierarchical parent-child structure for content organization.');
$config->save();
\Drupal::messenger()->addStatus(t('Updated content_page content type name to "Content Page".'));
}
}
}
/**
* Add content translations to site_sections taxonomy terms (no-op, see 10003).
*/
function structural_pages_update_10002(): void {
}
/**
* Add content translations to site_sections taxonomy terms (no-op, see 10004).
*/
function structural_pages_update_10003(): void {
}
/**
* Fix content translation config and update term translations.
*/
function structural_pages_update_10004(): void {
// Ensure content translation is properly configured for the vocabulary.
_structural_pages_ensure_content_translation();
$vocabulary = _structural_pages_get_vocabulary();
$terms = \Drupal::entityTypeManager()
->getStorage('taxonomy_term')
->loadByProperties(['vid' => $vocabulary]);
if ($terms) {
_structural_pages_add_term_translations($terms);
}
}
/**
* Ensures content translation settings exist for the configured vocabulary.
*/
function _structural_pages_ensure_content_translation(): void {
if (!\Drupal::moduleHandler()->moduleExists('content_translation')) {
return;
}
$vocabulary = _structural_pages_get_vocabulary();
$config = \Drupal\language\Entity\ContentLanguageSettings::loadByEntityTypeBundle('taxonomy_term', $vocabulary);
$config->setDefaultLangcode('site_default');
$config->setLanguageAlterable(TRUE);
$config->setThirdPartySetting('content_translation', 'enabled', TRUE);
$config->save();
}
/**
* Implements hook_requirements().
*/
function structural_pages_requirements(string $phase): array {
$requirements = [];
if ($phase === 'runtime') {
// Check if the configured vocabulary has terms.
$vocabulary = _structural_pages_get_vocabulary();
$term_count = \Drupal::entityQuery('taxonomy_term')
->accessCheck(FALSE)
->condition('vid', $vocabulary)
->count()
->execute();
if ($term_count === 0) {
$requirements['structural_pages_terms'] = [
'title' => t('Structural Pages'),
'value' => t('No terms in @vocabulary vocabulary', ['@vocabulary' => $vocabulary]),
'description' => t('The Structural Pages module requires terms in the site section vocabulary. <a href=":url">Add terms</a>.', [
':url' => '/admin/structure/taxonomy/manage/' . $vocabulary . '/add',
]),
'severity' => REQUIREMENT_WARNING,
];
}
else {
$requirements['structural_pages_terms'] = [
'title' => t('Structural Pages'),
'value' => t('@count terms configured', ['@count' => $term_count]),
'severity' => REQUIREMENT_OK,
];
}
}
return $requirements;
}