Completed
Pull Request — 8.x-3.x (#823)
by
unknown
01:44
created

Route::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 19

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
nc 1
nop 9
dl 0
loc 19
rs 9.6333
c 0
b 0
f 0

How to fix   Many Parameters   

Many Parameters

Methods with many parameters are not only hard to understand, but their parameters also often become inconsistent when you need more, or different data.

There are several approaches to avoid long parameter lists:

1
<?php
2
3
namespace Drupal\graphql_core\Plugin\GraphQL\Fields\Routing;
4
5
use Drupal\Core\Config\ConfigFactoryInterface;
6
use Drupal\Core\Path\PathValidatorInterface;
7
use Drupal\Core\PathProcessor\InboundPathProcessorInterface;
8
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
9
use Drupal\Core\Url;
10
use Drupal\graphql\GraphQL\Cache\CacheableValue;
11
use Drupal\graphql\GraphQL\Execution\ResolveContext;
12
use Drupal\graphql\Plugin\GraphQL\Fields\FieldPluginBase;
13
use Drupal\redirect\RedirectRepository;
14
use GraphQL\Type\Definition\ResolveInfo;
15
use Symfony\Component\DependencyInjection\ContainerInterface;
16
use Symfony\Component\HttpFoundation\Request;
17
18
/**
19
 * Retrieve a route object based on a path.
20
 *
21
 * @GraphQLField(
22
 *   id = "url_route",
23
 *   secure = true,
24
 *   name = "route",
25
 *   description = @Translation("Loads a route by its path."),
26
 *   type = "Url",
27
 *   arguments = {
28
 *     "path" = "String!"
29
 *   }
30
 * )
31
 */
32
class Route extends FieldPluginBase implements ContainerFactoryPluginInterface {
33
34
  /**
35
   * The path validator service.
36
   *
37
   * @var \Drupal\Core\Path\PathValidatorInterface
38
   */
39
  protected $pathValidator;
40
41
  /**
42
   * The language negotiator service.
43
   *
44
   * @var \Drupal\language\LanguageNegotiator
45
   */
46
  protected $languageNegotiator;
47
48
  /**
49
   * The language manager.
50
   *
51
   * @var \Drupal\Core\Language\LanguageManagerInterface
52
   */
53
  protected $languageManager;
54
55
  /**
56
   * @var \Drupal\redirect\RedirectRepository
57
   */
58
  protected $redirectRepository;
59
60
  /**
61
   * @var InboundPathProcessorInterface
62
   */
63
  protected $pathProcessor;
64
65
  /**
66
   * The Redirect config.
67
   *
68
   * @var \Drupal\Core\Config\ImmutableConfig
69
   */
70
  protected $config;
71
72
  /**
73
   * {@inheritdoc}
74
   */
75
  public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
76
    return new static(
77
      $configuration,
78
      $plugin_id,
79
      $plugin_definition,
80
      $container->get('path.validator'),
81
      $container->get('language_negotiator', ContainerInterface::NULL_ON_INVALID_REFERENCE),
82
      $container->get('language_manager'),
83
      $container->get('redirect.repository', ContainerInterface::NULL_ON_INVALID_REFERENCE),
84
      $container->get('path_processor_manager'),
85
      $container->get('config.factory')
86
    );
87
  }
88
89
  /**
90
   * Route constructor.
91
   *
92
   * @param array $configuration
93
   *   The plugin configuration.
94
   * @param string $pluginId
95
   *   The plugin id.
96
   * @param mixed $pluginDefinition
97
   *   The plugin definition.
98
   * @param \Drupal\Core\Path\PathValidatorInterface $pathValidator
99
   *   The path validator service.
100
   * @param \Drupal\language\LanguageNegotiator|null $languageNegotiator
101
   *   The language negotiator.
102
   * @param \Drupal\Core\Language\LanguageManagerInterface $languageManager
103
   *   The language manager.
104
   * @param \Drupal\redirect\RedirectRepository $redirectRepository
105
   *   The redirect repository, if redirect module is active.
106
   * @param \Drupal\Core\PathProcessor\InboundPathProcessorInterface
107
   *   An inbound path processor, to clean paths before redirect lookups.
108
   * @param \Drupal\Core\Config\ConfigFactoryInterface $configFactory
109
   *   The config factory.
110
   */
111
  public function __construct(
112
    array $configuration,
113
    $pluginId,
114
    $pluginDefinition,
115
    PathValidatorInterface $pathValidator,
116
    $languageNegotiator,
117
    $languageManager,
118
    $redirectRepository,
119
    $pathProcessor,
120
    ConfigFactoryInterface $configFactory
121
  ) {
122
    parent::__construct($configuration, $pluginId, $pluginDefinition);
123
    $this->redirectRepository = $redirectRepository;
124
    $this->pathProcessor = $pathProcessor;
125
    $this->pathValidator = $pathValidator;
126
    $this->languageNegotiator = $languageNegotiator;
127
    $this->languageManager = $languageManager;
128
    $this->config = $configFactory->get('redirect.settings');
129
  }
130
131
  /**
132
   * {@inheritdoc}
133
   *
134
   * Execute routing in language context.
135
   *
136
   * Language context has to be inferred from the path prefix, but set before
137
   * `resolveValues` is invoked.
138
   */
139
  public function resolve($value, array $args, ResolveContext $context, ResolveInfo $info) {
140
    // For now we just take the "url" negotiator into account.
141
    if ($this->languageManager->isMultilingual() && $this->languageNegotiator) {
142
      if ($negotiator = $this->languageNegotiator->getNegotiationMethodInstance('language-url')) {
143
        $context->setContext('language', $negotiator->getLangcode(Request::create($args['path'])), $info);
144
      }
145
      else {
146
        $context->setContext('language', $this->languageManager->getDefaultLanguage()->getId(), $info);
147
      }
148
    }
149
150
    return parent::resolve($value, $args, $context, $info);
151
  }
152
153
  /**
154
   * {@inheritdoc}
155
   *
156
   * Route field is always language aware since it sets it's context from
157
   * the prefix.
158
   */
159
  protected function isLanguageAwareField() {
160
    return TRUE;
161
  }
162
163
  /**
164
   * {@inheritdoc}
165
   */
166
  public function resolveValues($value, array $args, ResolveContext $context, ResolveInfo $info) {
167
    if ($this->redirectRepository) {
168
      $currentLanguage = $this->languageManager->getCurrentLanguage()->getId();
169
170
      $processedPath = $this->pathProcessor
171
        ->processInbound($args['path'], Request::create($args['path']));
172
173
      // Create new Request from path to split pathname & query.
174
      /** @var Request $sourceRequest */
175
      $sourceRequest = Request::create($processedPath);
176
177
      // Get pathname from request path without leading /.
178
      /** @var RedirectRepository $redirect_service */
179
      $sourcePath = trim($sourceRequest->getPathInfo(), '/');
180
181
      // Get query from request path.
182
      $sourceQuery = $sourceRequest->query->all();
183
184
      // Get the redirect entity by the path (without query string) and the query string separately.
185
      if ($redirectEntity =
186
        $this->redirectRepository->findMatchingRedirect($sourcePath, $sourceQuery, $currentLanguage)) {
187
        $passthroughQueryString = $this->config->get('passthrough_querystring');
188
189
        // Check whether to retain query parameters.
190
        if ($passthroughQueryString) {
191
          // Get URL from redirect destination.
192
          $redirectUrl = Url::fromUri($redirectEntity->getRedirect()['uri']);
193
194
          // Merge the query string from the current query (requested path) with the query string configured in the
195
          // redirect entity.
196
          $mergedQuery = ($redirectUrl->getOption('query') ?? []) + $sourceQuery;
197
198
          // Delete the query string from the url object since we want to pass that separately later.
199
          $redirectUrl->setOption('query', []);
200
201
          // Replace the original redirect based on the source URL, but add the query object this time and overwrite
202
          // those params with those from the redirect entity.
203
          $redirectEntity->setRedirect($redirectUrl->toString(), $mergedQuery);
204
        }
205
206
        yield $redirectEntity;
207
        return;
208
      }
209
    }
210
211
    if (($url = $this->pathValidator->getUrlIfValidWithoutAccessCheck($args['path'])) && $url->access()) {
212
      yield $url;
213
    }
214
    else {
215
      yield (new CacheableValue(NULL))->addCacheTags(['4xx-response']);
216
    }
217
  }
218
219
}
220