Drupal 8:当内容属于多个分类时如何管理面包屑?

如何解决Drupal 8:当内容属于多个分类时如何管理面包屑?

我在 Drupal 8 中有一个博客,它使用类别分类法来显示面包屑:主页 > 博客 > [类别] > 帖子标题。我正在添加标签分类法,这意味着每个帖子可以有一个类别和多个标签。

自从我添加标签分类后,它们就接管了各个博客帖子的面包屑:主页 > 博客 > [标签] > 帖子标题。

在 Drupal 管理员中(开箱即用,或通过模块):

  1. 是否可以控制在显示面包屑时应优先考虑哪个分类法?

  2. 是否可以根据用户来自哪里来控制在博客帖子上显示的分类法?例如,如果用户在个人标签页面:首页 > 博客 > [标签] 并点击属于该标签的博客文章,当博客文章打开时,它应该使用标签分类显示面包屑:主页 > 博客 > [标签] > 帖子标题。但是,如果用户在单个类别页面上:主页 > 博客 > [类别] 并单击属于该类别的博客文章,则当博客文章打开时,它应该使用类别分类法显示面包屑:主页 > 博客 > [类别] > 帖子标题。

解决方法

这是我的解决方案。请记住,我对 Drupal 很陌生,所以这可能有点过于复杂,但希望它能给有类似问题的人一些指导。在接下来的几天里,我可能会重构这个类,但现在我只需要从所有这些混乱中休息一下。

function [YOUR-MODULE-NAME]_system_breadcrumb_alter(\Drupal\Core\Breadcrumb\Breadcrumb &$breadcrumb,\Drupal\Core\Routing\RouteMatchInterface $route_match,array $context) {

  // Control Blog Post Breadcrumb Taxonomy Trail
  $blogPostBreadcrumb = new BlogPostBreadcrumb();
  $blogPostBreadcrumb->alter($breadcrumb);
}



use Drupal\Core\Breadcrumb\Breadcrumb;
use Drupal\Core\Entity\EntityBase;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Url;
use Drupal\node\Entity\Node;
use Drupal\taxonomy\Entity\Term;
use Exception;
use Symfony\Component\HttpFoundation\Request;

/**
 * Class BlogPostBreadcrumb
 *
 * The purpose of this class is to control Blog post breadcrumbs,as described here:
 * 
 * RULE 1:
 * When the user is on the Tag page (Home > Blog > Tag) and clicks on a blog post,the blog post breadcrumbs will
 * display: Home > Blog > [Tag Name] > Blog Post Title
 *
 * RULE 2:
 * When the user is on the Category page (Home > Blog > Category) and clicks on a blog post,the blog post breadcrumbs
 * will display: Home > Blog > [Category Name] > Blog Post Title
 *
 * RULE 3:
 * When the user loads the blog post directly (i.e. Home > Blog,or comes from other sources unrelated to
 * Category or Tag),the blog post breadcrumbs should default to Category:
 * Home > Blog > [Category Name] > Blog Post Title
 *
 */
class BlogPostBreadcrumb
{
  /**
   * @param Breadcrumb $breadcrumb
   */
  public function alter(Breadcrumb &$breadcrumb): void
  {
    try {
      // current node
      $current_node = $this->currentNode();

      // nothing found,nothing to do
      if (empty($current_node)) {
        return;
      }

      // what is the current content type
      $content_type = $this->getField($current_node,'type');

      // apply rule only to blog_post content type,otherwise let's stop the madness right here
      if ($content_type !== 'blog_post') {
        return;
      }

      // determine if the tag can be extracted from referrer. If not,default it to college_tag
      $altered_breadcrumb = $this->getTaxonomyLabelAndUrlByReferrer()
        ?? $this->getTaxonomyLabelAndUrlByCollege($current_node);

      // nothing matched - just let it be. Display blog_tags rather than nothing.
      if (empty($altered_breadcrumb)) {
        return;
      }

      // modify existing breadcrumb list by replacing the third link with proper tag
      // (Home > Blog > [college_tag/blog_tag] > Blog Title)
      $breadcrumb->getLinks()[2]->setText($altered_breadcrumb['label']);
      $breadcrumb->getLinks()[2]->setUrl($altered_breadcrumb['url']);

      // we have to disable caching,otherwise whichever taxonomy opens first,it will get cached!
      // load menu_link_content entity
      $entity =  \Drupal::entityTypeManager()
        ->getStorage('menu_link_content')
        ->load($current_node->getEntityTypeId());
      // disable caching
      $breadcrumb->addCacheableDependency($entity);
    } catch (Exception $e) {
      // if any exception is thrown,we don't want to stop the page from loading.
      // Worse case scenario,it will load blog_tags into breadcrumbs.
    }

  }

  /**
   * Get Field from node
   * Helper method for retrieving field value from given node.
   *
   * @param EntityInterface $node
   * @param string $fieldName
   * @return mixed|null
   */
  protected function getField(EntityInterface $node,string $fieldName)
  {
    return $node->get($fieldName)->getValue()[0]['target_id'] ?? null;
  }

  /**
   * Load node from current url
   *
   * @return EntityBase|null
   */
  protected function currentNode():? EntityBase
  {
    if ($nid = \Drupal::routeMatch()->getParameter('node')) {
      return Node::load($nid->id()) ?? null;
    }
    return null;
  }

  /**
   * Determine Taxonomy Breadcrumb Label and Url by referrer
   * We want to display Breadcrumb category depending from where the user is coming from:
   * Blog College (category) or Blog tag page
   *
   * @return array|null
   */
  protected function getTaxonomyLabelAndUrlByReferrer():? array
  {
    // capture referrer the "Drupal way"
    $route_parameters = $this->referrer();

    // if type is not a taxonomy term,it's not used to us
    if (empty($route_parameters['taxonomy_term'])) {
      return null;
    }

    // load node (taxonomy term)
    $term = Term::load($route_parameters['taxonomy_term']);

    // get taxonomy type
    $taxonomy = $this->getField($term,'vid');

    // check if taxonomy belongs to college_tags or blog_tags
    if (empty($taxonomy) && !in_array($taxonomy,['college_tags','blog_tags'])) {
      return null;
    }

    // if we can't find the url or the label
    if (empty($term->url() || empty($term->label()))) {
      return null;
    }

    return [
      'label' => $term->label(),'url' => Url::fromUserInput($term->url())
    ];
  }

  /**
   * Determine Taxonomy Breadcrumb Label and Url by college
   * This method will be used when referrer page doesn't exist,or the referrer is not Blog Category or Blog Tag page
   *
   * @param EntityInterface $node
   * @return array|null
   */
  protected function getTaxonomyLabelAndUrlByCollege(EntityInterface $node):? array
  {
    // blog can have one college tag (category)
    $taxonomy_id = $this->getField($node,'field_college');
    $term = Term::load($taxonomy_id);

    // if we can't find the url or the label
    if (empty($term->url() || empty($term->label()))) {
      return null;
    }

    return [
      'label' => $term->label(),'url' => Url::fromUserInput($term->url())
    ];
  }

  /**
   * Referrer node
   * Load referrer node the "drupal way"
   *
   * @return mixed
   */
  protected function referrer()
  {
    // this would be college_tag or blog_tag page
    $previousUrl = \Drupal::request()->server->get('HTTP_REFERER');
    // fake the request to previous page,so we can get more info
    $fake_request = Request::create($previousUrl);
    // build url object.
    $url_object = \Drupal::service('path.validator')->getUrlIfValid($fake_request->getRequestUri());
    if ($url_object) {
      return $url_object->getRouteParameters();
    } else {
      return null;
    }
  }
}

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


使用本地python环境可以成功执行 import pandas as pd import matplotlib.pyplot as plt # 设置字体 plt.rcParams['font.sans-serif'] = ['SimHei'] # 能正确显示负号 p
错误1:Request method ‘DELETE‘ not supported 错误还原:controller层有一个接口,访问该接口时报错:Request method ‘DELETE‘ not supported 错误原因:没有接收到前端传入的参数,修改为如下 参考 错误2:cannot r
错误1:启动docker镜像时报错:Error response from daemon: driver failed programming external connectivity on endpoint quirky_allen 解决方法:重启docker -> systemctl r
错误1:private field ‘xxx‘ is never assigned 按Altʾnter快捷键,选择第2项 参考:https://blog.csdn.net/shi_hong_fei_hei/article/details/88814070 错误2:启动时报错,不能找到主启动类 #
报错如下,通过源不能下载,最后警告pip需升级版本 Requirement already satisfied: pip in c:\users\ychen\appdata\local\programs\python\python310\lib\site-packages (22.0.4) Coll
错误1:maven打包报错 错误还原:使用maven打包项目时报错如下 [ERROR] Failed to execute goal org.apache.maven.plugins:maven-resources-plugin:3.2.0:resources (default-resources)
错误1:服务调用时报错 服务消费者模块assess通过openFeign调用服务提供者模块hires 如下为服务提供者模块hires的控制层接口 @RestController @RequestMapping("/hires") public class FeignControl
错误1:运行项目后报如下错误 解决方案 报错2:Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile (default-compile) on project sb 解决方案:在pom.
参考 错误原因 过滤器或拦截器在生效时,redisTemplate还没有注入 解决方案:在注入容器时就生效 @Component //项目运行时就注入Spring容器 public class RedisBean { @Resource private RedisTemplate<String
使用vite构建项目报错 C:\Users\ychen\work>npm init @vitejs/app @vitejs/create-app is deprecated, use npm init vite instead C:\Users\ychen\AppData\Local\npm-
参考1 参考2 解决方案 # 点击安装源 协议选择 http:// 路径填写 mirrors.aliyun.com/centos/8.3.2011/BaseOS/x86_64/os URL类型 软件库URL 其他路径 # 版本 7 mirrors.aliyun.com/centos/7/os/x86
报错1 [root@slave1 data_mocker]# kafka-console-consumer.sh --bootstrap-server slave1:9092 --topic topic_db [2023-12-19 18:31:12,770] WARN [Consumer clie
错误1 # 重写数据 hive (edu)> insert overwrite table dwd_trade_cart_add_inc > select data.id, > data.user_id, > data.course_id, > date_format(
错误1 hive (edu)> insert into huanhuan values(1,'haoge'); Query ID = root_20240110071417_fe1517ad-3607-41f4-bdcf-d00b98ac443e Total jobs = 1
报错1:执行到如下就不执行了,没有显示Successfully registered new MBean. [root@slave1 bin]# /usr/local/software/flume-1.9.0/bin/flume-ng agent -n a1 -c /usr/local/softwa
虚拟及没有启动任何服务器查看jps会显示jps,如果没有显示任何东西 [root@slave2 ~]# jps 9647 Jps 解决方案 # 进入/tmp查看 [root@slave1 dfs]# cd /tmp [root@slave1 tmp]# ll 总用量 48 drwxr-xr-x. 2
报错1 hive> show databases; OK Failed with exception java.io.IOException:java.lang.RuntimeException: Error in configuring object Time taken: 0.474 se
报错1 [root@localhost ~]# vim -bash: vim: 未找到命令 安装vim yum -y install vim* # 查看是否安装成功 [root@hadoop01 hadoop]# rpm -qa |grep vim vim-X11-7.4.629-8.el7_9.x
修改hadoop配置 vi /usr/local/software/hadoop-2.9.2/etc/hadoop/yarn-site.xml # 添加如下 <configuration> <property> <name>yarn.nodemanager.res