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

Route::resolveValues()   B

Complexity

Conditions 6
Paths 6

Size

Total Lines 52

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 6
nc 6
nop 4
dl 0
loc 52
rs 8.425
c 0
b 0
f 0

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

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