View source
<?php
namespace Drupal\rest\Plugin\views\display;
use Drupal\Core\Cache\CacheableMetadata;
use Drupal\Core\Cache\CacheableResponse;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Render\RenderContext;
use Drupal\Core\Render\RendererInterface;
use Drupal\Core\Routing\RouteProviderInterface;
use Drupal\Core\State\StateInterface;
use Drupal\views\Plugin\views\display\ResponseDisplayPluginInterface;
use Drupal\views\Render\ViewsRenderPipelineMarkup;
use Drupal\views\ViewExecutable;
use Drupal\views\Plugin\views\display\PathPluginBase;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\Routing\Route;
use Symfony\Component\Routing\RouteCollection;
class RestExport extends PathPluginBase implements ResponseDisplayPluginInterface {
protected $usesAJAX = FALSE;
protected $usesPager = FALSE;
protected $usesMore = FALSE;
protected $usesAreas = FALSE;
protected $usesOptions = FALSE;
protected $contentType = 'json';
protected $mimeType = 'application/json';
protected $renderer;
protected $authenticationCollector;
protected $authenticationProviderIds;
protected $formatProviders;
public function __construct(array $configuration, $plugin_id, $plugin_definition, RouteProviderInterface $route_provider, StateInterface $state, RendererInterface $renderer, array $authentication_providers, array $serializer_format_providers) {
parent::__construct($configuration, $plugin_id, $plugin_definition, $route_provider, $state);
$this->renderer = $renderer;
$this->authenticationProviderIds = array_keys($authentication_providers);
$this->formatProviders = $serializer_format_providers;
}
public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
return new static($configuration, $plugin_id, $plugin_definition, $container
->get('router.route_provider'), $container
->get('state'), $container
->get('renderer'), $container
->getParameter('authentication_providers'), $container
->getParameter('serializer.format_providers'));
}
public function initDisplay(ViewExecutable $view, array &$display, array &$options = NULL) {
parent::initDisplay($view, $display, $options);
if (!empty($options['style']['options']['formats']) && !isset($options['style']['options']['formats'][$this
->getContentType()])) {
$default_format = reset($options['style']['options']['formats']);
$this
->setContentType($default_format);
}
$request_content_type = $this->view
->getRequest()
->getRequestFormat();
if ($request_content_type !== 'html') {
$this
->setContentType($request_content_type);
}
$this
->setMimeType($this->view
->getRequest()
->getMimeType($this
->getContentType()));
}
public function getType() {
return 'data';
}
public function usesExposed() {
return TRUE;
}
public function displaysExposed() {
return FALSE;
}
public function setMimeType($mime_type) {
$this->mimeType = $mime_type;
}
public function getMimeType() {
return $this->mimeType;
}
public function setContentType($content_type) {
$this->contentType = $content_type;
}
public function getContentType() {
return $this->contentType;
}
public function getAuthOptions() {
return array_combine($this->authenticationProviderIds, $this->authenticationProviderIds);
}
protected function defineOptions() {
$options = parent::defineOptions();
$options['auth'] = [
'default' => [],
];
$options['style']['contains']['type']['default'] = 'serializer';
$options['row']['contains']['type']['default'] = 'data_entity';
$options['defaults']['default']['style'] = FALSE;
$options['defaults']['default']['row'] = FALSE;
unset($options['exposed_form']);
unset($options['exposed_block']);
unset($options['css_class']);
return $options;
}
public function optionsSummary(&$categories, &$options) {
parent::optionsSummary($categories, $options);
$auth = $this
->getOption('auth') ? implode(', ', $this
->getOption('auth')) : $this
->t('No authentication is set');
unset($categories['page'], $categories['exposed']);
unset($options['show_admin_links'], $options['analyze-theme']);
$categories['path'] = [
'title' => $this
->t('Path settings'),
'column' => 'second',
'build' => [
'#weight' => -10,
],
];
$options['path']['category'] = 'path';
$options['path']['title'] = $this
->t('Path');
$options['auth'] = [
'category' => 'path',
'title' => $this
->t('Authentication'),
'value' => views_ui_truncate($auth, 24),
];
unset($options['exposed_form']);
unset($options['exposed_block']);
unset($options['css_class']);
}
public function buildOptionsForm(&$form, FormStateInterface $form_state) {
parent::buildOptionsForm($form, $form_state);
if ($form_state
->get('section') === 'auth') {
$form['#title'] .= $this
->t('The supported authentication methods for this view');
$form['auth'] = [
'#type' => 'checkboxes',
'#title' => $this
->t('Authentication methods'),
'#description' => $this
->t('These are the supported authentication providers for this view. When this view is requested, the client will be forced to authenticate with one of the selected providers. Make sure you set the appropriate requirements at the <em>Access</em> section since the Authentication System will fallback to the anonymous user if it fails to authenticate. For example: require Access: Role | Authenticated User.'),
'#options' => $this
->getAuthOptions(),
'#default_value' => $this
->getOption('auth'),
];
}
}
public function submitOptionsForm(&$form, FormStateInterface $form_state) {
parent::submitOptionsForm($form, $form_state);
if ($form_state
->get('section') == 'auth') {
$this
->setOption('auth', array_keys(array_filter($form_state
->getValue('auth'))));
}
}
public function collectRoutes(RouteCollection $collection) {
parent::collectRoutes($collection);
$view_id = $this->view->storage
->id();
$display_id = $this->display['id'];
if ($route = $collection
->get("view.{$view_id}.{$display_id}")) {
$style_plugin = $this
->getPlugin('style');
$route
->setMethods([
'GET',
]);
$formats = $style_plugin
->getFormats();
if (!$formats) {
$formats = $this
->getFormatOptions();
}
$route
->setRequirement('_format', implode('|', $formats));
$auth = $this
->getOption('auth');
if (!empty($auth)) {
$route
->setOption('_auth', $auth);
}
}
}
protected function overrideApplies($view_path, Route $view_route, Route $route) {
$route_has_format = $route
->hasRequirement('_format');
$route_formats = $route_has_format ? explode('|', $route
->getRequirement('_format')) : [];
$view_route_formats = $view_route
->hasRequirement('_format') ? explode('|', $view_route
->getRequirement('_format')) : [];
return $this
->overrideAppliesPathAndMethod($view_path, $view_route, $route) && (!$route_has_format || array_intersect($route_formats, $view_route_formats) != []);
}
public static function buildResponse($view_id, $display_id, array $args = []) {
$build = static::buildBasicRenderable($view_id, $display_id, $args);
$response = new CacheableResponse('', 200);
$build['#response'] = $response;
$renderer = \Drupal::service('renderer');
$output = (string) $renderer
->renderRoot($build);
$response
->setContent($output);
$cache_metadata = CacheableMetadata::createFromRenderArray($build);
$response
->addCacheableDependency($cache_metadata);
$response->headers
->set('Content-type', $build['#content_type']);
return $response;
}
public function execute() {
parent::execute();
return $this->view
->render();
}
public function render() {
$build = [];
$build['#markup'] = $this->renderer
->executeInRenderContext(new RenderContext(), function () {
return $this->view->style_plugin
->render();
});
$this->view->element['#content_type'] = $this
->getMimeType();
$this->view->element['#cache_properties'][] = '#content_type';
if (!empty($this->view->live_preview)) {
$build['#prefix'] = '<pre>';
$build['#plain_text'] = $build['#markup'];
$build['#suffix'] = '</pre>';
unset($build['#markup']);
}
else {
$build['#markup'] = ViewsRenderPipelineMarkup::create($build['#markup']);
}
parent::applyDisplayCacheabilityMetadata($build);
return $build;
}
public function preview() {
return $this->view
->render();
}
protected function getFormatOptions() {
$formats = array_keys($this->formatProviders);
return array_combine($formats, $formats);
}
}