logo

额外区块类型 (EBT) - 全新的布局构建器体验❗

额外区块类型 (EBT) - 样式化、可定制的区块类型:幻灯片、标签页、卡片、手风琴等更多类型。内置背景、DOM Box、JavaScript 插件的设置。立即体验布局构建的未来。

演示 EBT 模块 下载 EBT 模块

❗额外段落类型 (EPT) - 全新的 Paragraphs 体验

额外段落类型 (EPT) - 类似的基于 Paragraph 的模块集合。

演示 EPT 模块 滚动

滚动

创建新的 EBT 模块

28/09/2025, by Ivan

创建新 EBT 模块的最简单方法是使用 Drush 命令(适用于 Drush 12+)。要使用此命令,您需要启用 EBT Core Starterkit 模块:

EBT Starterkit

之后,EBT 模块生成器将可用:

drush generate ebt:module

机器名需以 ebt_* 前缀开头,这是所有 EBT 模块正常工作的必需条件。

EBT module generate

您也可以在 EBT Core 模块文件夹中使用 EBT Starterkit。只需将文件中的所有 ebt_starterkit 重命名为新 EBT 模块的机器名。

https://www.drupal.org/project/ebt_core

或者复制 EBT Text 模块并替换其中的机器名。

https://www.drupal.org/project/ebt_text

因为它是最简单的 EBT 模块,并且包含所有基本的 EBT 设置。

逐步创建 EBT 模块

复制现有的 EBT Text 模块作为样板,或者使用 drush generate ebt:module 命令。

EBT Text 模块包含以下文件夹:
/ebt_text/config/install - 包含 EBT Text 区块类型和字段实例的配置。其他 EBT 模块可以包含段落类型和字段存储的配置。
/ebt_text/templates - 包含 block--block-content--ebt-text.html.twig 模板,用于可在区块布局页面中使用的内容区块,以及 block--inline-block--ebt-text.html.twig 模板,用于 Layout Builder 内联区块。
/ebt_text/tests - 包含 EBT 模块的测试,目前只有一个安装模块的测试。

以及其他常规的 Drupal 模块文件:composer.jsonebt_text.info.ymlreadme.md。您可以在官方文档中阅读更多关于创建自定义 Drupal 模块的信息:

https://www.drupal.org/docs/develop/creating-modules

我将创建一个新的模块 EBT Countdown,它将使用这个 javascript 插件 FlipDown:

https://github.com/PButcher/flipdown

FlipCount.js

Fork Github 仓库并提交到 Packagist

所有第三方库都应该 fork 并放置在 Packagist 上,例如:

https://packagist.org/packages/levmyshkin/flexslider

来源:

https://github.com/levmyshkin/flexslider

然后 Composer 就可以像下载普通 packagist 库一样下载它们。这些第三方库必须包含 "type": "drupal-library",并且默认情况下会下载到 /libraries 文件夹:
https://github.com/levmyshkin/flexslider/blob/master/composer.json

EBT 库

让我们 fork FlipDown 的 github 仓库。

fork git 仓库而不是直接使用源 git 仓库可能看起来有点不常见。但我认为这样可以更容易地使用 EBT 模块,而无需在主 composer.json 文件中手动操作来添加外部仓库链接。想象一下,对于新手来说,安装 composer、手动更新 composer.json 文件并将仓库源放在正确的位置是多么困难。有了自己的 packagist 库,安装过程会变得更简单。所以让我们把所有第三方库都放在 packagist 上。

fork git 仓库

在 fork git 仓库页面上,您可以重命名仓库。必须保持名称简洁,不能包含大写字母和特殊字符,短横线(-)和下划线(_)是允许的。

重命名仓库

现在我们有了一个新的 git 仓库:

https://github.com/levmyshkin/flipdown

接着我们需要在这个仓库中添加 composer.json 文件,并包含 "type": "drupal-library"

git add composer.json
git commit -m 'Add Composer.json file'
git push origin master

这里是 composer.json 文件:

https://github.com/levmyshkin/flipdown/blob/master/composer.json

如果您检查新 git 仓库中的当前标签,会发现是空的:

git tag

Git 标签

通常我会遵循源仓库的版本号,例如,如果库的最新版本是 1.4.6,我会将次版本号增加到 1.4.7。FlipDown 仓库没有任何标签或发布,因此我为新仓库创建了 1.0.0 版本:

git tag 1.0.0
git push origin 1.0.0

我们需要新的标签,因为它包含了带有 "type": "library" 的 composer.json 文件。

为什么我们不能简单地将 javascript 库复制到模块中?

我们只能复制 GPL 许可证下的库,但通常 javascript 库使用 MIT 许可证。从技术上讲可以这样做,但根据 Drupal.org 的规则这是被禁止的: 

https://www.drupal.org/about/licensing

让我们在 packagist.org 上提交 FlipDown 库:

https://packagist.org/packages/submit

在 packagist.org 上提交新库

如果您提交了库,但忘记在其中添加带有 "type": "drupal-library" 的 composer.json 文件,不用担心,只需添加 composer.json 文件并为您的 git 仓库创建新标签。这个标签会自动推送到 packagist。

这里是 FlipDown 的 packagist 库页面:

https://packagist.org/packages/levmyshkin/flipdown

Packagist 库

请确保在 packagist 页面上显示的是 drupal-library 类型。

接下来我们回到 drupal 文件中,复制 ebt_text 文件夹,我将新模块命名为 ebt_countdown:

EBT Countdown 模块

我们需要:

- 删除 /config/install 中的配置,我们稍后会导出新的配置

- 将所有 ebt_text 替换为 ebt_countdown

- 重命名文件名,将其中的 “text” 替换为 “countdown”

- 更新 ebt_countdown.info.yml 和 README.md 文件中的模块描述。

我会在 git 中分别提交每一步,这样您可以逐步查看更新:

git clone https://git.drupalcode.org/project/ebt_countdown.git

Git 历史
 

现在我们有了模块的样板,可以将更改推送到 Drupal.org。

在 Drupal.org 上创建模块项目

让我们进入 drupal.org 网站的添加项目页面:

https://www.drupal.org/node/add

Drupal.org 添加内容

我们需要添加一个模块项目:

https://www.drupal.org/node/add/project-module

名称: Extra Block Types (EBT): Countdown
项目类型: 完整项目
短名称: ebt_countdown
维护状态: 活跃维护
开发状态: 正在积极开发
模块类别: 内容,内容显示
生态系统: Extra Block Types (EBT): Core (3191928)

创建新的 drupal 项目

描述 字段中,我通常插入完整的可用 EBT 模块列表:

Extra Block Types: Countdown 模块提供添加一个带有动画倒计时区块的功能。

EBT 允许通过 UI 选择倒计时的样式。

EBT 模块提供在 Layout Builder 中通过几次点击即可添加不同区块的能力。您可以从这一系列 EBT 模块中单独安装区块类型:
<ul>
  <li><a href="https://www.drupal.org/project/ebt_accordion" title="EBT Accordion / FAQ">EBT Accordion / FAQ</a></li>
  <li><a href="https://www.drupal.org/project/ebt_basic_button" title="EBT Basic Button">EBT Basic Button</a></li>
  <li><a href="https://www.drupal.org/project/ebt_bootstrap_button" title="EBT Bootstrap Button">EBT Bootstrap Button</a></li>
  <li><a href="https://www.drupal.org/project/ebt_cta" title="EBT Call to Action">EBT Call to Action</a>
  <li><a href="https://www.drupal.org/project/ebt_carousel" title="EBT Tabs">EBT Carousel</a>
  <li><a href="https://www.drupal.org/project/ebt_counter" title="EBT Counter">EBT Counter</a>
  <li><a href="https://www.drupal.org/project/ebt_image_gallery">EBT Image Gallery</a></li>
  <li><a href="https://www.drupal.org/project/ebt_quote" title="EBT Quote">EBT Quote</a></li>
  <li><a href="https://www.drupal.org/project/ebt_slick_slider">EBT Slick Slider</a></li>
  <li><a href="https://www.drupal.org/project/ebt_slideshow">EBT Slideshow</a></li>
  <li><a href="https://www.drupal.org/project/ebt_stats">EBT Stats</a></li>
  <li><a href="https://www.drupal.org/project/ebt_tabs" title="EBT Tabs">EBT Tabs</a></li>
  <li><a href="https://www.drupal.org/project/ebt_text">EBT Text</a></li>
  <li><a href="https://www.drupal.org/project/ebt_timeline">EBT Timeline</a></li>
  <li><a href="https://www.drupal.org/project/ebt_webform">EBT Webform</a></li>
  <li><a href="https://www.drupal.org/project/ebt_webform_popup">EBT Webform Popup</a></li>
</ul>

所有 EBT 区块类型包含默认小部件,它具有以下设计选项:
<ul>
<li>CSS Box(边距、内边距、边框)</li>
<li>背景(使用颜色、图像(包括视差和覆盖)、视频(Youtube))</li>
<li>全宽,容器宽度</li>
</ul>

更多关于 EBT 区块的信息请参阅 EBT Core 模块页面:
https://www.drupal.org/project/ebt_core

<div class="container">
<div class="panel-layout capricorn pane-bundle-cta-multiple">
  <div class="panel-pane pane-fieldable-panels-pane pane-vid-10729 d-sponsor pane-bundle-cta pane-fpid-422">
   <div class="pane-content">
    <div class="fieldable-panels-pane pane-style-full nographic pane-style-supporter">
     <div class="pane-title pane-bundle-cta-multiple">
       <h3>需要其他 Extra Block Type?</h3>

       <a class="button-link" target="_blank" href="http://drupalbook.org/contact" title="DrupalBook">联系我们</a>

       <a href="http://drupalbook.org/contact" title="DrupalBook"  target="_blank"><img src="/files/logo.svg__1.png" alt="DrupalBook logo" width="85" /></a>
     </div>
   </div>
   </div>
  </div>
</div>
</div>

现在我们在 Drupal.org 上有了 Drupal 模块项目页面:
https://www.drupal.org/project/ebt_countdown

版本控制 标签中,您可以看到如何为本地 git 仓库添加远程 origin 的说明:

https://www.drupal.org/project/ebt_countdown/git-instructions

Drupal 项目版本控制

在初始提交之后,您应该创建一个新分支,以便跟随其他 EBT 模块的主版本,现在是 1.4.x。

现在我们可以开始为模块添加新功能。这个过程与自定义模块开发类似,我们将创建区块类型,添加字段,并包含 css/js 资源。

开始构建 EBT Countdown 功能

步骤 1. 创建 EBT Countdown 区块类型。如果您是使用 Drush 生成的模块,只需安装即可。

如果您是使用 Drush 生成的模块,只需安装即可。

首先,我们需要创建一个新的区块类型 EBT Countdown:

/admin/structure/block/block-content/types/add

创建新区块类型

必须确保机器名以 ebt_ 开头,所以我通常会将区块类型命名以 EBT 开头,这样机器名会自动正确生成。区块类型的机器名是否必须与模块名匹配?是的,这样做有助于保持一致性,并确保不会有其他 EBT 模块使用相同的机器名。区块类型的机器名必须以 ebt_ 开头,因为这样才能在模块中覆盖模板,而不是在主题文件夹中,详见 ebt_core 模块中的 ebt_core_theme_registry_alter() 函数。

现在我们可以添加 EBT 设置字段,这是所有 EBT 模块所需的。我们应该添加现有字段 EBT Settings: field_ebt_settings

添加 EBT 设置字段

EBT Settings 是来自 EBT Core 模块的通用字段,它提供 DOM Box、背景、间距和宽度设置。

由于我们需要倒计时到某个日期,所以我们应该有一个时间戳日期字段。让我们也添加它:

创建日期字段

我在机器可读名称中添加了 ebt_,但这里并不是必须的。它也可以是 field_countdown_date。我们还有默认的正文和标题字段,这对于倒计时区块来说已经足够了。

通常对于 EBT 模块,我们在编辑表单上有水平选项卡:

管理表单显示

这不是必须的,但将内容和设置分开是个好主意,因为我们有很多区块设置。

父字段组应为 Tabs,设置方向为 Horizontal,宽度断点为 120(或任意较小的数值):

选项卡设置

现在我们已经有了区块类型,让我们启用 EBT Countdown 模块,这样区块类型的模板就会被应用:

/admin/modules

启用 EBT Countdown

您还需要启用 Layout Builder 模块,并为某个内容类型启用布局构建器,例如基本页面。

/admin/structure/types/manage/page/display

Drupal EBT Countdown

当您创建新页面时,就可以在页面布局中添加区块了。

EBT Countdown

页面上的效果如下:

EBT Countdown

步骤 2. 将第三方库引入 EBT 模块

现在我们可以引入第三方库了。我们在 composer.json 中已经有 levmyshkin/flipdown 库,但由于这个新模块是自定义模块,所以我们需要使用 composer 手动安装该库:

composer require levmyshkin/flipdown

新库应会自动放置在 libraries 文件夹中:

安装 flipdown

让我们添加 ebt_countdown.libraries.yml 文件,并在其中引入 flipdown 的 css/js 文件以及一个 javascript 文件 ebt_flipdown/js/ebt_countdown.js,稍后我们将在其中初始化 flipdown 插件:

ebt_countdown.libraries.yml

ebt_countdown:
  css:
    component:
      /libraries/flipdown/dist/flipdown.min.css: { minified: true }
  js:
    /libraries/flipdown/dist/flipdown.min.js: { minified: true }
    js/ebt_countdown.js: {}

对于 /libraries 文件夹中的文件,我们使用开头的斜杠,因此这是绝对路径。

js/ebt_countdown.js:

(function ($, Drupal) {

  /**
   * EBT Countdown 行为.
   */
  Drupal.behaviors.ebtCountDown = {
    attach: function (context, settings) {

    };
  }

})(jQuery, Drupal);

我们还需要在模板中引入新的 ebt_countdown 库,别忘了我们有两个模板:

{{ attach_library('ebt_countdown/ebt_countdown') }}

Drupal 模板

清除缓存并检查页面上的 javascript 文件:

添加 javascript 文件

我们将通过 drupalSettings 从 PHP 向 javascript 传递日期。因此,我们需要在 ebt_countdown.libraries.yml 文件中扩展依赖项。同时我们将使用 once() 函数:

  dependencies:
    - core/once
    - core/drupalSettings

步骤 3. 为 EBT 设置引入自定义字段小部件,并将变量传递给 javascript

在 EBT 模块中,设置默认不会传递到 javascript。我们需要覆盖字段小部件类 EbtSettingsDefaultWidget:

ebt_countdown/src/Plugin/Field/FieldWidget/EbtSettingsCountDownWidget.php:

<?php

namespace Drupal\ebt_countdown\Plugin\Field\FieldWidget;

use Drupal\Core\Field\FieldItemListInterface;
use Drupal\Core\Form\FormStateInterface;
use Drupal\ebt_core\Plugin\Field\FieldWidget\EbtSettingsDefaultWidget;

/**
 * Plugin implementation of the 'ebt_settings_countdown' widget.
 *
 * @FieldWidget(
 *   id = "ebt_settings_countdown",
 *   label = @Translation("EBT Countdown settings"),
 *   field_types = {
 *     "ebt_settings"
 *   }
 * )
 */
class EbtSettingsCountDownWidget extends EbtSettingsDefaultWidget {

  /**
   * {@inheritdoc}
   */
  public function formElement(FieldItemListInterface $items, $delta, array $element, array &$form, FormStateInterface $form_state) {
    $element = parent::formElement($items, $delta, $element, $form, $form_state);

    $element['ebt_settings']['pass_options_to_javascript'] = [
      '#type' => 'hidden',
      '#value' => TRUE,
    ];

    return $element;
  }

  /**
   * {@inheritdoc}
   */
  public function massageFormValues(array $values, array $form, FormStateInterface $form_state) {
    foreach ($values as &$value) {
      $value += ['ebt_settings' => []];
    }
    return $values;
  }

}

现在我们可以为 EBT Settings 字段选择这个字段小部件:

/admin/structure/block/block-content/manage/ebt_countdown/form-display

Drupal 设置

让我们重新保存区块并检查 drupalSettings javascript 变量。现在所有来自 EBT Settings 字段的选项都会传递到 javascript:

javascript 变量

在 block-revision-id-* 的末尾,我们有区块修订 ID,因此每个区块都有唯一的键。对于内联区块,我们使用插件 ID plugin-id-block-contentd202c374-f31b-4f7e-8a0d-12842a1422ff。所以在 Layout Builder 中我们有唯一 ID。

FlipDown 插件有明暗主题选项,因此我们在字段小部件 EbtSettingsCountDownWidget 中传递这个设置字段:

    $element['ebt_settings']['color_theme'] = [
      '#title' => $this->t('Color theme'),
      '#type' => 'radios',
      '#options' => [
        'dark' => $this->t('Dark'),
        'light' => $this->t('Light'),
      ],
      '#default_value' => $items[$delta]->ebt_settings['color_theme'] ?? 'dark',
      '#description' => $this->t('Select color theme for countdown'),
      '#weight' => '3',
    ];

主题颜色

然后我们可以在 javascript 中获取主题颜色值:

javascript 值

步骤 4. 为 EBT Countdown 区块初始化 FlipDown 插件

我们已经将设置中的变量传递到 javascript,但还需要将内容中的日期值传递到 javascript。我们将创建一个带有属性 data-date="" 的空 div,其中放置来自日期字段的日期和时间。对于内联区块(Layout Builder 中的区块),我们将使用 block_revision_id 来定义区块的唯一 ID:

block--inline-block--ebt-countdown.html.twig:

    <div
      class="ebt-countdown-date ebt-countdown-inline-block flipdown"
      id="block-id-{{ configuration.block_revision_id }}"
      data-date="{{ content.field_ebt_countdown_date[0]['#attributes']['datetime']|date('U') }}">
    </div>

内联区块倒计时

对于来自区块布局页面的内容区块,我们将使用 plugin_id:

block--block-content--ebt-countdown.html.twig:

    <div
      class="ebt-countdown-date ebt-countdown-block-content flipdown"
      id="block-id-{{ plugin_id|clean_class }}"
      data-date="{{ content.field_ebt_countdown_date[0]['#attributes']['datetime']|date('U') }}">
    </div>

EBT 倒计时区块

如果您不确定字段数据在哪里,可以安装 Twig Debugger 模块,并在页面上打印 content.field_ebt_countdown_date {{ dump(content.field_ebt_countdown_date) }}:

https://www.drupal.org/project/twig_debugger

我们使用了 date('U') twig 过滤器将日期转换为时间戳。

现在我们可以引入自定义 javascript 并初始化 FlipDown。

/ebt_countdown/js/ebt_countdown.js:

(function ($, Drupal) {

  /**
   * EBT Countdown 行为.
   */
  Drupal.behaviors.ebtCountDown = {
    attach: function (context, settings) {
      var countdowns = once('ebt-countdown-block', '.ebt-countdown-date', context);
      countdowns.forEach(function(countdown) {
        var countdownTimestamp = parseInt(countdown.getAttribute('data-date'));
        var countdownId = countdown.getAttribute('id');
        new FlipDown(countdownTimestamp, countdownId, {
          theme: "dark",
        }).start();
      });
    }
  }

})(jQuery, Drupal);

不要忘记清除缓存以查看更新。之后 FlipDown 应该可以在页面上正常工作:

FlipDown

步骤 5. 为新的 EBT Countdown 区块添加样式。Drush 生成的 EBT 模块已包含 Gulp.js 文件。

正如您所看到的,即使是默认的 FlipDown 样式效果也不理想。在桌面端也会出现两行数字。但我们可以很容易通过自定义样式来修复它。您可以从 EBT Counter 模块复制 gulpfile.js 和 package.json 文件,用于将 scss 编译为 css:

https://www.drupal.org/project/ebt_counter

gulpfile.js:

// --------------------------------------------------
// 加载插件
// --------------------------------------------------

var gulp = require('gulp'),
    sass = require('gulp-dart-scss'),
    postcss = require("gulp-postcss"),
    autoprefixer = require("autoprefixer"),
    cssnano = require("cssnano"),
    notify = require('gulp-notify'),
    sassUnicode = require('gulp-sass-unicode');


var config = {
    // 导入部分的主 scss 文件
    scssSrc: 'scss/*.scss',
    // scss 目录中的所有 scss 文件
    allScss: 'scss/**/*.scss',
    // css 目标目录
    cssDest: 'css/',
    // js 目录中的所有 js 文件
    allJs: 'assets/js/**/*.js',
    // 所有图片文件
    allImgs: 'assets/img/**/*'
};


// 定义任务
function style() {

  return gulp.src(config.allScss)
    .pipe(sass())
    .pipe(sassUnicode())
    .pipe(postcss([autoprefixer()]))
    .pipe(gulp.dest(config.cssDest));

  gulp.task('sass:watch', function () {
    gulp.watch('./scss/**/*.scss', ['sass']);
  });
}

// 导出任务
// 可以通过命令行运行
// $ gulp style
exports.style = style;

function watch(){
    // gulp.watch 监听文件变更
    gulp.watch('scss/**/*.scss', style)
}

// 导出任务
exports.watch = watch

package.json:

{
  "name": "ebt_styles",
  "version": "1.0.0",
  "description": "运行 npm install 然后 gulp watch",
  "main": "gulpfile.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "autoprefixer": "^10.2.5",
    "cssnano": "^5.0.2",
    "gulp": "^4.0.2",
    "gulp-dart-scss": "^1.1.0",
    "gulp-notify": "^4.0.0",
    "gulp-postcss": "^9.0.0",
    "gulp-sass-unicode": "^1.0.5",
    "gulp-sourcemaps": "^3.0.0"
  },
  "dependencies": {
    "cucumber": "*",
    "postcss": "^8.2.13"
  }
}

运行以下命令后将生成 package-lock.json 文件:

npm install

您可以通过以下命令启动 gulp 任务:

gulp watch

现在我们将添加 scss 文件:

/ebt_countdown/scss/flipdown.scss

.flipdown {
  width: 580px;
}

flipdown.css 文件将会自动从 flipdown.scss 生成。我们可以在 .libraries.yml 中引入 .css 文件:

ebt_countdown:
  css:
    component:
      /libraries/flipdown/dist/flipdown.min.css: { minified: true }
      css/flipdown.css: { }

让我们清除缓存并查看结果:

EBT 倒计时

现在效果看起来好多了!

我们能否直接使用普通 css 而不是从 scss 编译?

可以,但编写 scss 对大多数开发人员来说更方便。

步骤 6. 使用 FlipDown 插件选项扩展设置表单

FlipDown 插件有一些选项可以更改显示:

https://github.com/PButcher/flipdown

  • theme
  • headings

我们已经为 EBT 设置创建了新的字段小部件 EbtSettingsCountDownWidget,现在我们将通过新字段扩展此表单:

/ebt_countdown/src/Plugin/Field/FieldWidget/EbtSettingsCountDownWidget.php:

    $element['ebt_settings']['color_theme'] = [
      '#title' => $this->t('Color theme'),
      '#type' => 'radios',
      '#options' => [
        'dark' => $this->t('Dark'),
        'light' => $this->t('Light'),
      ],
      '#default_value' => $items[$delta]->ebt_settings['color_theme'] ?? 'dark',
      '#description' => $this->t('Select color theme for countdown'),
      '#weight' => '3',
    ];

    $element['ebt_settings']['styles'] = [
      '#title' => $this->t('Styles'),
      '#type' => 'radios',
      '#options' => [
        'default' => $this->t('Default'),
        'new_year' => $this->t('New Year'),
      ],
      '#default_value' => $items[$delta]->ebt_settings['styles'] ?? 'default',
      '#description' => $this->t('Select special style for countdown'),
      '#weight' => '4',
    ];

    $element['ebt_settings']['heading_days'] = [
      '#title' => $this->t('Heading Days'),
      '#type' => 'textfield',
      '#default_value' => $items[$delta]->ebt_settings['heading_days'] ?? $this->t('Days'),
      '#description' => $this->t('Header for Days counter'),
      '#weight' => '5',
    ];

    $element['ebt_settings']['heading_hours'] = [
      '#title' => $this->t('Heading Hours'),
      '#type' => 'textfield',
      '#default_value' => $items[$delta]->ebt_settings['heading_hours'] ?? $this->t('Hours'),
      '#description' => $this->t('Header for Hours counter'),
      '#weight' => '6',
    ];

    $element['ebt_settings']['heading_minutes'] = [
      '#title' => $this->t('Heading Minutes'),
      '#type' => 'textfield',
      '#default_value' => $items[$delta]->ebt_settings['heading_minutes'] ?? $this->t('Minutes'),
      '#description' => $this->t('Header for Minutes counter'),
      '#weight' => '7',
    ];

    $element['ebt_settings']['heading_seconds'] = [
      '#title' => $this->t('Heading Seconds'),
      '#type' => 'textfield',
      '#default_value' => $items[$delta]->ebt_settings['heading_seconds'] ?? $this->t('Seconds'),
      '#description' => $this->t('Header for Seconds counter'),
      '#weight' => '8',
    ];
    
    return $element;

更新设置表单

这样我们就可以使用 Headings 来做翻译:

添加标题

我们在 javascript 中已经拥有所有 EBT 设置值,因此我在模板中只添加了 ID,以便更容易获取正确的唯一键。

.setAttribute('id', 'plugin-id-' ~ plugin_id|clean_class)
.setAttribute('id', 'block-revision-id-' ~ configuration.block_revision_id)

选项键的模式与 ID 相同:

/ebt_core/ebt_core.module:

  // 对于内容区块使用 plugin_id。
  $build['#attached']['drupalSettings'][$bundle]['block-revision-id-' . $revision_id[0]['value']] = $block_options;
  $uuid = $entity->get('uuid')->getValue();
  $block_options = [
    'blockClass' => 'plugin-id-block-content' . $uuid[0]['value'],
    'options' => $options,
  ];
  $build['#attached']['drupalSettings'][$bundle]['plugin-id-block-content' . $uuid[0]['value']] = $block_options;

所以我们可以在 javascript drupalSettings 中使用这些选项:

EBT 设置

/ebt_countdown/js/ebt_countdown.js:

(function ($, Drupal) {

  /**
   * EBT Countdown 行为.
   */
  Drupal.behaviors.ebtCountDown = {
    attach: function (context, settings) {
      var countdowns = once('ebt-countdown-block', '.ebt-countdown-date', context);
      countdowns.forEach(function(countdown) {
        // 获取区块 ID。
        var countdownWrapper = countdown.closest('.ebt-block-countdown');
        var countdownWrapperId = countdownWrapper.getAttribute('id');
        // 获取区块 EBT 设置。
        var ebtOptions = drupalSettings['ebtCountdown'][countdownWrapperId];
        // 为 javascript 插件准备选项。
        var countdownTimestamp = parseInt(countdown.getAttribute('data-date'));
        var countdownId = countdown.getAttribute('id');
        // 初始化 javascript 插件。
        new FlipDown(countdownTimestamp, countdownId, {
          theme: ebtOptions['options']['color_theme'],
          headings: [
            ebtOptions['options']['heading_days'],
            ebtOptions['options']['heading_hours'],
            ebtOptions['options']['heading_minutes'],
            ebtOptions['options']['heading_seconds'],
          ],
        }).start();
      });
    }
  }

})(jQuery, Drupal);

我还在字段小部件中添加了 $element['ebt_settings']['styles'],所以我们会在模板中使用它为整个区块添加新类:

{%
  set classes = [
  'block',
  'ebt-block',
  'ebt-block-countdown',
  'ebt-block-' ~ plugin_id|clean_class,
  'block-' ~ configuration.provider|clean_class,
  'block-' ~ plugin_id|clean_class,
  'plugin-id-' ~ plugin_id|clean_class,
  content.field_ebt_settings['#object'].field_ebt_settings.ebt_settings.styles,
]
%}
{% if content.field_ebt_settings['#object'].field_ebt_settings.ebt_settings.styles == 'new_year' %}
  {{ attach_library('ebt_countdown/new_year') }}
{% endif %}

它会为新年样式引入 new_year 库,但现在我们需要创建这个库。

/ebt_countdown/ebt_countdown.libraries.yml:

new_year:
  css:
    component:
      css/new-year.css: { }

下面是 new-year 区块的样式:

/ebt_countdown/scss/new-year.scss
/ebt_countdown/css/new-year.css

.ebt-block-countdown.new_year {
  background: url(../img/snowflakes.webp) center center repeat;
}

这是添加新样式的结果:

新年 EBT 区块

您可以为新的或现有的 EBT 模块添加任意数量的样式。您也可以为任何 EBT 模块提出自己的样式,只需在 drupal.org 上创建 issue:

https://www.drupal.org/project/issues/ebt_core

步骤 7. 导出 EBT 区块类型、段落类型和字段的配置

我认为我们已经完成了为 EBT Countdown 添加功能,现在是时候导出配置并在 Drupal.org 上部署更改了。我们应该将所有与 EBT Countdown 相关的配置复制到 /ebt_countdown/config/install 文件夹。

如果您是使用 Drush 生成的 EBT 模块,则需要更新新字段和 EBT 区块类型的配置。

之后,在扩展页面 /admin/modules 启用 EBT 模块。新的 EBT 区块类型和其他设置将会从 config 文件中的 /config/install 文件夹中安装:

 

EBT 模块配置

我们不需要添加 language.* 配置,因为有些 drupal 站点只有一种语言,并且语言模块可能是禁用的。

通常我会复制所有文件,并检查 config/install 文件夹中是否有副本。

配置文件副本

现在我们需要从 config/install 文件夹中的配置中移除 uuid 和哈希值。

移除 uuid

由于我们使用了其他 Drupal 模块,因此应该在 .info 文件中将它们作为依赖项包含进去。

Drupal 依赖项

/ebt_countdown/ebt_countdown.info:

dependencies:
  - drupal:datetime

步骤 8. 在 Drupal.org 上部署并进行测试

我们之前已经在 Drupal.org 上创建了新项目:

https://www.drupal.org/project/ebt_countdown

我将使用 1.4.x 分支作为主分支,以保持与其他 EBT 模块的一致性:

Drupal EBT 模块

因此,所有发布版本将从 1.4.0 开始:

git tag 1.4.0
git push origin 1.4.0

您也可以在创建稳定版 1.4.0 之前,先发布 -alpha、-beta 版本。

我们需要等待 10 天,模块才能被纳入安全公告覆盖范围。

EBT Countdown

这样我们就可以测试新模块并修复错误。

步骤 9. 添加 README.md 文件

不要忘记添加 README.md 文件,您可以在其他 EBT 模块中查看示例:

https://www.drupal.org/project/ebt_slideshow

感谢您使用 EBT 模块!欢迎随时提出问题或分享任何想法:

在 Drupal.org 上创建问题

联系 EBT 模块开发者

或者在 LinkedIn 上给我发消息