Completed
Pull Request — 8.x-3.x (#673)
by Philipp
02:22
created

Route::getPathProcessor()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
nc 1
nop 0
dl 0
loc 3
rs 10
c 0
b 0
f 0
1
<?php
2
3
namespace Drupal\graphql_core\Plugin\GraphQL\Fields\Routing;
4
5
use Drupal\Core\Path\PathValidatorInterface;
6
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
7
use Drupal\graphql\GraphQL\Cache\CacheableValue;
8
use Drupal\graphql\GraphQL\Execution\ResolveContext;
9
use Drupal\graphql\Plugin\GraphQL\Fields\FieldPluginBase;
10
use Drupal\language\LanguageNegotiator;
11
use Drupal\Core\Language\LanguageManagerInterface;
12
use Drupal\redirect\Entity\Redirect;
13
use Drupal\Tests\views_ui\Functional\ReportFieldsTest;
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
   * {@inheritdoc}
57
   */
58
  public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
59
    return new static(
60
      $configuration,
61
      $plugin_id,
62
      $plugin_definition,
63
      $container->get('path.validator'),
64
      $container->has('language_negotiator') ? $container->get('language_negotiator') : NULL,
65
      $container->get('language_manager')
66
    );
67
  }
68
69
  /**
70
   * Route constructor.
71
   *
72
   * @param array $configuration
73
   *   The plugin configuration.
74
   * @param string $pluginId
75
   *   The plugin id.
76
   * @param mixed $pluginDefinition
77
   *   The plugin definition.
78
   * @param \Drupal\Core\Path\PathValidatorInterface $pathValidator
79
   *   The path validator service.
80
   * @param \Drupal\language\LanguageNegotiator|null $languageNegotiator
81
   *   The language negotiator.
82
   * @param \Drupal\Core\Language\LanguageManagerInterface $languageManager
83
   *   The language manager.
84
   */
85
  public function __construct(
86
    array $configuration,
87
    $pluginId,
88
    $pluginDefinition,
89
    PathValidatorInterface $pathValidator,
90
    $languageNegotiator,
91
    $languageManager
92
  ) {
93
    parent::__construct($configuration, $pluginId, $pluginDefinition);
94
    $this->pathValidator = $pathValidator;
95
    $this->languageNegotiator = $languageNegotiator;
96
    $this->languageManager = $languageManager;
97
  }
98
99
  /**
100
   * {@inheritdoc}
101
   *
102
   * Execute routing in language context.
103
   *
104
   * Language context has to be inferred from the path prefix, but set before
105
   * `resolveValues` is invoked.
106
   */
107
  public function resolve($value, array $args, ResolveContext $context, ResolveInfo $info) {
108
    // For now we just take the "url" negotiator into account.
109
    if ($this->languageManager->isMultilingual() && $this->languageNegotiator) {
110
      if ($negotiator = $this->languageNegotiator->getNegotiationMethodInstance('language-url')) {
111
        $context->setContext('language', $negotiator->getLangcode(Request::create($args['path'])), $info);
112
      }
113
      else {
114
        $context->setContext('language', $this->languageManager->getDefaultLanguage()->getId(), $info);
115
      }
116
    }
117
118
    return parent::resolve($value, $args, $context, $info);
119
  }
120
121
  /**
122
   * {@inheritdoc}
123
   *
124
   * Route field is always language aware since it sets it's context from
125
   * the prefix.
126
   */
127
  protected function isLanguageAwareField() {
128
    return TRUE;
129
  }
130
131
  /**
132
   * Get the redirect repository service.
133
   *
134
   * @return \Drupal\redirect\RedirectRepository
135
   */
136
  protected function getRedirectRepository() {
137
    return \Drupal::service('redirect.repository');
138
  }
139
140
  /**
141
   * Get the path processor.
142
   *
143
   * @return \Drupal\Core\PathProcessor\InboundPathProcessorInterface
144
   */
145
  protected function getPathProcessor() {
146
    return \Drupal::service('path_processor_manager');
147
  }
148
149
  /**
150
   * {@inheritdoc}
151
   */
152
  public function resolveValues($value, array $args, ResolveContext $context, ResolveInfo $info) {
153
    if (\Drupal::moduleHandler()->moduleExists('redirect')) {
154
      $redirectRepository = $this->getRedirectRepository();
155
      $currentLanguage = $this->languageManager->getCurrentLanguage()->getId();
156
157
      $processedPath = $this->getPathProcessor()
158
        ->processInbound($args['path'], Request::create($args['path']));
159
160
      if ($redirect = $redirectRepository->findMatchingRedirect($processedPath, [], $currentLanguage)) {
161
        yield $redirect;
162
        return;
163
      }
164
    }
165
166
    if (($url = $this->pathValidator->getUrlIfValidWithoutAccessCheck($args['path'])) && $url->access()) {
167
      yield $url;
168
    }
169
    else {
170
      yield (new CacheableValue(NULL))->addCacheTags(['4xx-response']);
171
    }
172
  }
173
174
}
175