wieni/wmentity_overview

改进的EntityListBuilders,支持分页、表格排序、表格拖动、筛选、批量操作、数据库查询等。

安装次数: 11 219

依赖项: 0

建议者: 0

安全: 0

星标: 1

关注者: 5

分支: 1

公开问题: 5

类型:drupal-module

1.10.1 2024-03-18 09:10 UTC

README

Latest Stable Version Total Downloads License

改进的EntityListBuilders,支持分页、表格排序、表格拖动、筛选、批量操作、数据库查询等。

为什么?

在Wieni,我们不是很喜欢Views模块,原因有以下几点

  • 我们是程序员,不喜欢通过点击Drupal界面创建功能,尤其是膨胀的Views界面
  • 我们更喜欢编写自己的数据库或实体查询,这在我们进行筛选和包含非实体字段数据时提供了更多的灵活性,并使查询优化更容易

这就是为什么几年前我们决定完全禁用该模块,最终得到了基于EntityListBuilder的列表。

这些很快就显得功能不足且用户友好性差,这就是我们为什么最终创建了此模块:Views和EntityListBuilder之间的完美折衷。它提供了后者的所有功能,以及以下功能

  • 暴露筛选带有自定义表单
  • 幕后筛选使用自定义数据库查询
  • 表格排序,可按列配置
  • 批量操作使用核心操作插件
  • 重写内置实体列表使用自定义列表,在实体类型或包级别上
  • 重写任何路由使用自定义实体列表

安装

此包需要PHP 7.1和Drupal 8或更高版本。可以使用Composer进行安装

 composer require wieni/wmentity_overview

它是如何工作的?

创建概述

概述是具有@OverviewBuilder注解的Drupal插件。每个注解至少需要entity_typeid参数才能正常工作。

您可以选择以下三个基本类之一

  • OverviewBuilderBase:最基本的支持数据库查询、分页和表格排序的实体概述
  • FilterableOverviewBuilderBase:结合基本功能与暴露筛选表单的实体概述
  • DraggableOverviewBuilderBase:具有可拖动、可重新排序表格的实体概述,但不支持分页或筛选

示例

<?php

namespace Drupal\yourmodule\Plugin\EntityOverview;

/**
 * @OverviewBuilder(
 *     entity_type = "node",
 * )
 */
class NodeOverview extends FilterableOverviewBuilderBase
{
}

覆盖现有的实体列表

您可以通过将override参数添加到注解中,用自定义概述覆盖默认的实体列表。如果实体类型未被此模块识别,您可以添加route_name并传递实体列表的路由名称。

也可以在激活某些筛选器组合的情况下仅重写实体列表。这样,您可以在概述通过特定包筛选时添加额外的筛选器或表格列。

示例

<?php

namespace Drupal\yourmodule\Plugin\EntityOverview;

/**
 * @OverviewBuilder(
 *     id = "node",
 *     entity_type = "node",
 *     override = true,
 * )
 */
class NodeOverview extends FilterableOverviewBuilderBase
{
}
<?php

namespace Drupal\yourmodule\Plugin\EntityOverview;

/**
 * @OverviewBuilder(
 *     id = "redirect",
 *     entity_type = "redirect",
 *     route_name = "redirect.list",
 * )
 */
class RedirectOverview extends FilterableOverviewBuilderBase
{
}
<?php

namespace Drupal\yourmodule\Plugin\EntityOverview;

/**
 * @OverviewBuilder(
 *     id = "node.article",
 *     entity_type = "node",
 *     override = true,
 *     filters = {
 *         "type" = "article",
 *     },
 * )
 */
class ArticleOverview extends NodeOverview
{
}

渲染概述

当您创建未覆盖现有路由的概述时,您必须手动将其渲染到某个位置。

创建实体概述实例的方式与其他Drupal插件相同,通过使用OverviewBuilderManagercreateInstance方法。

另一种选项是在您的路由定义的defaults部分添加_entity_overview,值是插件ID。

示例

yourmodule.content_overview.article:
    path: '/admin/content/article'
    defaults:
        _entity_overview: 'node.article'
        _title: 'Articles'
    requirements:
        _permission: 'administer nodes'
    options:
        _admin_route: TRUE

过滤器存储

需要临时存储其过滤器值的实体概述,这是过滤器存储发挥作用的地方:这是一种存储这些值的抽象。

默认情况下,包含两种存储方法:将值存储为URL中的查询参数的query,以及将值存储在会话存储中的session

可以通过创建一个带有@FilterStorage注释和id参数的Drupal插件,实现FilterStorageInterface并可选地扩展FilterStorageBase来添加自定义存储方法。

默认存储方法是query,但可以通过向@OverviewBuilder注释添加filter_storage参数来更改。

添加批量操作

可以通过实现BulkActionOverviewBuilderInterfacegetBulkActionPlugins方法来向概述添加批量操作。此方法可以返回两种类型的数组

  • 一个以插件ID为键,标签为值的关联数组
  • 一个包含插件ID的平面数组

在后一种情况下,将使用默认的插件标签。

可以通过实现PluginFormInterface将配置表单附加到您的操作插件。如果您需要在表单的验证和/或提交处理程序中访问实体,则可以实现ActionPluginFormInterface。请注意,与PluginFormInterface不同,这是一个自定义接口,仅由本模块支持。

钩子和事件

hook_entity_overview_alter

此钩子仅在使用覆盖或使用路由中的_entity_overview默认值时调用。还提供了一个与钩子等效的事件:WmEntityOverviewEvents::ENTITY_OVERVIEW_ALTER

示例
<?php

use Drupal\wmentity_overview\Annotation\OverviewBuilder;

function yourmodule_entity_overview_alter(OverviewBuilder $definition, array &$overview)
{
    if (!empty($overview['form'])) {
        $overview['form']['#attributes']['class'][] = 'custom-entity-overview__form';
    }

    $overview['table']['#attributes']['class'][] = 'custom-entity-overview__table';
}
<?php

namespace Drupal\yourmodule\EventSubscriber;

use Drupal\wmentity_overview\Event\EntityOverviewAlterEvent;
use Drupal\wmentity_overview\WmEntityOverviewEvents;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;

class EntityOverviewSubscriber implements EventSubscriberInterface
{
    public static function getSubscribedEvents()
    {
        $events[WmEntityOverviewEvents::ENTITY_OVERVIEW_ALTER][] = ['onAlter'];

        return $events;
    }

    public function onAlter(EntityOverviewAlterEvent $event): void
    {
        $overview = &$event->getOverview();

        if (!empty($overview['form'])) {
            $overview['form']['#attributes']['class'][] = 'custom-entity-overview__form';
        }
    
        $overview['table']['#attributes']['class'][] = 'custom-entity-overview__table';
    }
}

hook_entity_overview_alternatives_alter

此钩子仅在OverviewBuilderManager::getAlternatives方法中调用。还提供了一个与钩子等效的事件:WmEntityOverviewEvents::ENTITY_OVERVIEW_ALTERNATIVES_ALTER

示例

<?php

namespace Drupal\yourmodule\EventSubscriber;

use Drupal\Core\Routing\RouteMatchInterface;
use Drupal\wmentity_overview\Event\EntityOverviewAlternativesAlterEvent;
use Drupal\wmentity_overview\OverviewBuilder\OverviewBuilderManager;
use Drupal\wmentity_overview\WmEntityOverviewEvents;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;

class EntityOverviewAlternativesSubscriber implements EventSubscriberInterface
{
    /** @var OverviewBuilderManager */
    protected $overviewBuilders;
    /** @var RouteMatchInterface */
    protected $routeMatch;

    public function __construct(
        OverviewBuilderManager $overviewBuilders,
        RouteMatchInterface $routeMatch
    ) {
        $this->overviewBuilders = $overviewBuilders;
        $this->routeMatch = $routeMatch;
    }

    public static function getSubscribedEvents()
    {
        $events[WmEntityOverviewEvents::ENTITY_OVERVIEW_ALTERNATIVES_ALTER][] = ['onTaxonomyAlternativesAlter'];

        return $events;
    }

    /**
     * Since taxonomy has a per-bundle overview, we get the bundle from
     * the route parameters and use it to add more possible alternatives.
     */
    public function onTaxonomyAlternativesAlter(EntityOverviewAlternativesAlterEvent $event): void
    {
        if (!$vocabulary = $this->routeMatch->getParameter('taxonomy_vocabulary')) {
            return;
        }

        if ($event->getDefinition()->getEntityTypeId() !== 'taxonomy_term') {
            return;
        }

        $filters = ['vid' => $vocabulary->id()];
        $alternatives = array_merge(
            $event->getAlternatives(),
            $this->overviewBuilders->getAlternativesByFilters($event->getDefinition(), $filters)
        );

        $event->setAlternatives($alternatives);
    }
}

变更日志

本项目的所有重大更改都将记录在CHANGELOG文件中。

安全

如果您发现任何与安全相关的问题,请通过电子邮件security@wieni.be而不是使用问题跟踪器。

许可证

在MIT许可证下分发。有关更多信息,请参阅LICENSE文件。