雲客Drupal源碼分析之條件插件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
在表單內部以值類型被保存

 

我是雲客,【雲遊天下,做客四方】,聯繫方式見主頁,歡迎轉載,但須註明出處

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章