如何解决Drupal 8:当内容属于多个分类时如何管理面包屑?
我在 Drupal 8 中有一个博客,它使用类别分类法来显示面包屑:主页 > 博客 > [类别] > 帖子标题。我正在添加标签分类法,这意味着每个帖子可以有一个类别和多个标签。
自从我添加标签分类后,它们就接管了各个博客帖子的面包屑:主页 > 博客 > [标签] > 帖子标题。
在 Drupal 管理员中(开箱即用,或通过模块):
-
是否可以控制在显示面包屑时应优先考虑哪个分类法?
-
是否可以根据用户来自哪里来控制在博客帖子上显示的分类法?例如,如果用户在个人标签页面:首页 > 博客 > [标签] 并点击属于该标签的博客文章,当博客文章打开时,它应该使用标签分类显示面包屑:主页 > 博客 > [标签] > 帖子标题。但是,如果用户在单个类别页面上:主页 > 博客 > [类别] 并单击属于该类别的博客文章,则当博客文章打开时,它应该使用类别分类法显示面包屑:主页 > 博客 > [类别] > 帖子标题。
解决方法
这是我的解决方案。请记住,我对 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 举报,一经查实,本站将立刻删除。