php
RouteSubscriber.php
<?php
namespace Drupal\scp_base\Routing;
use Drupal\Core\Routing\RouteSubscriberBase;
use Symfony\Component\Routing\RouteCollection;
class RouteSubscriber extends RouteSubscriberBase {
/**
* {@inheritdoc}
*/
protected function alterRoutes(RouteCollection $collection) {
// Make sure profile pages are not admin pages, in order to load the right
// translation.
if ($route = $collection->get('profile.user_page.single')) {
$route->setOption('_admin_route', FALSE);
}
}
}
13.11.2025 | Pascal Crott
Prevent the user profile from being displayed in backend theme using RouteSubscriber
RouteSubscriber.php
<?php
namespace Drupal\layout_builder_collapse_categories\Routing;
use Drupal\Core\Routing\RoutingEvents;
use Drupal\Core\Routing\RouteSubscriberBase;
use Symfony\Component\Routing\RouteCollection;
use Drupal\layout_builder_collapse_categories\Controller\ChooseBlockController;
/**
* Override the controller for layout_builder.move_block.
*/
class RouteSubscriber extends RouteSubscriberBase {
/**
* {@inheritdoc}
*/
public static function getSubscribedEvents() {
$events[RoutingEvents::ALTER] = ['onAlterRoutes', -1000];
return $events;
}
/**
* {@inheritdoc}
*/
public function alterRoutes(RouteCollection $collection) {
// Add a decorator for the choose_block conroller
if ($route = $collection->get('layout_builder.choose_block')) {
$defaults = $route->getDefaults();
$route->setOption('original_controller', substr($defaults['_controller'], 0, strpos($defaults['_controller'], '::')));
$defaults['_controller'] = ChooseBlockController::class . '::build';
$route->setDefaults($defaults);
}
}
}
ChooseBlockController.php
<?php
namespace Drupal\layout_builder_collapse_categories\Controller;
use Drupal\Core\Controller\ControllerBase;
use Drupal\Core\Routing\RouteMatchInterface;
use Drupal\layout_builder\SectionStorageInterface;
use Drupal\Core\Controller\ControllerResolverInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
class ChooseBlockController extends ControllerBase {
/**
* The original ChooseBlockController
*
* @var \Drupal\layout_builder\Controller\ChooseBlockController $originalController
*/
protected $originalController;
/**
* @param \Drupal\Core\Controller\ControllerResolverInterface $controller_resolver
*/
public function __construct(ControllerResolverInterface $controller_resolver, RouteMatchInterface $route_match) {
$original_controller_class = $route_match->getRouteObject()->getOption('original_controller');
$this->originalController = $controller_resolver->getControllerFromDefinition($original_controller_class);
}
/**
* {@inheritdoc}
*/
public static function create(ContainerInterface $container) {
return new static(
$container->get('controller_resolver'),
$container->get('current_route_match')
);
}
public function build(SectionStorageInterface $section_storage, $delta, $region) {
$build = $this->originalController->build($section_storage, $delta, $region);
foreach ($build['block_categories'] as &$category) {
if (isset($category['#open'])) {
$category['#open'] = FALSE;
}
}
return $build;
}
}
16.07.2026 | Dominik Wille
Controller decorator
If you want to extend a class with static methods, don't use self:: since it will scope the static method to the extended class.
FooElement.php
// $options = self::getPluginOptions($element)
$options = static::getPluginOptions($element)
10.03.2023 | Fabian Alleblas, Dominik Wille
Replace self with static: Just do it, trust me.
ComponentPluginManager.php
// Check if the component plugin instance was already created.
if (isset($this->componentPluginCacheEntries[$machine_name])) {
return $this->componentPluginCacheEntries[$machine_name];
}
$definitions = $this->getDefinitions();
if (empty($definitions)) {
throw new ComponentNotFoundException('Unable to find any component definition.');
}
$instance = $this->createInstance(
$this->componentNegotiator->negotiate($machine_name, $definitions)
);
// Cache the component plugin instance.
$this->componentPluginCacheEntries[$machine_name] = $instance;
27.01.2023 | Dominik Wille, Peter Gerken, Pascal Crott
How to static cache in symfony services
SampleEntityProvider.php
<?php
namespace Drupal\MY_MODULE;
use Drupal\Core\DependencyInjection\ServiceProviderBase;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Field\FieldStorageDefinitionInterface;
use Psr\Log\LoggerInterface;
/**
* A service that generates a sample entity with populated fields.
*/
class SampleEntityProvider extends ServiceProviderBase {
/**
* The entity type manager.
*
* @var \Drupal\Core\Entity\EntityTypeManagerInterface
*/
protected $entityTypeManager;
/**
* The logger service.
*
* @var \Psr\Log\LoggerInterface
*/
protected $logger;
/**
* Creates a SampleEntityProvider object.
*
* @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
* The entity type manager.
* @param \Psr\Log\LoggerInterface $logger
* A logger instance.
*/
public function __construct(EntityTypeManagerInterface $entity_type_manager, LoggerInterface $logger) {
$this->entityTypeManager = $entity_type_manager;
$this->logger = $logger;
}
/**
* Gets a sample entity with populated fields.
*
* @param string $entity_type_id
* The entity type id the samle entity should have.
* @param string $entity_bundle
* The bundle the sample entity should have.
*
* @return \Drupal\Core\Entity\EntityInterface|void $entity
* The generated sample entity.
*/
public function getSampleEntity(string $entity_type_id, string $entity_bundle) {
try {
$entity_storge = $this->entityTypeManager->getStorage($entity_type_id);
$bundle_key = $entity_storge->getEntityType()->getKey('bundle');
$sample_entity = $entity_storge->create([$bundle_key => $entity_bundle]);
$this->populateFields($sample_entity);
return $sample_entity;
} catch (\Exception $e) {
$this->logger->error($e->getMessage());
}
}
/**
* Populate the fields on a given entity with sample values.
*
* @param \Drupal\Core\Entity\EntityInterface $entity
* The entity to be enriched with sample field values.
*
* @throws \Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException
* @throws \Drupal\Component\Plugin\Exception\PluginNotFoundException
*/
public function populateFields(EntityInterface $entity) {
$properties = [
'entity_type' => $entity->getEntityType()->id(),
'bundle' => $entity->bundle(),
];
$field_config_storage = \Drupal::entityTypeManager()->getStorage('field_config');
/** @var \Drupal\field\FieldConfigInterface[] $instances */
$instances = $field_config_storage->loadByProperties($properties);
foreach ($instances as $instance) {
$field_storage = $instance->getFieldStorageDefinition();
$max = $cardinality = $field_storage->getCardinality();
if ($cardinality == FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED) {
// Just an arbitrary number for 'unlimited'.
$max = rand(1, 3);
}
$field_name = $field_storage->getName();
$entity->$field_name->generateSampleItems($max);
}
}
}
DomainRouteProvider.php
<?php
namespace Drupal\poormans_domain\Routing;
use Drupal\Core\Routing\RouteProvider;
use Symfony\Component\HttpFoundation\Request;
/**
* Custom router.route_provider service to make it domain context sensitive.
*/
class DomainRouteProvider extends RouteProvider {
/**
* {@inheritdoc}
*/
protected function getRouteCollectionCacheId(Request $request) {
// Add domain sensitive cache information to the cid.
$this->addExtraCacheKeyPart('poormans_domain', $request->getHost());
return parent::getRouteCollectionCacheId($request);
}
}
poormans_domain.services.yml
services:
poormans_domain.route_provider:
class: Drupal\poormans_domain\Routing\DomainRouteProvider
decorates: router.route_provider
decoration_priority: 10
arguments: ['@database', '@state', '@path.current', '@cache.data', '@path_processor_manager', '@cache_tags.invalidator', 'router', '@language_manager']
27.01.2023
poormans_domain.services.yml
MetaCspSubscriber.php
/**
* Alter CSP policy for meta.
*/
class MetaCspSubscriber implements EventSubscriberInterface {
/**
* @var \Drupal\meta_atipixel\MetaAtiCode
*/
protected $metaAtiCode;
/**
* {@inheritdoc}
*/
public static function getSubscribedEvents() {
$events[CspEvents::POLICY_ALTER] = ['onCspPolicyAlter'];
return $events;
}
/**
* MetaCspSubscriber constructor.
*
* @param\Drupal\meta_atipixel\MetaAtiCode $meta_ati_code
* The ati code service.
*/
public function __construct(MetaAtiCode $meta_ati_code) {
$this->metaAtiCode = $meta_ati_code;
}
/**
* Add hashed and nonces if we are not on unsafe-inline anyway.
*
* @param \Drupal\csp\Event\PolicyAlterEvent $alterEvent
* The Policy Alter event.
*/
public function onCspPolicyAlter(PolicyAlterEvent $alterEvent) {
$policy = $alterEvent->getPolicy();
$nonce = $this->metaAtiCode->getNonce();
if (!in_array("'unsafe-inline'", $policy->getDirective('script-src'))) {
$additions = [
// scripts in html.html.twig
"'sha256-u9HSg2Pp8ssH/rPdIjXPA2C4w25lvarx61zTFRKUrmM='",
"'sha256-MpSPVM+F08E973/LoTypmKAw/3M85wXWX6kWfoTFytc='",
"'sha256-LP15v8l8fhV/n/S6XgVVfXn7GJIVJ3hoL8UIw4BYxsE='",
// onClicks in page.html.twig
"'sha256-UvdkyVIodw5ho+TLRpWSJlSwRybZxclpp+OSCf7w67I='",
"'sha256-GGza1Y9dREBYst5ReIQ6hgev0+2sE9tMsbcJ29qs4w4='",
"'sha256-O5E6+QtFv/CBsWdAYZvTiTYiHXAA7iTst1rBecCv6dI='",
"'sha256-hIoyxe70kL8INnzt1lpp3M9bfkqfZmnY0SXJrA5LKoA='",
"'sha256-IVlAoFKs/eP8PtbJup9f6kWE26ZguV+Cmqs6+98t3EE='",
"'sha256-JmPJi7h6GEv+mUBBxVrImXEvDVkqcCK/xncob2D/3JA='",
// Ati pixel nonce
"'nonce-$nonce'"
];
$policy->fallbackAwareAppendIfEnabled('script-src', $additions);
}
}
}
10.08.2022 | Dominik Wille
MetaCspSubscriber.php
Easy clean up cron functionality using DB Statements. Should be used with custom tables, which brought their own schema. See: https://mariadb.com/kb/en/date-and-time-units/
example.php
/**
* Implements hook_cron().
*/
function your_module_cron() {
\Drupal::database()
->query("DELETE FROM example_custom_table WHERE created < UNIX_TIMESTAMP(NOW() - INTERVAL 6 MONTH)")
->execute();
}
29.06.2022 | Nikolas Kopp
Cleanup Cron
Related issue: https://www.drupal.org/project/drupal/issues/2408549
SMTPConfigForm.php
/**
* Check if config variable is overridden by the settings.php.
*
* @param string $name
* SMTP settings key.
*
* @return bool
* Boolean.
*/
protected function isOverridden($name) {
$original = $this->configFactory->getEditable('smtp.settings')->get($name);
$current = $this->configFactory->get('smtp.settings')->get($name);
return $original != $current;
}
10.08.2022 | Dominik Wille