code-rhapsodie/ezdataflow-bundle

基于 Code-Rhapsodie Dataflow 的 Ibexa 导入/导出包

v4.1.2 2024-03-15 10:32 UTC

README

EzDataflowBundle 是一个将 Code Rhapsodie Dataflow bundle 集成到 Ibexa 4.0+ 中的包。可以从 Ibexa 后台集成界面中启动数据流。EzDataflow bundle 用于管理来自外部数据源的内容导入。

注意:在使用此包之前,请阅读 Code Rhapsodie Dataflow bundle 文档

命令行注意事项:当您使用数据流命令时,除非是 code-rhapsodie:dataflow:dump-schema 命令,否则请使用 --siteaccess 而不是 --connection

用户界面 (UI)

该 UI 允许您从任何定义的 DataflowTypes 创建工作流程过程,并为每个设置选项。

过程可以设置为

  • 仅运行一次,在指定的时间和日期
  • 定期运行,通过定义首次运行的时间和日期以及后续运行之间的间隔

安装

步骤 1:通过 composer 安装包

$ composer require code-rhapsodie/ezdataflow-bundle

步骤 2:启用包

注意:数据流包和 Ez Dataflow 包的加载顺序很重要。数据流必须首先加载。

config/bundles.php 文件中添加以下两行

<?php

return [
     // ...
    CodeRhapsodie\DataflowBundle\CodeRhapsodieDataflowBundle::class => ['all' => true],
    CodeRhapsodie\EzDataflowBundle\CodeRhapsodieEzDataflowBundle::class => ['all' => true],
    // ...
];

步骤 3:导入包路由文件

# config/routing/ezdataflow.yaml

_cr.dataflow:
  resource: '@CodeRhapsodieEzDataflowBundle/Resources/config/routing.yaml'

步骤 4:更新数据库模式

请参阅 Code-Rhapsodie Dataflow Bundle 安装指南

步骤 5:安排作业运行器

请参阅 Code-Rhapsodie Dataflow Bundle 队列部分

配置

默认情况下,ContentWriter 将使用 admin 用户发布内容。如果您想使用其他用户(具有足够的权限),可以按如下方式进行配置

# config/packages/code_rhapsodie_ez_dataflow.yaml

code_rhapsodie_ez_dataflow:
  # Integer values are assumed to be user ids, non-integer values are assumed to be user logins
  admin_login_or_id: webmaster

定义您的数据流

在使用管理 UI 管理数据流之前,您需要定义它们。请参阅 Code-Rhapsodie Dataflow 类型文档

使用 ContentWriter

要添加或更新 Ibexa 内容,您可以使用 CodeRhapsodie\EzDataflowBundle\Writer\ContentWriter 编写器。

步骤 1:注入依赖项并添加编写器

ContentWriter 服务注入到您的 DataflowType 构造函数中,并将内容编写器添加到编写器列表中,如下所示

// In your DataflowType

use CodeRhapsodie\EzDataflowBundle\Writer\ContentWriter;
use CodeRhapsodie\DataflowBundle\DataflowType\AbstractDataflowType;
[...]

class MyDataflowType extends AbstractDataflowType
{
    //[...]
    /**
     * @var ContentWriter
     */
    private $contentWriter;

    public function __construct(ContentWriter $contentWriter)
    {
        $this->contentWriter = $contentWriter;
    }
    //[...]
    protected function buildDataflow(DataflowBuilder $builder, array $options): void
    {
        //[...]
        $builder->addWriter($this->contentWriter);
    }
}

步骤 2:添加一个步骤来准备内容

要处理 Ibexa 内容并添加到您的数据流中,您需要将数据转换为 ContentCreateStructureContentUpdateStructure 对象。分别用于创建或更新内容。

但是,为了确定内容是否已经存在,您首先需要查找它。

一种方法是使用远程 id 搜索内容。

在以下示例中,远程 id 模式为 article-<id>,其中 <id> 由读取器提供的数据 id 替换。为了检查内容是否存在,我使用 Ibexa 提供的 ContentService 服务。

该步骤作为匿名函数添加,有 3 种返回值类型

  • 当步骤返回 false 时,数据将被丢弃。
  • 当步骤返回一个 ContentCreateStructure 时,数据将被保存到一个新的 Ibexa 内容中。
  • 当步骤返回ContentUpdateStructure时,现有Ibexa内容将通过覆盖数据中定义的所有字段来更新。

对于新内容,您必须提供一个或多个“父位置ID”,作为ContentCreateStructure构造函数的第三个参数。

在这个例子中,我添加了一个新的文件夹来存储所有文章。

要获取父Ibexa内容的ID,请转到管理员UI,选择未来的父内容,点击“详细信息”标签,并像这样读取“位置ID”

parent folder

注意:最佳实践是将此父ID定义在您的parameters.yml文件或每个执行环境的.env.local文件中。

// In your DataflowType

use CodeRhapsodie\EzDataflowBundle\Factory\ContentStructureFactory;
use CodeRhapsodie\EzDataflowBundle\Writer\ContentWriter;
use CodeRhapsodie\DataflowBundle\DataflowType\AbstractDataflowType;
[...]

class MyDataflowType extends AbstractDataflowType
{
    //[...]
    /**
     * @var ContentWriter
     */
    private $contentWriter;

    /**
     * @var ContentStructureFactory
     */
    private $contentStructureFactory;

    public function __construct(ContentWriter $contentWriter, ContentStructureFactory $contentStructureFactory)
    {
        $this->contentWriter = $contentWriter;
        $this->contentStructureFactory = $contentStructureFactory;
    }
    //[...]
    protected function buildDataflow(DataflowBuilder $builder, array $options): void
    {
        //[...]
        $builder->addStep(function ($data) {
            if (!isset($data['id'])) {
                return false;
            }

            $remoteId = sprintf('article-%d', $data['id']);
            unset($data['id']);

            return $this->contentStructureFactory->transform(
                    $data,
                    $remoteId,
                    'eng-GB',
                    'article2',
                    54, //Parent location id
                    ContentStructureFactoryInterface::MODE_INSERT_OR_UPDATE //Optional value. Other choice : ContentStructureFactoryInterface::MODE_INSERT_ONLY or ContentStructureFactoryInterface::MODE_UPDATE_ONLY
                );
        });
        // If you want the writer log
        $this->contentWriter->setLogger($this->logger);
        $builder->addWriter($this->contentWriter);
    }
}

此示例使用ContentStructureFactory来检查内容是否存在,并返回传递给内容编写器的适当ContentStrucure

使用NotModifiedContentFilter

在更新内容时,您可能想忽略更新不会导致字段值实际更改的内容。在这种情况下,您可以将NotModifiedContentFilter添加为您的步骤之一。

// In your DataflowType
public function __construct(NotModifiedContentFilter $notModifiedContentFilter)
{
    $this->notModifiedContentFilter = $notModifiedContentFilter;
}

//[...]
protected function buildDataflow(DataflowBuilder $builder, array $options): void
{
    //[...]
    // If you want the filter log
    $this->notModifiedContentFilter->setLogger($this->logger);
    $builder->addStep($this->notModifiedContentFilter);
    //[...]
}

此过滤器将接收到的ContentUpdateStructure中的每个字段值与现有内容对象的字段值进行比较。如果所有值都相同,则此过滤器将返回false,否则将按原样返回ContentUpdateStructure

并非所有字段类型都受此过滤器支持。如果字段类型不受支持,则假设值不同。如果您的数据流处理包含不受支持字段类型的内容类型,则最好根本不使用NotModifiedContentFilter,以防止不必要的开销。

支持的字段类型

  • ezstring
  • ezauthor
  • ezboolean
  • ezcountry
  • ezdate
  • ezdatetime
  • ezemail
  • ezfloat
  • ezisbn
  • ezobjectrelation
  • ezobjectrelationlist
  • ezkeyword
  • ezselection
  • eztext
  • eztime
  • eztags
  • novaseometas
  • ezurl
  • ezmatrix
  • ezgmaplocation
  • ezrichtext

添加自定义字段比较器

如果您想支持某种字段类型,只需创建自己的比较器。

<?php

use CodeRhapsodie\EzDataflowBundle\Core\FieldComparator\AbstractFieldComparator;
use Ibexa\Core\FieldType\Value;
//[...]

class MyFieldComparator extends AbstractFieldComparator
{
    //[...]
    protected function compareValues(Value $currentValue, Value $newValue): bool
    {
        // Return true if values are identical, false if values are different.
    }
}
# Service declaration
App\FieldComparator\MyFieldComparator:
  parent: 'CodeRhapsodie\EzDataflowBundle\Core\FieldComparator\AbstractFieldComparator'
  tags:
    - { name: 'coderhapsodie.ezdataflow.field_comparator', fieldType: 'my_field_type_identifier' }

管理员UI

访问eZ Dataflow UI

您可以从Ibexa管理员后台办公室访问eZ Dataflow管理UI。

Admin menu

  1. 点击“管理员”
  2. 点击“eZ Dataflow”

计划的数据流列表

当您访问eZ Dataflow管理UI时,您会在这里

Scheduled dataflow list

  1. 计划的数据流列表
  2. 添加新计划数据流的按钮
  3. 每个计划数据流可用的工具。从左到右依次为
    1. 显示此数据流计划的记录
    2. 编辑此数据流计划
    3. 启用/禁用此数据流计划
    4. 删除此数据流计划

注意:您可以为任何给定数据流定义多个计划。

添加新计划

转到eZ Dataflow管理员,并单击橙色加号按钮。

在新弹出窗口中填写字段

Add a new schedule

  1. 输入数据流计划名称
  2. 选择数据流类型。列表会自动从具有coderhapsodie.dataflow.type标签的Symfony服务列表中生成。如果您的数据流类型不存在,请检查配置
  3. 在此处输入数据流选项。基本预期格式:每行一个选项,选项名和值用: 分隔。对于更复杂选项,支持整个YAML格式。
  4. 在此处输入频率。值必须与PHP strtotime函数兼容。
  5. 选择第一个工作的日期和时间。
  6. 检查是否要运行此数据流。

最后,单击“创建”按钮。

读取历史记录

当您在eZ Dataflow管理UI中单击“历史记录”标签时,将显示所有配置和执行的数据流作业历史记录。

History list

  1. 历史列表
  2. 此列显示已处理的对象数量。
  3. 单击问号可显示作业详情。

一个预定作业的详情

Job execution details

一次性作业

如果您不想定期运行数据流,您可以在您想要的日期和时间添加单次执行。

转到 eZ Dataflow 管理界面并单击“一次性”标签。

Oneshot list

  1. 此按钮允许您定义一次性作业(见下文)。
  2. 此列显示已处理的对象数量。
  3. 单击问号可显示作业详情。

一次性作业的详情

onshot details

这里作业已失败。

添加一次性作业

转到 eZ Dataflow 管理界面并单击“一次性”标签。单击橙色加号按钮打开添加弹出窗口。

The add one-shot popin

  1. 输入数据流作业名称
  2. 选择数据流类型。列表会自动从具有coderhapsodie.dataflow.type标签的Symfony服务列表中生成。如果您的数据流类型不存在,请检查配置
  3. 在此处输入数据流选项。基本预期格式:每行一个选项,选项名和值用: 分隔。对于更复杂选项,支持整个YAML格式。
  4. 选择第一个工作的日期和时间。

最后,单击“创建”按钮。

权限

如果非管理员用户需要仅对数据流接口的只读访问,请在其角色中添加“设置/管理”和“eZ Dataflow/查看”策略。

问题和功能请求

请在此处报告问题和请求功能:https://github.com/code-rhapsodie/ezdataflow-bundle/issues

贡献

欢迎贡献。请参阅CONTRIBUTING.md以获取详细信息。感谢所有已贡献者

许可

此软件包在MIT许可下授权。