-
-
Save pmichelazzo/744aca841bc503e4e4d2f3d8baa26ccd to your computer and use it in GitHub Desktop.
Example Dynamic node route in drupal 8.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
name: Example | |
type: module | |
description: Provides a homepage route based on a publish schedule date range field. | |
package: Example | |
core: 8.x | |
dependencies: | |
- node |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
example.home: | |
path: '/home' | |
defaults: | |
_controller: '\Drupal\node\Controller\NodeViewController::view' | |
_title_callback: '\Drupal\node\Controller\NodeViewController::title' | |
requirements: | |
_entity_access: 'node.view' | |
options: | |
_route_enhancers: 'route_enhancer.example.homepage' |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
services: | |
route_enhancer.example.homepage: | |
class: Drupal\example\Routing\Enhancer\HomepageEnhancer | |
arguments: ['@entity.query', '@entity_type.manager'] | |
tags: | |
- { name: route_enhancer } |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/** | |
* @file `tests/src/Kernel/ExampleHomepageResolverTest.php` | |
* | |
* Provides kernel tests for the HomepageEnhancer. | |
*/ | |
namespace Drupal\Tests\example\Kernel; | |
use Drupal\Core\Datetime\DrupalDateTime; | |
use Drupal\datetime_range\Plugin\Field\FieldType\DateRangeItem; | |
use Drupal\field\Entity\FieldConfig; | |
use Drupal\field\Entity\FieldStorageConfig; | |
use Drupal\node\Entity\Node; | |
use Drupal\simpletest\ContentTypeCreationTrait; | |
use Drupal\simpletest\UserCreationTrait; | |
use Drupal\Tests\field\Kernel\FieldKernelTestBase; | |
use Symfony\Component\HttpFoundation\Request; | |
/** | |
* Tests homepage resolution. | |
* | |
* @group example | |
* @coversDefaultClass \Drupal\example\Routing\Enhancer\HomepageEnhancer | |
*/ | |
class ExampleHomepageResolverTest extends FieldKernelTestBase { | |
use UserCreationTrait; | |
use ContentTypeCreationTrait; | |
/** | |
* A field storage to use in this test class. | |
* | |
* @var \Drupal\field\Entity\FieldStorageConfig | |
*/ | |
protected $fieldStorage; | |
/** | |
* The field used in this test class. | |
* | |
* @var \Drupal\field\Entity\FieldConfig | |
*/ | |
protected $field; | |
/** | |
* {@inheritdoc} | |
*/ | |
public static $modules = [ | |
'node', | |
'datetime', | |
'datetime_range', | |
'example', | |
]; | |
/** | |
* {@inheritdoc} | |
*/ | |
protected function setUp() { | |
parent::setUp(); | |
$this->installEntitySchema('node'); | |
$this->installSchema('node', 'node_access'); | |
$this->installConfig('node'); | |
// Create a node type. | |
$this->createContentType(array( | |
'type' => 'homepage', | |
'name' => 'Homepage', | |
'display_submitted' => FALSE, | |
)); | |
// Add a datetime range field. | |
$this->fieldStorage = FieldStorageConfig::create([ | |
'field_name' => 'field_schedule', | |
'entity_type' => 'node', | |
'type' => 'daterange', | |
'settings' => ['datetime_type' => DateRangeItem::DATETIME_TYPE_DATE], | |
]); | |
$this->fieldStorage->save(); | |
$this->field = FieldConfig::create([ | |
'field_storage' => $this->fieldStorage, | |
'bundle' => 'homepage', | |
'required' => TRUE, | |
]); | |
$this->field->save(); | |
} | |
/** | |
* Tests the homepage resolves according to the date. | |
*/ | |
public function testHomepageResolver() { | |
$this->fieldStorage->setSetting('datetime_type', DateRangeItem::DATETIME_TYPE_DATE); | |
$field_name = $this->fieldStorage->getName(); | |
$start_date = new DrupalDateTime('-3 Days'); | |
$end_date = new DrupalDateTime('-2 Days'); | |
// Create an expired homepage node. | |
$homepage_expired = Node::create([ | |
'title' => $this->randomMachineName(), | |
'type' => 'homepage', | |
$field_name => [ | |
'value' => $start_date->format(DATETIME_DATE_STORAGE_FORMAT), | |
'end_value' => $end_date->format(DATETIME_DATE_STORAGE_FORMAT), | |
], | |
]); | |
$homepage_expired->save(); | |
$start_date = new DrupalDateTime('-15 Days'); | |
$end_date = new DrupalDateTime('+15 Days'); | |
// Create a valid homepage node. | |
$homepage_current = Node::create([ | |
'title' => $this->randomMachineName(), | |
'type' => 'homepage', | |
$field_name => [ | |
'value' => $start_date->format(DATETIME_DATE_STORAGE_FORMAT), | |
'end_value' => $end_date->format(DATETIME_DATE_STORAGE_FORMAT), | |
], | |
]); | |
$homepage_current->save(); | |
$authenticated_user = $this->createUser(['access content']); | |
\Drupal::service('account_switcher')->switchTo($authenticated_user); | |
$request = Request::create('/home'); | |
$kernel = \Drupal::getContainer()->get('http_kernel'); | |
$response = $kernel->handle($request); | |
// Make sure access content is enough to see the homepage node. | |
self::assertSame(200, $response->getStatusCode()); | |
// Make sure the current homepage is the one that resolves. | |
self::assertSame($homepage_current->id(), $request->attributes->get('node')->id(), 'The homepage is resolved'); | |
// Used for text assertions. | |
$this->setRawContent($response->getContent()); | |
// Make sure the correct title is rendered. | |
$this->assertText($homepage_current->getTitle()); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/** | |
* @file `src/Routing/Enhancer/HomepageEnhancer.php` | |
* | |
* The HomepageEnhancer class is responsible for supplying the current homepage | |
* node that should be displayed dependent on the schedule. | |
* | |
* This module assumes the `homepage` content type with the `field_schedule` | |
* daterange field has been created. | |
*/ | |
namespace Drupal\example\Routing\Enhancer; | |
use Drupal\Core\Datetime\DrupalDateTime; | |
use Drupal\Core\Entity\EntityTypeManagerInterface; | |
use Drupal\Core\Entity\Query\QueryFactory; | |
use Drupal\Core\Routing\Enhancer\RouteEnhancerInterface; | |
use Symfony\Cmf\Component\Routing\RouteObjectInterface; | |
use Symfony\Component\HttpFoundation\Request; | |
use Symfony\Component\Routing\Route; | |
class HomepageEnhancer implements RouteEnhancerInterface { | |
/** | |
* The query factory. | |
* | |
* @var \Drupal\Core\Entity\Query\QueryFactoryInterface | |
*/ | |
protected $entity_query; | |
/** | |
* The entity type manager. | |
* | |
* @var \Drupal\Core\Entity\EntityTypeManagerInterface | |
*/ | |
protected $entity_type_manager; | |
/** | |
* Constructs an HomepageEnhancer instance. | |
* | |
* @param \Drupal\Core\Entity\Query\QueryFactory $entity_query | |
* The entity resolver manager. | |
* @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager | |
* The entity type manager. | |
*/ | |
public function __construct(QueryFactory $entity_query, EntityTypeManagerInterface $entity_type_manager) { | |
$this->entity_query = $entity_query; | |
$this->entity_type_manager = $entity_type_manager; | |
} | |
/** | |
* {@inheritdoc} | |
*/ | |
public function enhance(array $defaults, Request $request) { | |
if (empty($defaults['node'])) { | |
// Use a datetime object to get the current time. | |
$now = new DrupalDateTime('now'); | |
$sql_time = $now->format(DATETIME_DATE_STORAGE_FORMAT); | |
// Get the latest published homepage. | |
$homepage_result = $this->entity_query->get('node') | |
->condition('type', 'homepage') | |
->condition('field_schedule', $sql_time, '<=') | |
->condition('field_schedule.end_value', $sql_time, '>=') | |
->condition('status', 1) | |
->sort('field_schedule', 'DESC') | |
->range(0,1) | |
->execute(); | |
$nid = reset($homepage_result); | |
if (!empty($nid)) { | |
// Get the Symfony route object. | |
$route = $defaults[RouteObjectInterface::ROUTE_OBJECT]; | |
// If we don't set the default nid route match won't work meaning that access checks will fail and node context won't be available. | |
$route->setDefault('node', $nid); | |
// This is the enhancement part, setting the node object. | |
$defaults['node'] = $this->entity_type_manager->getStorage('node')->load($nid); | |
} | |
} | |
return $defaults; | |
} | |
/** | |
* {@inheritdoc} | |
*/ | |
public function applies(Route $route) { | |
// Only applies to the homepage route. | |
return TRUE; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment