92. 条件插件condition plugins
条件插件在块实体配置中被用到(在默认安装下,系统也只有该处用到),用来指定块在什么条件下才显示,见管理后台:管理》结构》区块布局》点击某个块的配置,每一种类型的条件由一个插件负责,这些插件由条件插件管理器来管理:
服务id:plugin.manager.condition
类:Drupal\Core\Condition\ConditionManager
获取方式:\Drupal::service('plugin.manager.condition');
插件定义的修改钩子:condition_info
插件存放目录:src/Plugin/Condition
释文类:\Drupal\Core\Condition\Annotation\Condition
系统默认提供了5个条件插件:
语言条件:
控制在某种语言界面下,是否满足需求,类如下:
Drupal\language\Plugin\Condition\Language
内容类型条件:
控制是在哪些内容类型下条件是否满足,类如下:
\Drupal\node\Plugin\Condition\NodeType
页面条件:
依据路径判断是否满足条件,类如下:
\Drupal\system\Plugin\Condition\RequestPath
角色条件:
依据角色判断是否满足条件,类如下:
\Drupal\user\Plugin\Condition\UserRole
当前主题条件:
只在当前主题下才满足条件,类如下:
\Drupal\system\Plugin\Condition\CurrentThemeCondition
自定义条件插件:
在模块的src/Plugin/Condition目录下定义一个类,实现以下接口:
\Drupal\Core\Condition\ConditionInterface
系统很贴心的提供了条件插件的默认基类:
\Drupal\Core\Condition\ConditionPluginBase
只需要继承她即可,清除缓存启用
可参见系统定义的插件示例,以下提供了一个自定义的示例。
自定义示例:
这里提供一个示例,用于在指定的星期才显示块,没有指定的那一天不显示,如果没有配置,将视为显示,这里假设模块名为“yunke”,在目录yunke/src/Plugin/Condition建立一个类,文件名:Week.php,内容如下:
<?php
namespace Drupal\yunke\Plugin\Condition;
use Drupal\Core\Condition\ConditionPluginBase;
use Drupal\Core\Form\FormStateInterface;
/**
* 提供一个星期条件
*
* @Condition(
* id = "week",
* label = @Translation("week"),
* )
*/
class Week extends ConditionPluginBase
{
/**
* {@inheritdoc}
*/
public function buildConfigurationForm(array $form, FormStateInterface $form_state)
{
$options = [
1 => 'Monday',
2 => 'Tuesday',
3 => 'Wednesday',
4 => 'Thursday',
5 => 'Friday',
6 => 'Saturday',
0 => 'Sunday',
];
$form['week'] = [
'#type' => 'checkboxes',
'#title' => '在以下时间显示',
'#default_value' => $this->configuration['week'],
'#options' => $options,
'#description' => '如果没有选择,相当于全部选中',
];
return parent::buildConfigurationForm($form, $form_state);
}
/**
* {@inheritdoc}
*/
public function defaultConfiguration()
{
return [
'week' => [],
] + parent::defaultConfiguration();
}
/**
* {@inheritdoc}
*/
public function submitConfigurationForm(array &$form, FormStateInterface $form_state)
{
$this->configuration['week'] = array_filter($form_state->getValue('week'));
parent::submitConfigurationForm($form, $form_state);
}
/**
* {@inheritdoc}
*/
public function summary()
{
$days = $this->configuration['week'];
if (count($days) > 1) {
$days = implode(', ', $days);
} else {
$days = reset($days);
}
if (!empty($this->configuration['negate'])) {
return $this->t('在星期 @week 将不显示', ['@week' => $days]);
} else {
return $this->t('在星期 @week 显示', ['@week' => $days]);
}
}
/**
* {@inheritdoc}
*/
public function evaluate()
{
$week=date("w");
if (empty($this->configuration['week']) && !$this->isNegated()) {
return TRUE;
}
return in_array($week, $this->configuration['week']);
}
/**
* {@inheritdoc}
*/
public function getCacheContexts()
{
$contexts = parent::getCacheContexts();
$contexts[]='week';
//此处应定义一个关于星期的上下文,以便让缓存正常工作
return $contexts;
}
}
该类需要一个自定义的上下文,在目录yunke\src\CacheContext建立类:
文件名:WeekCacheContext.php 内容如下:
<?php
namespace Drupal\yunke\CacheContext;
use Drupal\Core\Cache\CacheableMetadata;
use Drupal\Core\Cache\Context\CacheContextInterface;
/**
* 定义一个星期缓存上下文
*
* 上下文 ID: 'week'.
*/
class WeekCacheContext implements CacheContextInterface {
/**
* {@inheritdoc}
*/
public static function getLabel() {
return t('Week');
}
/**
* {@inheritdoc}
*/
public function getContext() {
return date("w");
}
/**
* {@inheritdoc}
*/
public function getCacheableMetadata() {
return new CacheableMetadata();
}
}
然后在服务定义文件:yunke/yunke.services.yml中添加以下内容:
cache_context.week:
class: \Drupal\yunke\CacheContext\WeekCacheContext
tags:
- { name: cache.context }
清除缓存,然后到块配置页面就能看到我们自定义的条件了
条件解析特征:
系统提供了一个条件解析特征:
\Drupal\Core\Condition\ConditionAccessResolverTrait
这被用来判断有多个条件时,最终条件是否能够满足,只有一个方法:
resolveConditions($conditions, $condition_logic)
参数$conditions是由条件插件对象构成的数组,$condition_logic代表级联条件的关键词,and或or之一,
该方法返回一个布尔值,代表条件是否得到满足,true为所有条件满足。
补充:
条件插件的上下文映射数组来自:
\Drupal\Core\Condition\ConditionPluginBase::buildConfigurationForm
在表单内部以值类型被保存