From 9b34772f278a4df399bc24875a6c679c08a657fe Mon Sep 17 00:00:00 2001 From: Albert Skibinski Date: Fri, 13 Jul 2018 08:40:12 +0200 Subject: [PATCH] Various patches --- purl.install | 111 ++++++++++-------- purl.module | 43 ------- purl.services.yml | 13 +- src/Annotation/PurlMethod.php | 2 +- src/ContextHelper.php | 19 +-- src/Controller/ModifiersController.php | 14 +-- src/Event/RequestSubscriber.php | 2 + .../RouteNormalizerRequestSubscriber.php | 92 +++++++++++++++ src/Plugin/Purl/Provider/StaticProvider.php | 2 +- src/PurlServiceProvider.php | 14 ++- src/Routing/PurlRouteProvider.php | 24 ++-- src/StackMiddleware/PageCache.php | 29 +++++ 12 files changed, 236 insertions(+), 129 deletions(-) create mode 100644 src/Event/RouteNormalizerRequestSubscriber.php create mode 100644 src/StackMiddleware/PageCache.php diff --git a/purl.install b/purl.install index 2d4b32c..788ff33 100644 --- a/purl.install +++ b/purl.install @@ -1,58 +1,69 @@ array( - 'provider' => array( - 'type' => 'varchar', - 'length' => 150, - 'not null' => true, - ), - 'method' => array( - 'type' => 'varchar', - 'length' => 255, - 'not null' => true, - ), - 'settings' => array( - 'type' => 'text', - 'not null' => true, - 'mysql_type' => 'mediumtext', - ), - 'rebuild' => array( - 'type' => 'int', - //'size' => 'tinyint', - 'default' => 0, - ), - ), - 'primary key' => array('provider'), - 'description' => 'PURL provider settings', + $schema['purl_providers_settings'] = array( + 'fields' => array( + 'provider' => array( + 'description' => '', + 'type' => 'varchar', + 'length' => 255, + 'not null' => TRUE, + ), + 'method' => array( + 'description' => '', + 'type' => 'varchar', + 'length' => 255, + 'not null' => TRUE, + ), + 'settings' => array( + 'description' => '', + 'type' => 'text', + 'not null' => TRUE, + 'size' => 'medium', + ), + 'rebuild' => array( + 'description' => '', + 'type' => 'int', + 'size' => 'tiny', + 'not null' => TRUE, + 'default' => 0, + ), + ), + 'primary key' => array(array('provider', 191)), + 'description' => 'PURL provider settings', ); - $schema['purl_modifiers'] = array( - 'fields' => array( - 'provider' => array( - 'type' => 'varchar', - 'length' => 150, - 'not null' => true, - ), - 'modifier' => array( - 'type' => 'varchar', - 'length' => 150, - 'not null' => true, - ), - 'value' => array( - 'type' => 'text', - 'not null' => true, - 'mysql_type' => 'mediumtext', - ), - ), - 'primary key' => array('provider', 'modifier'), - 'description' => 'Index of PURL modifiers', - ); + $schema['purl_modifiers'] = array( + 'fields' => array( + 'provider' => array( + 'description' => '', + 'type' => 'varchar', + 'length' => 255, + 'not null' => TRUE, + ), + 'modifier' => array( + 'description' => '', + 'type' => 'varchar', + 'length' => 255, + 'not null' => TRUE, + ), + 'value' => array( + 'description' => '', + 'type' => 'text', + 'not null' => TRUE, + 'mysql_type' => 'mediumtext', + ), + ), + 'primary key' => array(array('provider', 191), array('modifier', 191)), + 'description' => 'Index of PURL modifiers', + ); - return $schema; + return $schema; } diff --git a/purl.module b/purl.module index a44b443..1c7f3c5 100644 --- a/purl.module +++ b/purl.module @@ -8,49 +8,6 @@ use Drupal\purl\Entity\Provider; use Drupal\node\NodeTypeInterface; use Drupal\Core\Form; -function purl_entity_base_field_info(EntityTypeInterface $entity_type) { - - if ($entity_type->id() !== 'menu_link_content') { - return; - } - - $fields = []; - - /* @todo Remove this; we don't need these extra fields anymore */ - - $fields['purl_provider'] = BaseFieldDefinition::create('entity_reference') - ->setLabel(t('PURL provider')) - ->setName('purl_provider') - ->setRevisionable(false) - ->setTranslatable(false) - ->setDescription('PURL provider') - ->setSettings([ - 'target_type' => 'purl_provider', - 'default_value' => null, - ]); - - $fields['purl_modifier'] = BaseFieldDefinition::create('string') - ->setLabel(t('PURL modifier')) - ->setName('purl_modifier') - ->setRevisionable(false) - ->setDescription('PURL modififer') - ->setSettings([ - 'default_value' => null, - 'max_length' => 255, - ]); - - $fields['purl_strip_context'] = BaseFieldDefinition::create('boolean') - ->setLabel(t('PURL strip context')) - ->setName('purl_strip_context') - ->setRevisionable(false) - ->setDescription('PURL strip context') - ->setSettings([ - 'default_value' => false, - ]); - - return $fields; -} - function purl_form_menu_edit_form_alter(&$form, $form_state) { $providers = Provider::loadMultiple(); diff --git a/purl.services.yml b/purl.services.yml index fc5908b..8fbc9d0 100644 --- a/purl.services.yml +++ b/purl.services.yml @@ -17,7 +17,7 @@ services: purl.request_subscriber: class: Drupal\purl\Event\RequestSubscriber - arguments: + arguments: - '@purl.modifier_index' - '@purl.matched_modifiers' tags: @@ -29,11 +29,6 @@ services: tags: - { name: event_subscriber } - purl.provider_storage: - class: Drupal\Core\Entity\EntityStorageInterface - factory: ['@entity.manager', getStorage] - arguments: ['purl_provider'] - cache_context.purl: class: Drupal\purl\Cache\Context\PurlCacheContext tags: @@ -42,14 +37,14 @@ services: purl.rebuild_index: class: Drupal\purl\Event\RebuildIndex - arguments: + arguments: - '@purl.modifier_index' tags: - { name: event_subscriber } purl.outbound_path_processor: class: Drupal\purl\PathProcessor\PurlContextOutboundPathProcessor - arguments: + arguments: - '@purl.matched_modifiers' - '@purl.context_helper' tags: @@ -78,4 +73,4 @@ services: purl.context_helper: class: Drupal\purl\ContextHelper - arguments: ['@purl.provider_storage'] + arguments: ['@entity_type.manager'] diff --git a/src/Annotation/PurlMethod.php b/src/Annotation/PurlMethod.php index 1016341..3394310 100644 --- a/src/Annotation/PurlMethod.php +++ b/src/Annotation/PurlMethod.php @@ -20,7 +20,7 @@ public function __construct($values) } if (!isset($this->definition['stages'])) { - $this->definition['stage'] = [MethodInterface::STAGE_PROCESS_OUTBOUND]; + $this->definition['stages'] = [MethodInterface::STAGE_PROCESS_OUTBOUND]; } } } diff --git a/src/ContextHelper.php b/src/ContextHelper.php index 8d1b2d8..aa182dc 100644 --- a/src/ContextHelper.php +++ b/src/ContextHelper.php @@ -2,7 +2,7 @@ namespace Drupal\purl; -use Drupal\Core\Entity\EntityStorageInterface; +use Drupal\Core\Entity\EntityTypeManager; use Drupal\Core\Render\BubbleableMetadata; use Drupal\purl\Entity\Provider; use Drupal\purl\Plugin\Purl\Method\MethodInterface; @@ -12,13 +12,18 @@ class ContextHelper { /** - * @var EntityStorageInterface + * @var \Drupal\Core\Entity\EntityTypeManager */ - protected $storage; + protected $entityTypeManager; - public function __construct(EntityStorageInterface $storage) + /** + * ContextHelper constructor. + * + * @param \Drupal\Core\Entity\EntityTypeManager $entity_type_manager + */ + public function __construct(EntityTypeManager $entity_type_manager) { - $this->storage = $storage; + $this->entityTypeManager = $entity_type_manager; } /** @@ -105,10 +110,10 @@ public function createContextsFromMap(array $map) return []; } - $providers = $this->storage->loadMultiple(array_keys($map)); + $providers = $this->entityTypeManager->getStorage('purl_provider')->loadMultiple(array_keys($map)); return array_map(function (Provider $provider) use ($map) { return new Context($map[$provider->id()], $provider->getMethodPlugin()); }, $providers); } -} \ No newline at end of file +} diff --git a/src/Controller/ModifiersController.php b/src/Controller/ModifiersController.php index 0386d84..d215e51 100644 --- a/src/Controller/ModifiersController.php +++ b/src/Controller/ModifiersController.php @@ -45,9 +45,6 @@ public function modifiers(Request $request) { $build = array(); - $ids = \Drupal::entityQuery('purl_provider') - ->execute(); - $headers = array('provider', 'modifier', 'value'); $headers = array_map(function ($header) { @@ -56,9 +53,9 @@ public function modifiers(Request $request) $rows = array(); - foreach ($this->modifierIndex->findModifiers() as $modifier) { + foreach ($this->modifierIndex->findAll() as $modifier) { - $provider = $modifier['provider']; + $provider = $modifier->getProvider(); if (!$provider) { continue; @@ -67,14 +64,14 @@ public function modifiers(Request $request) $row = array(); $row[] = array( - 'data' => $provider->getLabel() + 'data' => $provider->getLabel(), ); $row[] = array( 'data' => array( '#type' => 'html_tag', '#tag' => 'code', - '#value' => $modifier['modifier'], + '#value' => $modifier->getModifierKey(), ), ); @@ -82,14 +79,13 @@ public function modifiers(Request $request) 'data' => array( '#type' => 'html_tag', '#tag' => 'code', - '#value' => $this->stringify($modifier['value']), + '#value' => $this->stringify($modifier->getValue()), ), ); $rows[] = $row; } - $build['modifiers'] = array( '#theme' => 'table', '#header' => $headers, diff --git a/src/Event/RequestSubscriber.php b/src/Event/RequestSubscriber.php index 136a1e7..8279f88 100644 --- a/src/Event/RequestSubscriber.php +++ b/src/Event/RequestSubscriber.php @@ -61,6 +61,7 @@ public function onRequest(GetResponseEvent $event, $eventName, EventDispatcherIn { $request = $event->getRequest(); $modifiers = $this->getModifiers(); + $original_uri = $request->getRequestUri(); $matches = array(); @@ -104,6 +105,7 @@ public function onRequest(GetResponseEvent $event, $eventName, EventDispatcherIn } $request->attributes->set('purl.matched_modifiers', $matches); + $request->attributes->set('original_uri', $original_uri); } /** diff --git a/src/Event/RouteNormalizerRequestSubscriber.php b/src/Event/RouteNormalizerRequestSubscriber.php new file mode 100644 index 0000000..8ca5370 --- /dev/null +++ b/src/Event/RouteNormalizerRequestSubscriber.php @@ -0,0 +1,92 @@ +config->get('route_normalizer_enabled') || !$event->isMasterRequest()) { + return; + } + + $request = $event->getRequest(); + if ($request->attributes->get('_disable_route_normalizer')) { + return; + } + + if ($this->redirectChecker->canRedirect($request)) { + // The "" placeholder can be used for all routes except the front + // page because it's not a real route. + $route_name = $this->pathMatcher->isFrontPage() ? '' : ''; + + // Don't pass in the query here using $request->query->all() + // since that can potentially modify the query parameters. + $options = ['absolute' => TRUE]; + $redirect_uri = $this->urlGenerator->generateFromRoute($route_name, [], $options); + + // Strip off query parameters added by the route such as a CSRF token. + if (strpos($redirect_uri, '?') !== FALSE) { + $redirect_uri = strtok($redirect_uri, '?'); + } + + // Append back the request query string from $_SERVER. + $query_string = $request->server->get('QUERY_STRING'); + if ($query_string) { + $redirect_uri .= '?' . $query_string; + } + + // Remove /index.php from redirect uri the hard way. + if (!RequestHelper::isCleanUrl($request)) { + // This needs to be fixed differently. + $redirect_uri = str_replace('/index.php', '', $redirect_uri); + } + + $uri = $request->attributes->has('original_uri') ? $request->attributes->get('original_uri') : $request->getRequestUri(); + $original_uri = $request->getSchemeAndHttpHost() . $uri; + $original_uri = urldecode($original_uri); + $redirect_uri = urldecode($redirect_uri); + if ($redirect_uri != $original_uri) { + $response = new TrustedRedirectResponse($redirect_uri, $this->config->get('default_status_code')); + $response->headers->set('X-Drupal-Route-Normalizer', 1); + $event->setResponse($response); + // Disable page cache for redirects as that results in unpredictable + // behavior, e.g. when a trailing ? without query parameters is + // involved. + // @todo Remove when https://www.drupal.org/node/2761639 is fixed in + // Drupal core. + \Drupal::service('page_cache_kill_switch')->trigger(); + } + } + } + +} diff --git a/src/Plugin/Purl/Provider/StaticProvider.php b/src/Plugin/Purl/Provider/StaticProvider.php index dc60edf..4c541e0 100644 --- a/src/Plugin/Purl/Provider/StaticProvider.php +++ b/src/Plugin/Purl/Provider/StaticProvider.php @@ -12,7 +12,7 @@ */ class StaticProvider extends ProviderAbstract { - public function getModifiers() + public function getModifierData() { return array( 'un' => 1, diff --git a/src/PurlServiceProvider.php b/src/PurlServiceProvider.php index a561cb5..23a431c 100644 --- a/src/PurlServiceProvider.php +++ b/src/PurlServiceProvider.php @@ -13,6 +13,8 @@ use Drupal\Core\DependencyInjection\ServiceProviderBase; use Drupal\purl\Routing\PurlRouteProvider; use Drupal\purl\Utility\PurlAwareUnroutedUrlAssembler; +use Drupal\purl\StackMiddleware\PageCache; +use Drupal\purl\Event\RouteNormalizerRequestSubscriber; use Symfony\Component\DependencyInjection\Reference; class PurlServiceProvider extends ServiceProviderBase @@ -22,6 +24,11 @@ public function alter(ContainerBuilder $container) $urlGeneratorDefinition = $container->getDefinition('url_generator'); $urlGeneratorDefinition->replaceArgument(0, new Reference('purl.url_generator')); + if ($container->hasDefinition('redirect.route_normalizer_request_subscriber')) { + $routeNormalizerDefinition = $container->getDefinition('redirect.route_normalizer_request_subscriber'); + $routeNormalizerDefinition->setClass(RouteNormalizerRequestSubscriber::class); + } + $assemblerDefinition = $container->getDefinition('unrouted_url_assembler'); $assemblerDefinition->setClass(PurlAwareUnroutedUrlAssembler::class); $assemblerDefinition->addArgument(new Reference('purl.context_helper')); @@ -31,5 +38,10 @@ public function alter(ContainerBuilder $container) $routerDefinition->setClass(PurlRouteProvider::class); $routerDefinition->addArgument(new Reference('purl.context_helper')); $routerDefinition->addArgument(new Reference('purl.matched_modifiers')); + + if ($container->hasDefinition('http_middleware.page_cache')) { + $pageCacheDefinition = $container->getDefinition('http_middleware.page_cache'); + $pageCacheDefinition->setClass(PageCache::class); + } } -} \ No newline at end of file +} diff --git a/src/Routing/PurlRouteProvider.php b/src/Routing/PurlRouteProvider.php index e96974b..400a7d5 100644 --- a/src/Routing/PurlRouteProvider.php +++ b/src/Routing/PurlRouteProvider.php @@ -5,6 +5,7 @@ use Drupal\Core\Cache\Cache; use Drupal\Core\Cache\CacheBackendInterface; use Drupal\Core\Cache\CacheTagsInvalidatorInterface; +use Drupal\Core\Language\LanguageManagerInterface; use Drupal\Core\Path\CurrentPathStack; use Drupal\Core\Path\PathValidator; use Drupal\Core\PathProcessor\InboundPathProcessorInterface; @@ -108,7 +109,10 @@ class PurlRouteProvider extends RouteProvider { * @param \Drupal\Core\Cache\CacheTagsInvalidatorInterface $cache_tag_invalidator * The cache tag invalidator. * @param string $table - * (Optional) The table in the database to use for matching. Defaults to 'router' + * (Optional) The table in the database to use for matching. Defaults to + * 'router'. + * @param \Drupal\Core\Language\LanguageManagerInterface $language_manager + * (Optional) The language manager. */ public function __construct( Connection $connection, @@ -117,10 +121,12 @@ public function __construct( CacheBackendInterface $cache_backend, InboundPathProcessorInterface $path_processor, CacheTagsInvalidatorInterface $cache_tag_invalidator, + $table = 'router', + LanguageManagerInterface $language_manager = NULL, ContextHelper $contextHelper, MatchedModifiers $matchedModifiers ) { - parent::__construct($connection, $state, $current_path, $cache_backend, $path_processor, $cache_tag_invalidator); + parent::__construct($connection, $state, $current_path, $cache_backend, $path_processor, $cache_tag_invalidator, $table, $language_manager); $this->contextHelper = $contextHelper; $this->matchedModifiers = $matchedModifiers; } @@ -155,12 +161,14 @@ public function getRouteCollectionForRequest(Request $request) { // Incoming path processors may also set query parameters. $query_parameters = $request->query->all(); $routes = $this->getRoutesByPath(rtrim($path, '/')); - $cache_value = [ - 'path' => $path, - 'query' => $query_parameters, - 'routes' => $routes, - ]; - $this->cache->set($cid, $cache_value, CacheBackendInterface::CACHE_PERMANENT, ['route_match']); + if (!empty($routes->count())) { + $cache_value = [ + 'path' => $path, + 'query' => $query_parameters, + 'routes' => $routes, + ]; + $this->cache->set($cid, $cache_value, CacheBackendInterface::CACHE_PERMANENT, ['route_match']); + } return $routes; } } diff --git a/src/StackMiddleware/PageCache.php b/src/StackMiddleware/PageCache.php new file mode 100644 index 0000000..a682e88 --- /dev/null +++ b/src/StackMiddleware/PageCache.php @@ -0,0 +1,29 @@ +attributes->has('original_uri') ? $request->attributes->get('original_uri') : $request->getRequestUri(); + $cid_parts = [ + $request->getSchemeAndHttpHost() . $uri, + $request->getRequestFormat(), + ]; + return implode(':', $cid_parts); + } + +}