I'm looking for a solution to change the site name in a .theme file in Drupal 8. I'm using the Group module and want to display a different site name when the current user navigate inside each group. How can I achieve this ?
-
Do you mean you want to change the site_name variable for an existing template? Which template?– Clive ♦Jul 12, 2016 at 8:44
-
I'm using the group module and when I'm in a specific group, I want to change the site name. For exemple on front page I have the default site name, on group 1 page, I would have another site name.– SnabowJul 12, 2016 at 8:46
-
What do you mean by "site name" though? The page title? h1? Something else?– Clive ♦Jul 12, 2016 at 8:52
-
1General site name, you can change it here "admin/config/system/site-information" in drupal administration– SnabowJul 12, 2016 at 8:59
2 Answers
In a *.theme file this would be difficult to find all places where the site name may end up. This is much easier to do it in settings.php right at the start:
settings.php:
if ($_SERVER['REQUEST_URI'] == '/abc/def') {
$config['system.site']['name'] = 'abc-def';
}
-
Ugh, this isnt really ideal in settings.php for Nodes related to Groups. How can this be done in a way that the
[site:name]
token is altered to swap it out with the Group name early enough for metatag module to update the Window Title (ie<title>
tag) on nodes related to the Group so they display[node:title] | [site:name]
and the site name is swapped for the Group label. Feb 22, 2019 at 12:17
You can override the site title based on the group name by implementing a Config Factory Override class inside a custom module, and passing a '@current_route_match' argument and a few other arguments noted below to help get the information you need out of the entity represented at the current route.
In my case, I needed to limit the site name change to a specific group bundle type called division
that has a specific field value. The code below is currently working for me inside a custom module called: mysite_group
. There are two helper methods that contain the logic for finding the group entity and deciding whether or not to change the site name. The logic should work both on the group page itself, as well as on any other entity or node that is related to the group.
Note: the site we built is leveraging entity_reference fields to maintain the mapping between nodes->groups, if this is not the case for your site, you can take the example below and modify the logic contained in the getSiteNameFromEntityReference()
method and customize it to your needs.
# in mysite_group.services.yml
services:
mysite_group.group_site_name_config_override:
class: \Drupal\mysite_group\GroupSiteNameConfigOverride
arguments: ['@current_route_match', '@entity_type.manager', '@entity_field.manager']
tags:
- {name: config.factory.override, priority: 5}
<?php
// in mysite_group/src/GroupSiteNameConfigOverride.php
namespace Drupal\mysite_group;
use Drupal\Core\Cache\CacheableMetadata;
use Drupal\Core\Config\ConfigFactoryOverrideInterface;
use Drupal\Core\Config\StorageInterface;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Entity\EntityFieldManagerInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Routing\RouteMatchInterface;
use Drupal\field\Entity\FieldConfig;
/**
* Override the site name config variable on groups and nodes that relate to
* groups.
*/
class GroupSiteNameConfigOverride implements ConfigFactoryOverrideInterface {
/**
* {@inheritdoc}
*/
public function __construct(RouteMatchInterface $route_match, EntityTypeManagerInterface $entity_type_manager,EntityFieldManagerInterface $entity_field_manager) {
$this->routeMatch = $route_match;
$this->entityTypeManager = $entity_type_manager;
$this->entityFieldManager = $entity_field_manager;
}
/**
* {@inheritdoc}
*/
public function loadOverrides($names) {
$overrides = [];
if (!in_array('system.site', $names)) {
return $overrides;
}
$site_name = NULL;
if ($entity = $this->getViewedEntity()) {
if ($entity->getEntityTypeId() == 'group') {
$site_name = $this->getSiteNameFromGroup($entity);
}
else {
$site_name = $this->getSiteNameFromEntityReference($entity);
}
}
if ($site_name) {
$overrides['system.site'] = ['name' => $site_name];
}
return $overrides;
}
/**
* {@inheritdoc}
*/
public function getCacheSuffix() {
return 'GroupSiteNameConfigOverride';
}
/**
* {@inheritdoc}
*/
public function getCacheableMetadata($name) {
return new CacheableMetadata();
}
/**
* {@inheritdoc}
*/
public function createConfigObject($name, $collection = StorageInterface::DEFAULT_COLLECTION) {
return NULL;
}
/**
* Helper method loads the viewed entity from the current route.
*
* Adapted from https://www.drupal.org/node/2309797#comment-12752478
*
* @return an entity object, when it exists; otherwise null.
*/
protected function getViewedEntity() {
foreach ($this->routeMatch->getParameters() as $param) {
if ($param instanceof EntityInterface) {
$page_entity = $param;
break;
}
}
if (!isset($page_entity)) {
// Some routes don't properly define entity parameters.
// Thus, try to load them by its raw Id, if given.
$types = $this->entityTypeManager->getDefinitions();
foreach ($this->routeMatch->getParameters()->keys() as $param_key) {
if (!isset($types[$param_key])) {
continue;
}
if ($param = $this->routeMatch->getParameter($param_key)) {
if (is_string($param) || is_numeric($param)) {
try {
$page_entity = $this->entityTypeManager->getStorage($param_key)->load($param);
}
catch (\Exception $e) {
}
}
break;
}
}
}
if (!isset($page_entity) || !$page_entity->access('view')) {
$page_entity = FALSE;
return NULL;
}
return $page_entity;
}
/**
* Helper method determines the site name based on the specified group
* entity.
*
* @return (string) site name value based on the specified group; null if the group
*/
protected function getSiteNameFromGroup(EntityInterface $group) {
$site_name = NULL;
// In our application only groups in the 'division' bundle that have a
// 'library' specified in their field_division_type should provide an
// alternate site name.
if ($group->bundle() == 'division' && $group->field_division_type->getString() == 'library') {
$site_name = $group->label();
}
return $site_name;
}
/**
* Helper method loads the site name from an entity reference field.
*
* @return (string) site name value based on the first group found in the
* entity reference field on the specified entity.
*/
protected function getSiteNameFromEntityReference(EntityInterface $entity) {
$site_name = NULL;
$bundle = $entity->bundle();
$type = $entity->getEntityTypeId();
$valid_group_type = 'division';
// Gather a list of all entity reference fields.
$map = $this->entityFieldManager->getFieldMapByFieldType('entity_reference');
// We only care about entity reference fields on the current entity.
$reference_field_ids = [];
if (!empty($map[$type])) {
foreach ($map[$type] as $name => $data) {
if (!empty($data['bundles'][$bundle])) {
// TODO: Improve logic to determine which reference fields may be
// used to determine the site name, for improved performance. The
// order in which we process reference fields is currently
// arbitrary, based on the order returned by
// EntityFieldManager::getFieldMapByFieldType()
$reference_field_ids[] = "$type.$bundle.$name";
}
}
}
// Determine if any of the reference fields on the current entity point
// to a group.
foreach (FieldConfig::loadMultiple($reference_field_ids) as $field_config) {
$field_name = $field_config->getName();
$target_type = $field_config->getSetting('target_type');
if (!empty($target_type)) {
$handler_settings = $field_config->getSetting('handler_settings');
if (isset($handler_settings['target_bundles'][$valid_group_type])) {
if ($referenced_entities = $entity->{$field_name}->referencedEntities()) {
// If multiple entities are referenced, the first one with a
// custom site name takes precedence.
foreach($referenced_entities as $referenced_entity) {
if ($site_name = $this->getSiteNameFromGroup($referenced_entity)) {
break 2;
}
}
}
}
}
}
return $site_name;
}
}