From 338705adf3b7a8bf07ae01b1eccb2eb2e61308a3 Mon Sep 17 00:00:00 2001
From: Alex Pott <alex.a.pott@googlemail.com>
Date: Sat, 20 Jul 2013 21:31:43 +0100
Subject: [PATCH] Issue #1979036 by dawehner: Convert views_ajax() to a
 Controller.

---
 core/modules/views/includes/ajax.inc          |  68 ---------
 .../views/Controller/ViewAjaxController.php   | 142 ++++++++++++++++++
 core/modules/views/views.module               |   6 +-
 core/modules/views/views.routing.yml          |   6 +
 4 files changed, 149 insertions(+), 73 deletions(-)
 create mode 100644 core/modules/views/lib/Drupal/views/Controller/ViewAjaxController.php
 create mode 100644 core/modules/views/views.routing.yml

diff --git a/core/modules/views/includes/ajax.inc b/core/modules/views/includes/ajax.inc
index d20bfb98a650..a662cc8421d7 100644
--- a/core/modules/views/includes/ajax.inc
+++ b/core/modules/views/includes/ajax.inc
@@ -22,74 +22,6 @@
  * Handles the server side AJAX interactions of Views.
  */
 
-/**
- * Menu callback to load a view via AJAX.
- */
-function views_ajax() {
-  $request = drupal_container()->get('request');
-  $name = $request->request->get('view_name');
-  $display_id = $request->request->get('view_display_id');
-  if (isset($name) && isset($display_id)) {
-    $args = $request->request->get('view_args');
-    $args = isset($args) && $args !== '' ? explode('/', $args) : array();
-    $path = $request->request->get('view_path');
-    $dom_id = $request->request->get('view_dom_id');
-    $dom_id = isset($dom_id) ? preg_replace('/[^a-zA-Z0-9_-]+/', '-', $dom_id) : NULL;
-    $pager_element = $request->request->get('pager_element');
-    $pager_element = isset($pager_element) ? intval($pager_element) : NULL;
-
-    $response = new ViewAjaxResponse();
-
-    // Remove all of this stuff from the query of the request so it doesn't end
-    // up in pagers and tablesort URLs.
-    foreach (array('view_name', 'view_display_id', 'view_args', 'view_path', 'view_dom_id', 'pager_element', 'view_base_path', 'ajax_html_ids', 'ajax_page_state') as $key) {
-      if ($request->query->has($key)) {
-        $request->query->remove($key);
-      }
-      if ($request->request->has($key)) {
-        $request->request->remove($key);
-      }
-    }
-
-    // Load the view.
-    $view = views_get_view($name);
-    if ($view && $view->access($display_id)) {
-      // Fix the current path for paging.
-      if (!empty($path)) {
-        _current_path($path);
-      }
-
-      // Add all $_POST data, because AJAX is always a post and many things,
-      // such as tablesorts, exposed filters and paging assume $_GET.
-      $request_all = $request->request->all();
-      $query_all = $request->query->all();
-      $request->query->replace($request_all + $query_all);
-
-      // Overwrite the destination.
-      // @see drupal_get_destination()
-      $origin_destination = $path;
-      $query = drupal_http_build_query($request->query->all());
-      if ($query != '') {
-        $origin_destination .= '?' . $query;
-      }
-      $destination = &drupal_static('drupal_get_destination');
-      $destination = array('destination' => $origin_destination);
-
-      // Override the display's pager_element with the one actually used.
-      if (isset($pager_element)) {
-        $response->addCommand(new ScrollTopCommand(".view-dom-id-$dom_id"));
-        $view->displayHandlers->get($display_id)->setOption('pager_element', $pager_element);
-      }
-      // Reuse the same DOM id so it matches that in Drupal.settings.
-      $view->dom_id = $dom_id;
-
-      $preview = $view->preview($display_id, $args);
-      $response->addCommand(new ReplaceCommand(".view-dom-id-$dom_id", drupal_render($preview)));
-    }
-    return $response;
-  }
-}
-
 /**
  * Wrapper around drupal_build_form to handle some AJAX stuff automatically.
  * This makes some assumptions about the client.
diff --git a/core/modules/views/lib/Drupal/views/Controller/ViewAjaxController.php b/core/modules/views/lib/Drupal/views/Controller/ViewAjaxController.php
new file mode 100644
index 000000000000..b83ac773f2c4
--- /dev/null
+++ b/core/modules/views/lib/Drupal/views/Controller/ViewAjaxController.php
@@ -0,0 +1,142 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\views\Controller\ViewAjaxController.
+ */
+
+namespace Drupal\views\Controller;
+
+use Drupal\Component\Utility\Url;
+use Drupal\Core\Ajax\ReplaceCommand;
+use Drupal\Core\Controller\ControllerInterface;
+use Drupal\Core\Entity\EntityStorageControllerInterface;
+use Drupal\views\Ajax\ScrollTopCommand;
+use Drupal\views\Ajax\ViewAjaxResponse;
+use Drupal\views\ViewExecutableFactory;
+use Symfony\Component\DependencyInjection\ContainerInterface;
+use Symfony\Component\HttpFoundation\Request;
+use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
+
+/**
+ * Defines a controller to load a view via AJAX.
+ */
+class ViewAjaxController implements ControllerInterface {
+
+  /**
+   * The entity storage controller for views.
+   *
+   * @var \Drupal\Core\Entity\EntityStorageControllerInterface
+   */
+  protected $storageController;
+
+  /**
+   * The factory to load a view executable with.
+   *
+   * @var \Drupal\views\ViewExecutableFactory
+   */
+  protected $executableFactory;
+
+  /**
+   * Constructs a ViewAjaxController object.
+   *
+   * @param \Drupal\Core\Entity\EntityStorageControllerInterface $storage_controller
+   *   The entity storage controller for views.
+   * @param \Drupal\views\ViewExecutableFactory $executable_factory
+   *   The factory to load a view executable with.
+   */
+  public function __construct(EntityStorageControllerInterface $storage_controller, ViewExecutableFactory $executable_factory) {
+    $this->storageController = $storage_controller;
+    $this->executableFactory = $executable_factory;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function create(ContainerInterface $container) {
+    return new static(
+      $container->get('plugin.manager.entity')->getStorageController('view'),
+      $container->get('views.executable')
+    );
+  }
+
+  /**
+   * Loads and renders a view via AJAX.
+   *
+   * @param \Symfony\Component\HttpFoundation\Request $request
+   *  The current request object.
+   *
+   * @return \Drupal\views\Ajax\ViewAjaxResponse
+   *  The view response as ajax response.
+   *
+   * @throws \Symfony\Component\HttpKernel\Exception\NotFoundHttpException
+   *   Thrown when the view was not found.
+   */
+  public function ajaxView(Request $request) {
+    $name = $request->request->get('view_name');
+    $display_id = $request->request->get('view_display_id');
+    if (isset($name) && isset($display_id)) {
+      $args = $request->request->get('view_args');
+      $args = isset($args) && $args !== '' ? explode('/', $args) : array();
+      $path = $request->request->get('view_path');
+      $dom_id = $request->request->get('view_dom_id');
+      $dom_id = isset($dom_id) ? preg_replace('/[^a-zA-Z0-9_-]+/', '-', $dom_id) : NULL;
+      $pager_element = $request->request->get('pager_element');
+      $pager_element = isset($pager_element) ? intval($pager_element) : NULL;
+
+      $response = new ViewAjaxResponse();
+
+      // Remove all of this stuff from the query of the request so it doesn't
+      // end up in pagers and tablesort URLs.
+      foreach (array('view_name', 'view_display_id', 'view_args', 'view_path', 'view_dom_id', 'pager_element', 'view_base_path', 'ajax_html_ids', 'ajax_page_state') as $key) {
+        $request->query->remove($key);
+        $request->request->remove($key);
+      }
+
+      // Load the view.
+      $result = $this->storageController->load(array($name));
+      if (!$entity = reset($result)) {
+        throw new NotFoundHttpException();
+      }
+      $view = $this->executableFactory->get($entity);
+      if ($view && $view->access($display_id)) {
+        // Fix the current path for paging.
+        if (!empty($path)) {
+          $request->attributes->set('system_path', $path);
+        }
+
+        // Add all $_POST data, because AJAX is always a post and many things,
+        // such as tablesorts, exposed filters and paging assume $_GET.
+        $request_all = $request->request->all();
+        $query_all = $request->query->all();
+        $request->query->replace($request_all + $query_all);
+
+        // Overwrite the destination.
+        // @see drupal_get_destination()
+        $origin_destination = $path;
+        $query = Url::buildQuery($request->query->all());
+        if ($query != '') {
+          $origin_destination .= '?' . $query;
+        }
+        $destination = &drupal_static('drupal_get_destination');
+        $destination = array('destination' => $origin_destination);
+
+        // Override the display's pager_element with the one actually used.
+        if (isset($pager_element)) {
+          $response->addCommand(new ScrollTopCommand(".view-dom-id-$dom_id"));
+          $view->displayHandlers->get($display_id)->setOption('pager_element', $pager_element);
+        }
+        // Reuse the same DOM id so it matches that in Drupal.settings.
+        $view->dom_id = $dom_id;
+
+        $preview = $view->preview($display_id, $args);
+        $response->addCommand(new ReplaceCommand(".view-dom-id-$dom_id", drupal_render($preview)));
+      }
+      return $response;
+    }
+    else {
+      throw new NotFoundHttpException();
+    }
+  }
+
+}
diff --git a/core/modules/views/views.module b/core/modules/views/views.module
index 9a5b00cbf1d7..2165f6783440 100644
--- a/core/modules/views/views.module
+++ b/core/modules/views/views.module
@@ -297,13 +297,9 @@ function views_menu() {
   $items = array();
   $items['views/ajax'] = array(
     'title' => 'Views',
-    'page callback' => 'views_ajax',
     'theme callback' => 'ajax_base_page_theme',
-    'delivery callback' => 'ajax_deliver',
-    'access callback' => TRUE,
-    'description' => 'Ajax callback for view loading.',
+    'route_name' => 'views_ajax',
     'type' => MENU_CALLBACK,
-    'file' => 'includes/ajax.inc',
   );
   // Define another taxonomy autocomplete because the default one of drupal
   // does not support a vid a argument anymore
diff --git a/core/modules/views/views.routing.yml b/core/modules/views/views.routing.yml
new file mode 100644
index 000000000000..016b2a5315c9
--- /dev/null
+++ b/core/modules/views/views.routing.yml
@@ -0,0 +1,6 @@
+views_ajax:
+  pattern: '/views/ajax'
+  defaults:
+    _controller: '\Drupal\views\Controller\ViewAjaxController::ajaxView'
+  requirements:
+    _access: 'TRUE'
-- 
GitLab