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. Add terms.', [ ':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; }