Trả lại mã HTTP thay thế cho nút chưa được công bố


8

Tôi đang cố gắng trả lại trang 404 thay vì phản hồi 403 cho các nút chưa được công bố trong Drupal 8.

Tôi đã kiểm tra thuê bao phản hồi kernel , nhưng thấy mã tôi đang sử dụng sẽ chỉ thay đổi mã trạng thái thành 404 từ 403, không thực sự hiển thị trang 404. Vì vậy, có lẽ ai đó có thể chỉ cho tôi cách tạo đối tượng Phản hồi trang 404 ở đó?

Đây là mã tôi đang sử dụng:

class ResponseSubscriber implements EventSubscriberInterface {

  /**
   * {@inheritdoc}
   */
  public static function getSubscribedEvents() {
    return [KernelEvents::RESPONSE => [['alterResponse']]];
  }

  /**
   * Change status code to 404 from 403 if page is an unpublished node.
   *
   * @param FilterResponseEvent $event
   *   The route building event.
   */
  public function alterResponse(FilterResponseEvent $event) {
    if ($event->getResponse()->getStatusCode() == 403) {
      /** @var \Symfony\Component\HttpFoundation\Request $request */
      $request = $event->getRequest();
      $node = $request->attributes->get('node');
      if ($node instanceof Node && !$node->isPublished()) {
        $response = $event->getResponse();
        // This changes the code, but doesn't return a 404 page.
        $response->setStatusCode(404);

        $event->setResponse($response);
      }
    }
  }

}

Cuối cùng tôi đã dùng đến việc loại bỏ hoàn toàn thuê bao phản hồi này và sử dụng hook_node_access như thế này:

use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use Drupal\Core\Access\AccessResult;

function unpublished_404_node_access(\Drupal\node\NodeInterface $node, $op, \Drupal\Core\Session\AccountInterface $account) {

  if ($op == 'view' && !$node->isPublished()) {
    if (\Drupal::moduleHandler()->moduleExists('workbench_moderation') && $account->hasPermission('view any unpublished content')) {
      return AccessResult::neutral();
    }
    elseif (\Drupal::routeMatch()->getRouteName() == 'entity.node.canonical' && \Drupal::routeMatch()->getRawParameter('node') == $node->id()) {
      throw new NotFoundHttpException();
      return AccessResult::neutral();
    }
  }

  return AccessResult::neutral();
}

Điều này dường như phù hợp với một số câu trả lời trên trang web này cho Drupal 7. Nhưng tôi muốn xem liệu có ai có cách làm tốt hơn với người đăng ký KernelEvent, thay vì hook_node_access. Có vẻ như những gì tôi muốn làm là kiểm tra nếu một nút trả về 403 và sau đó tạo phản hồi mới với trang 404 và mã trạng thái 404. Tôi không chắc làm thế nào để làm điều đó.

Câu trả lời:


6

Bạn có thể thử làm điều này sớm hơn trong một ngoại lệ thay vì thuê bao phản hồi. Mở rộng HttpExceptionSubscriberBase, vì vậy bạn cần ít mã hơn để làm điều này. Sau đó thay thế 403 bằng ngoại lệ 404 bằng phương thức$event->setException()

/src/EventSubscacker/Unpublished404Subscacker.php

<?php

namespace Drupal\mymodule\EventSubscriber;

use Drupal\Core\EventSubscriber\HttpExceptionSubscriberBase;
use Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;

class Unpublished404Subscriber extends HttpExceptionSubscriberBase {

  protected static function getPriority() {
    // set priority higher than 50 if you want to log "page not found"
    return 0;
  }

  protected function getHandledFormats() {
    return ['html'];
  }

  public function on403(GetResponseForExceptionEvent $event) {
    $request = $event->getRequest();
    if ($request->attributes->get('_route') == 'entity.node.canonical') {
      $event->setException(new NotFoundHttpException());
    }
  }

}

mymodule.service.yml:

services:
  mymodule.404:
    class: Drupal\mymodule\EventSubscriber\Unpublished404Subscriber
    arguments: []
    tags:
      - { name: event_subscriber }

Điều này thay thế tất cả 403 ngoại lệ cho các tuyến nút chính tắc. Bạn có thể lấy đối tượng nút $request->attributes->get('node')nếu bạn muốn kiểm tra xem điều này có thực sự là do nút không được công bố hay không.


Cảm ơn bạn, tôi đã thử nghiệm nó và nó hoạt động rất tốt! Đây chỉ là loại điều tôi đang tìm kiếm.
oknate
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.