oxid-esales/smarty-to-twig-converter

将 smarty 模板引擎转换为 twig 的脚本

安装: 31

依赖项: 0

建议者: 1

安全性: 0

星级: 26

关注者: 11

分支: 7

类型:application

v1.0.1 2020-05-20 07:53 UTC

This package is auto-updated.

Last update: 2024-09-19 22:37:50 UTC


README

位于 GitHub 的转换工具可以将现有的 Smarty 模板文件转换为 Twig 语法。此工具除了标准 Smarty 语法外,还调整以处理定制的 OXID 修改和扩展。

安装

克隆仓库

git clone https://github.com/OXID-eSales/smarty-to-twig-converter.git

安装依赖项

cd smarty-to-twig-converter

composer install

使用

convert 命令尝试在一个给定的文件、目录或数据库上修复尽可能多的编码标准问题。

路径和扩展名参数

转换器可以与文件和目录一起工作

php toTwig convert --path=/path/to/dir php toTwig convert --path=/path/to/file

默认情况下,将创建扩展名为 .html.twig 的文件。要指定不同的扩展名,请使用 --ext 参数

php toTwig convert --path=/path/to/dir --ext=.js.twig

数据库和数据库列参数

它还可以与数据库一起工作

php toTwig convert --database="mysql://user:password@localhost/db"

--database 参数获取 数据库 doctrine-like URL。默认情况下,转换器将以下表列转换为

  • oxactions.OXLONGDESC
  • oxactions.OXLONGDESC_1
  • oxactions.OXLONGDESC_2
  • oxactions.OXLONGDESC_3
  • oxcontents.OXCONTENT
  • oxcontents.OXCONTENT_1
  • oxcontents.OXCONTENT_2
  • oxcontents.OXCONTENT_3
  • oxartextends.OXLONGDESC
  • oxartextends.OXLONGDESC_1
  • oxartextends.OXLONGDESC_2
  • oxartextends.OXLONGDESC_3
  • oxcategories.OXLONGDESC
  • oxcategories.OXLONGDESC
  • oxcategories.OXLONGDESC_2
  • oxcategories.OXLONGDESC_3

使用 --database-columns 选项可以让你选择要转换的表列(表列名必须以 table_a.column_b 格式指定,并用逗号分隔)

php toTwig convert --database="..." --database-columns=oxactions.OXLONGDESC,oxcontents.OXCONTENT

您还可以通过 -table_a.column_b 使用黑名单排除不需要的表列

php toTwig convert --database="..." --database-columns=-oxactions.OXLONGDESC_1,-oxcontents.OXCONTENT_1

转换器参数

--converters 选项允许您选择要应用的确切转换器(转换器名称必须用逗号分隔)

php toTwig convert --path=/path/to/dir --ext=.html.twig --converters=for,if,misc

如果您觉得这样做更方便,还可以使用 -name 黑名单排除不需要的转换器

php toTwig convert --path=/path/to/dir --ext=.html.twig --converters=-for,-if

dry-run、verbose 和 diff 参数

--dry-run--verbose--diff 的组合将显示提议的更改摘要,但不会修改您的文件。

默认情况下,所有转换器都会应用。

--dry-run 选项显示需要修复的文件,但实际上不会修改它们

php toTwig convert --path=/path/to/code --ext=.html.twig --dry-run

config-path 参数

除了构建长的命令行之外,还可以注入 PHP 配置代码。主目录中包含两个示例文件:config_file.phpconfig_database.php。要包含配置文件,请使用 --config-path 参数

php toTwig convert --config-path=config_file.php

配置脚本应返回 toTwig\Config\ConfigInterface 实例。可以使用 toTwig\Config\Config::create() 静态方法创建。

已知问题

  • 在Twig中默认所有变量都会被转义。一些变量应该使用|raw过滤器进行过滤以避免这种情况。这意味着所有模板、HTML代码和包含不安全字符(如< > $ &)的字符串都应该在输出之前使用|raw进行过滤。您可以使用网页浏览器的检查工具来检查是否所有必要的变量都被转义。如果您想输出包含模板的变量,而不是使用raw过滤器,可以使用template_from_string函数。更多相关信息请参阅文档

    Smarty

    [{$product->oxarticles__oxtitle->value}]

    转换后的Twig

    {{ product.oxarticles__oxtitle.value }}

    修复后的Twig

    {{ product.oxarticles__oxtitle.value|raw }}
  • 变量作用域。在Twig中,模板中声明的变量作用域由块(如{% block %}{% for %}等)限制。如果变量在块之外使用,则应在块之外声明。

    Smarty

    [{foreach $myColors as $color}]
        <li>[{$color}]</li>
    [{/foreach}]
    [{$color}]

    转换后的Twig

    {% for color in myColors %}
        <li>{{ color }}</li>
    {% endfor %}
    {{ color }}

    修复后的Twig

    {% for color in myColors %}
        <li>{{ color }}</li>
    {% endfor %}
    {{ myColors|last }}
  • 重新声明块在Twig中是不允许的。您必须在每个模板中为每个块使用唯一的名称。

    Smarty

    [{block name="foo"}]
        ...
    [{/block}]
    [{block name="foo"}]
        ...
    [{/block}]

    转换后的Twig

    {% block foo %}
        ...
    {% endblock %}
    {% block foo %}
        ...
    {% endblock %}

    修复后的Twig

    {% block foo_A %}
        ...
    {% endblock %}
    {% block foo_B %}
        ...
    {% endblock %}
  • 访问数组项$myArray.$itemIndex应手动转换为myArray[itemIndex]

    Smarty

    [{$myArray.$itemIndex}]

    转换后的Twig

    {{ myArray.$itemIndex }}

    修复后的Twig

    {{ myArray[itemIndex] }}
  • 在模板中使用正则表达式字符串——在如此复杂的案例中,工具可能会中断或工作不正确,因此手动复制粘贴正则表达式更安全。

    Smarty

    [{birthDate|regex_replace:"/^([0-9]{4})[-]/":""|regex_replace:"/[-]([0-9]{1,2})$/":""}]

    转换后的Twig

    {{ birthDate|regex_replace("/^([0-9]{4)})[-]/":""|regex_replace("/[-]([0-9]{1,) 2})$/":"" }}

    修复后的Twig

    {{ birthDate|regex_replace("/^([0-9]{4})[-]/","")|regex_replace("/[-]([0-9]{1,2})$/","") }}
  • [{section}] - loop是触发不同行为的数组或整数。工具无法检测变量类型,因此您需要检查每个loop中使用的内容。

    Smarty

    [{section name="month" start=1 loop=13}]
        [{$smarty.section.month.index}]
    [{/section}]
    [{section name=customer loop=$custid}]
        id: [{$custid[customer]}]<br />
    [{/section}]

    转换后的Twig

    {% for month in 1..13 %}
        {{ loop.index0 }}
    {% endfor %}
    {% for customer in 0..$custid %}
        id: {{ custid[customer] }}<br />
    {% endfor %}

    修复后的Twig

    {% for month in 1..12 %}
        {{ loop.index0 }}
    {% endfor %}
    {% for customer in custid %}
        id: {{ customer }}<br />
    {% endfor %}
  • 字符串连接——工具在处理字符串的开启和关闭时存在问题。在字符串中使用Smarty变量可能会导致转换器失败。Twig不支持这种类型的连接。您应该在拼接变量的地方检查并使用Twig的~而不是字符串中的变量。在转换后的模板中,您应该寻找类似$var_name的模式。

    Smarty

    [{assign var="sUrl" value="http://www.example.com?aid=`$sAccountId`&wid=`$sWidgetId`&csize=20&start=0"}]
    [{assign var="divId" value=oxStateDiv_$stateSelectName}]

    转换后的Twig

    {% set sUrl = "http://www.example.com?aid=`$sAccountId`&wid=`$sWidgetId`&csize=20&start=0" %}
    {% set divId = oxStateDiv_$stateSelectName %}

    修复后的Twig

    {% set sUrl = "http://www.example.com?aid=" ~ sAccountId ~ "&wid=" ~ sWidgetId ~ "&csize=20&start=0" %}
    {% set divId = "oxStateDiv_" ~ stateSelectName %}
  • $符号并不总是从变量中移除。有时当表达式过于复杂时,转换器将不会从变量名中移除$符号。转换后,您应该检查模板中的$符号。

    Smarty

    [{$oViewConf->getImageUrl($sEmailLogo, false)}]

    转换后的Twig

    {{ oViewConf.getImageUrl($sEmailLogo, false) }}

    修复后的Twig

    {{ oViewConf.getImageUrl(sEmailLogo, false) }}
  • Twig提供了轻松访问循环的第一个元素的途径。您可以使用loop.index0或当前的迭代loop.index来代替变量的索引元素。转换器不处理如$smarty.section.arg之类的结构。更多相关信息请参阅Twig 'for' 文档

    Smarty

    [{if $review->getRating() >= $smarty.section.starRatings.iteration}]

    转换后的Twig

    {% if review.getRating() >= smarty.section.starRatings.iteration %}

    修复后的Twig

    {% if review.getRating() >= loop.index %}
  • 在某些地方,访问全局变量的方式需要调整。在转换后的代码中寻找单词smarty并将其替换为twig

    Smarty

    [{$smarty.capture.loginErrors}]

    转换后的Twig

    {{ smarty.capture.loginErrors }}

    修复后的Twig

    {{ twig.capture.loginErrors }}
  • 在Smarty和Twig中,属性访问方式不同,有时需要手动修复。如果没有定义魔术isset,则必须显式调用魔术getter。此外,如果您想访问类属性而不调用getter,则必须使用类似数组的语法。

    Smarty

    [{foreach from=$cattree->aList item=pcat}]
        [{pcat.val}]

    转换后的Twig

    {% for pcat in cattree.aList %}
        {{ pcat.val }}

    修复后的Twig

    {% for pcat in cattree.__get('aList') %}
        {{ pcat['val'] }}
  • 转换器并不总是转换逻辑运算符如||&&,如果它们没有用空格分隔。需要手动将||改为or,将&&改为and

    Smarty

    [{if $product->isNotBuyable()||($aVariantSelections&&$aVariantSelections.selections)||$product->hasMdVariants()}]

    转换后的Twig

    {% if product.isNotBuyable()||(aVariantSelections&&$aVariantSelections.selections) or product.hasMdVariants() %}

    修复后的Twig

    {% if product.isNotBuyable() or (aVariantSelections and aVariantSelections.selections) or product.hasMdVariants() %}
  • 如果您从模板中访问请求变量,请考虑重构任何进行此操作的模板。如果不可能,请使用与Twig引擎一起提供的函数get_global_cookieget_global_get。如果您需要访问其他请求变量,您将需要自行扩展这些函数之一。

    Smarty

    [{if $smarty.get.plain == '1'}] popup[{/if}]

    转换后的Twig

    {% if smarty.get.plain == '1' %} popup{% endif %}

    修复后的Twig

    {% if get_global_get('plain') == '1' %} popup{% endif %}
  • 您可能需要手动检查模板文件中的逻辑。某些地方将需要使用is same as比较,它使用PHP的===而不是==。这可能是在检查变量是否设置、是否包含信息、是否为0或是否为null时必要的。检查不存在的(null)属性存在问题。例如,我们想检查不存在属性oxarticles__oxunitname的值。Twig使用isset来检查此属性是否存在,如果不存在,则Twig会假设属性名是函数名,并尝试调用它。

    Smarty

    [{if $_sSelectionHashCollection}]
        [{assign var="_sSelectionHashCollection" value=$_sSelectionHashCollection|cat:","}]
    [{/if}]

    转换后的Twig

    {% if _sSelectionHashCollection %}
        {% set _sSelectionHashCollection = _sSelectionHashCollection|cat(",") %}
    {% endif %}

    修复后的Twig

    {% if _sSelectionHashCollection is not same as("") %}
        {% set _sSelectionHashCollection = _sSelectionHashCollection|cat(",") %}
    {% endif %}

转换的插件和语法片段

以下是插件和语法片段的列表,以及基本示例如何进行转换。请注意,这些示例仅用于展示转换方式,并不涵盖所有可能的情况,如附加参数、块嵌套、重复调用(如计数器和循环函数)等。

核心Smarty

assign > set

转换器名称:assign

Smarty
[{assign var="name" value="Bob"}]

Twig
{% set name = "Bob" %}

block > block

转换器名称:block

Smarty
[{block name="title"}]默认标题[{/block}]

Twig
{% block title %}默认标题{% endblock %}

capture > set

转换器名称:CaptureConverter

Smarty
[{capture name="foo" append="var"}] bar [{/capture}]

Twig
{% set foo %}{{ var }} bar {% endset %}

注释

转换器名称:comment

Smarty
[{* foo *}]

Twig
{# foo #}

counter > set

转换器名称:counter

Smarty
[{counter}]

Twig
{% set defaultCounter = ( defaultCounter|default(0) ) + 1 %}

cycle > smarty_cycle

转换器名称:cycle

Smarty
[{cycle values="val1,val2,val3"}]

Twig
{{ smarty_cycle(["val1", "val2", "val3"]) }}

foreach > for

转换器名称:for

Smarty
[{foreach $myColors as $color}]foo[{/foreach}]

Twig
{% for color in myColors %}foo{% endfor %}

if > if

转换器名称:if

Smarty
[{if !$foo or $foo->bar or $foo|bar:foo["hello"]}]foo[{/if}]

Twig
{% if not foo or foo.bar or foo|bar(foo["hello"]) %}foo{% endif %}

include > include

转换器名称:include

Smarty
[{include file='page_header.tpl'}]

Twig
{% include 'page_header.tpl' %}

insert > include

转换器名称:insert

Smarty
[{insert name="oxid_tracker" title="PRODUCT_DETAILS"|oxmultilangassign product=$oDetailsProduct cpath=$oView->getCatTreePath()}]

Twig
{% include "oxid_tracker" with {title: "PRODUCT_DETAILS"|oxmultilangassign, product: oDetailsProduct, cpath: oView.getCatTreePath()} %}

mailto > mailto

转换器名称:mailto

Smarty
[{mailto address='me@example.com'}]

Twig
{{ mailto('me@example.com') }}

math > core Twig math syntax

转换器名称:math

Smarty
[{math equation="x + y" x=1 y=2}]

Twig
{{ 1 + 2 }}

变量转换

转换器名称:variable

其他

转换器名称:misc

OXID自定义扩展

oxcontent > include_content

转换器名称:oxcontent

Smarty
[{oxcontent ident='oxregisteremail'}]

Twig
{% include_content 'oxregisteremail' %}

oxeval > include(template_from_string())

转换器名称:OxevalConverter

Smarty
[{oxeval var=$variable}]

Twig
{{ include(template_from_string(variable)) }}

oxgetseourl > seo_url

转换器名称:oxgetseourl

Smarty
[{oxgetseourl ident=$oViewConf->getSelfLink()|cat:"cl=basket"}]

Twig
{{ seo_url({ ident: oViewConf.getSelfLink()|cat("cl=basket") }) }}

oxhasrights > hasrights

转换器名称:oxhasrights

Smarty
[{oxhasrights object=$edit readonly=$readonly}]foo[{/oxhasrights}]

Twig
{% hasrights { "object": "edit", "readonly": "readonly", } %}foo{% endhasrights %}

oxid_include_dynamic > include_dynamic

转换器名称:oxid_include_dynamic

Smarty
[{oxid_include_dynamic file="form/formparams.tpl"}]

Twig
{% include_dynamic "form/formparams.tpl" %}

oxid_include_widget > include_widget

转换器名称:oxid_include_widget

Smarty
[[oxid_include_widget cl="oxwCategoryTree" cnid=$oView->getCategoryId() deepLevel=0 noscript=1 nocookie=1]]

Twig
{{ include_widget({ cl: "oxwCategoryTree", cnid: oView.getCategoryId(), deepLevel: 0, noscript: 1, nocookie: 1 }) }}

oxifcontent => ifcontent

转换器名称: oxifcontent

Smarty
[[oxifcontent ident="TOBASKET" object="aObject"]]foo[[/oxifcontent]]

Twig
{% ifcontent ident "TOBASKET" set aObject %}foo{% endifcontent %}

oxinputhelp => include "inputhelp.tpl"

转换器名称: oxinputhelp

Smarty
[[oxinputhelp ident="foo"]]

Twig
{% include "inputhelp.tpl" with {'sHelpId': getSHelpId(foo), 'sHelpText': getSHelpText(foo)} %}

oxmailto => oxmailto

转换器名称: oxmailto

Smarty
[[oxmailto address='me@example.com']]

Twig
{{ mailto('me@example.com') }}

oxmultilang => translate

转换器名称: oxmultilang

Smarty
[[oxmultilang ident="ERROR_404"]]

Twig
{{ translate({ ident: "ERROR_404" }) }}

oxprice => format_price

转换器名称: oxprice

Smarty
[[oxprice price=$basketitem->getUnitPrice() currency=$currency]]

Twig
{{ format_price(basketitem.getUnitPrice(), { currency: currency }) }}

oxscript => script

转换器名称: oxscript

Smarty
[[oxscript include="js/pages/details.min.js" priority=10]]

Twig
{{ script({ include: "js/pages/details.min.js", priority: 10, dynamic: __oxid_include_dynamic }) }}

oxstyle => style

转换器名称: oxstyle

Smarty
[[oxstyle include="css/libs/chosen/chosen.min.css"]]

Twig
{{ style({ include: "css/libs/chosen/chosen.min.css" }) }}

section => for

转换器名称: section

Smarty
[[section name=picRow start=1 loop=10]]foo[[/section]]

Twig
{% for picRow in 1..10 %}foo{% endfor %}

过滤器

运行数据库转换 PHPUnit 测试

CI 注意:要运行数据库转换 PHPUnit 测试,需要 sqlite。您可以通过运行以下命令来安装它

$ sudo apt-get install sqlite3
$ sudo apt-get install php7.2-sqlite

错误和问题

如果您遇到任何错误或问题,请在 https://bugs.oxid-esales.comOXID eShop(所有版本) 部分 Twig 引擎 类别下报告