psmb / newsletter

基于 Fusion 生成通讯

安装 数量: 1,302

依赖项: 0

建议者: 0

安全性: 0

星标: 12

关注者: 5

分支: 8

开放问题: 2

类型:neos-package

v2.5.0 2019-01-03 15:13 UTC

This package is auto-updated.

Last update: 2024-08-26 22:07:00 UTC


README

使用本包,您可以根据 Neos CMS 网站的内容(例如最新文章的摘要)生成通讯。

酷的地方在于,您可以使用 Fusion 渲染这些通讯,这允许您重用任何现有的网站 Fusion 对象,并且具有完全的灵活性。

安装

composer require "psmb/newsletter:@dev"

配置

将以下内容放入您的 Settings.yaml 中

Psmb:
  Newsletter:
    globalSettings:
      senderAddress: 'robot@server.com'
      senderName: 'Your robot'
    subscriptions:
      -
        identifier: daily
        renderer: 'Your.NameSpace:DailyLetterRenderer'
        label: 'Our daily newsletter'
        interval: P1D
      -
        identifier: weekly
        renderer: 'Your.NameSpace:WeeklyLetterRenderer'
        label: 'Our weekly newsletter (In Russian)'
        interval: P1W
        dimensions:
          language: ['ru']
      -
        identifier: handcrafted
        renderer: 'Your.NameSpace:HandcraftedDigestRenderer'
        sendFromUiNodeType: 'Your.NameSpace:HandcraftedDigest'
        label: 'Manually crafted newsletter'
        interval: manual

您还必须在 Settings.yaml 中配置一个 baseUri

Neos:
  Flow:
    http:
      baseUri: 'http://yourdomain.tld/'

在 Psmb.Newsletter.subscriptions 下定义您需要的订阅类型。

您可能还需要配置 SwiftMailer,请参阅其文档了解如何进行配置。

渲染通讯

如前所述,我们完全使用 Fusion 渲染信件,因此定义渲染对象完全取决于您。渲染的入口点是 newsletter = Psmb.Newsletter:SubscriptionCase,因此您可以直接挂钩到 Psmb.Newsletter:SubscriptionCase 来拦截渲染过程。但预期的用法是通过 renderer 设置键(见上文)为每个订阅预设提供不同的渲染器。

然后为每个渲染器定义一个类似以下 Fusion 对象

prototype(Your.NameSpace:WeeklyLetterRenderer) < prototype(Psmb.Newsletter:MailRenderer) {
	subject = 'Our weekly digest'
	body = 'Generate message body. Use your imagination.'

  # You may automatically inline all css styles.
	# body.@process.cssToInline = Psmb.Newsletter:CssToInline {
	#	  cssPath = 'resource://Your.Package/Public/Path/To/Your/Styles.css'
	# }
  # # You may also override these settings, but usually no need to
  # format = 'plaintext' # defaults to 'html'
	# recipientAddress = ${subscriber.email}
	# recipientName = ${subscriber.name}
	# replyToAddress = ${subscription.senderAddress || globalSettings.senderAddress}
	# senderAddress = ${subscription.senderAddress || globalSettings.senderAddress}
	# senderName = ${subscription.senderName || globalSettings.senderName}
}

您将可用以下上下文变量

一个更实用的例子

prototype(Sfi.Site:DigestMail) < prototype(Psmb.Newsletter:MailRenderer) {
    # ElasticSearch used here, but could be a simple FlowQuery as well
    @context.nodes = ${Search.query(site).nodeType('Sfi.Site:News').exactMatch('type', 'ourNews').greaterThan('date', Date.format(Date.subtract(Date.now(), subscription.interval), "Y-m-d\TH:i:sP")).sortDesc('date').execute()}
    @if.notEmpty = ${q(nodes).count() > 0}
    subject = ${Translation.translate('newsletter.digestSubject', null, [], null, 'Sfi.Site')}
    body = Neos.Fusion:Collection {
        collection = ${nodes}
        itemName = 'node'
        itemRenderer = Sfi.Site:DigestArticle
    }
    @process.cssToInline = Psmb.Newsletter:CssToInline {
        cssPath = 'resource://Sfi.Site/Public/built/index.css'
    }
}

prototype(Sfi.Site:DigestArticle) < prototype(Neos.Fusion:Tag) {
    tagName = 'a'
    attributes.href = NodeUri {
        node = ${node}
        absolute = ${true}
    }
    content = ${node.properties.title}
}

提供的 Fusion 对象

要自定义确认邮件,覆盖 Psmb.Newsletter:ConfirmationMailRenderer

渲染订阅插件

插入 Psmb.Newsletter:SubscriptionPlugin nodetype 或手动渲染。

订阅流程如下

  1. 填写注册表单。要求提供姓名和电子邮件,并允许选择可用的订阅计划。
  2. 确认电子邮件。
  3. 编辑订阅选项或通过电子邮件链接取消订阅。

您绝对必须覆盖默认模板,默认模板仅用于演示目的。在 Configuration 中创建一个 Views.yaml 文件。

-
  requestFilter: 'isPackage("Psmb.Newsletter") && isController("Subscription")'
  options:
    templateRootPaths:
      - 'resource://Sfi.Site/Private/Newsletter/Templates/'
      - 'resource://Psmb.Newsletter/Private/Templates'
    partialRootPaths:
      - 'resource://Sfi.Site/Private/Newsletter/Partials/'
      - 'resource://Psmb.Newsletter/Private/Partials/'
    layoutRootPaths:
      - 'resource://Sfi.Site/Private/Newsletter/Layouts/'

发送内容

一旦您设置好订阅的渲染,就是时候发送它们了!有一个 CLI 命令可以做到这一点。

./flow newsletter:send --subscription="daily" 会向所有订阅标识为 "daily" 的订阅者发送通讯。

./flow newsletter:send --interval="P1H" 会找到所有间隔等于 "P1H" 的订阅并向它们发送信件。这对于根据时间间隔设置 cron 任务非常有用。

从 UI 手动发送

image

如果您的 nodetype 继承自 Psmb.Newsletter:NewsletterMixin,您将看到一个新检查器选项卡,您可以通过它发送基于当前文档节点的手动通讯。

为此,您的至少一个订阅预设必须具有 interval: manual。这些预设将出现在检查器视图选择框中。点击发送,该通讯就会发送给所选订阅组的所有订阅者。当前文档节点将作为 documentNodenode 在 Fusion 渲染器中可用。

使用作业队列提高可靠性

本包使用 flowpack/jobqueue 包生成和传递消息。请参阅其文档了解如何通过适当的作业队列实现提高其可靠性。

从 CSV 导入订阅者

创建一个包含您的订阅者数据的 CSV 文件,并将其放在您的服务器上的某个位置。

该文件应具有以下格式

"user@email.com","User Name","subscriptionId1|subscriptionId2"
"user1@email.com","User1 Name","subscriptionId2"

然后运行(文件路径相对于安装根目录)

./flow newsletter:importCsv --filename="test.csv"

这是一个如何从MySQL创建CSV导出的快速示例。

SELECT email, name INTO OUTFILE '/path/test.csv' FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '"' LINES TERMINATED BY '\n' FROM yourTable;

外部数据源

获取订阅者的默认数据源有一个标识符 Repository。它会获取通过默认订阅插件订阅的所有订阅者。

您可以通过Json数据源从外部JSON源获取订阅者。以下是一个示例

Psmb:
  Newsletter:
    subscriptions:
      -
        dataSourceIdentifier: 'Json'
        dataSourceOptions:
          uri: 'http://some.host/some-url'

或者,您可以提供自己的自定义数据源。查看JsonDataSource.php的实现,了解如何做到这一点。

还可以为数据源提供一些额外的参数,这些参数将从节点的其他属性中填充。以下是一个示例NodeTypes.yaml文件

'Psmb.Newsletter:NewsletterMixin':
  abstract: true
  ui:
    inspector:
      tabs:
        newsletter:
          label: i18n
          position: 100
          icon: icon-send
      groups:
        newsletter:
          label: i18n
          tab: newsletter
      views:
        newsletter:
          viewOptions:
            dataSourceAdditionalArguments:
              sampleArgument: 'ClientEval:node.properties.sampleProperty'
  properties:
    sampleProperty:
      type: DateTime
      ui:
        label: 'Subscribers since'
        inspector:
          group: newsletter
          position: 1
          editorOptions:
            format: 'Y-m-d'

然后,dataSourceAdditionalArguments将被传递给数据源。您可以查看Json数据源如何处理它。

致谢

这是我第一个Flow包,没有社区的支持,特别是Christian Müller回答了Slack上成百上千个新手问题,这是不可能实现的。