【问题标题】:How to override existing field in Siteorigin?如何覆盖 Siteorigin 中的现有字段?
【发布时间】:2018-11-01 18:52:37
【问题描述】:

我想为现有字段类型 color 创建一个自定义字段,这是 Siteorigin 小部件包中的默认值。基本上,我需要为 color 字段类型创建自己的 UI 和后端逻辑。

由于这个字段用在很多地方,如果我可以直接覆盖字段类型,它将自动在每个地方工作。

我搜索了很多次,还挖掘了小部件捆绑包和 SO 本身的源代码,但找不到我需要的东西,即使我尝试以 0 优先级(最高)加载我的字段文件夹但没有不工作。它仍然显示默认的颜色字段类型。

谁能给我指出一些操作或过滤器,以便我可以取消注册并使用相同类型的color 重新注册?或者是否有其他可能的解决方法?


更新

我的问题焦点是 Siteorigin Widgets Bundle Plugin

我不想只覆盖任何样式变量,而是想覆盖现有字段。经过一番研究,我发现了 2 个可用于覆盖现有字段的过滤器:

// Give other plugins a way to modify this form.
$form_options = apply_filters( 'siteorigin_widgets_form_options', $form_options, $this );
$form_options = apply_filters( 'siteorigin_widgets_form_options_' . $this->id_base, $form_options, $this );

这两个过滤器在类SiteOrigin_Widget中的方法form_options()中被调用,但是这个方法是这样调用的:

public function form( $instance, $form_type = 'widget' ) {

    if( $form_type == 'widget' ) {
        if( empty( $this->form_options ) ) {
            $this->form_options = $this->form_options();
        }
        $form_options = $this->form_options;
    }

...
...

}

但看起来$this->form_options 永远不会为空,因此,方法$this->form_options() 永远不会被调用,这反过来又不会应用过滤器siteorigin_widgets_form_optionssiteorigin_widgets_form_options_<id_base>

因此,通过这种方法,我修改表单字段的机会变为zero

我基本上需要的是例如。有一个现有字段color,我还有另一个自定义字段adv-color。现在,挑战是将color 字段的所有实例覆盖为adv-color,因此该字段的每个实例都被覆盖。但是,这仍然是一个希望。

如果我的方法有误,或者有其他方法可以解决这个问题,请告诉我。示例非常值得期待。

【问题讨论】:

  • SiteOrigin 是一家公司,因此很难确定您具体指的是哪个插件/小部件。你能提供一个特定插件的链接吗?并且 - 如果它是“Widgets Bundle”(您所说的),那么您要问的具体是哪个小部件?
  • @cale_b 对不起,我的意思是 Siteorigin Widgets Bundle Plugin。
  • 为什么要覆盖现有的字段?我对这个问题的第一个版本的解决方案覆盖了color generated。覆盖小部件控件中的颜色字段与覆盖小部件渲染时输出的颜色 value 有什么区别?

标签: wordpress siteorigin


【解决方案1】:

谁能给我指出一些操作或过滤器,以便我可以 注销并重新注册同类型color?或者如果有其他 可以解决吗?

我看不到取消注册和重新注册color 字段类型(或生成器)的方法。

但是,如果您想自定义字段的 UI(或者甚至完全改变其外观),您可以创建一个 PHP class 来扩展以下 classes 之一: SiteOrigin_Widget_Field_BaseSiteOrigin_Widget_Field_Text_Input_BaseSiteOrigin_Widget_Field_Color。请看下面的简单示例:

// File: class-my-siteorigin-widget-field-color.php
class My_SiteOrigin_Widget_Field_Color extends SiteOrigin_Widget_Field_Color {

    public function enqueue_scripts() {
        // Enqueues custom CSS and/or JS files, if any.

        wp_enqueue_script( 'my-script', 'path/to/file.js', [ 'jquery' ], '20180601' );
        wp_enqueue_style( 'my-custom-stylesheet', 'path/to/file.css', [], '20180601' );
    }

    // Here you can modify the field's UI to your liking. Even a totally new UI.
    protected function render_field( $value, $instance ) {
        ?>
        <b>Text before</b>
        <input type="<?php echo esc_attr( $this->input_type ) ?>"
               name="<?php echo esc_attr( $this->element_name ) ?>"
               id="<?php echo esc_attr( $this->element_id ) ?>"
                 value="<?php echo esc_attr( $value ) ?>"
                 <?php $this->render_data_attributes( $this->get_input_data_attributes() ) ?>
                 <?php $this->render_CSS_classes( $this->get_input_classes() ) ?>
            <?php if ( ! empty( $this->placeholder ) ) echo 'placeholder="' . esc_attr( $this->placeholder ) . '"' ?>
            <?php if( ! empty( $this->readonly ) ) echo 'readonly' ?> />
        <i>Text after</i>
        <?php
    }

    // See `SiteOrigin_Widget_Field_Base` for all the properties and methods you
    // can extend. See also `SiteOrigin_Widget_Field_Text_Input_Base`, which is
    // being extended by `SiteOrigin_Widget_Field_Color`.
}

然后,您应该在 WordPress 中的 init 挂钩中/期间加载 class示例:

add_action( 'init', function(){
    require_once __DIR__ . '/includes/class-my-siteorigin-widget-field-color.php';
} );

然后,要强制color 字段使用自定义class(上图),请将class 名称​​前缀 添加到$prefixes array 下面:

add_filter( 'siteorigin_widgets_field_class_prefixes', function( $prefixes ){
    return array_merge( [ 'My_SiteOrigin_Widget_Field_' ], $prefixes );
} );

很遗憾,您无法从class 列表中删除unsetSiteOrigin_Widget_Field_Color,因为上述过滤器只允许您过滤class 名称​​前缀

但在上面的示例回调中,自定义 My_SiteOrigin_Widget_Field_Color 将首先被 SiteOrigin Widgets Bundle 插件“看到”;因此,color 字段将使用自定义 class 代替默认字段 - 即 SiteOrigin_Widget_Field_Color

有关这方面的更多详细信息,请参阅 SiteOrigin_Widget_Field_Factory::get_class_prefixes() 和整个 SiteOrigin_Widget_Field_Factory 源代码。还有SiteOrigin_Widget::form()

另见:

更新

但看起来$this-&gt;form_options 永远不会为空,因此,方法 $this-&gt;form_options() 永远不会被调用,这反过来又不会应用 过滤器siteorigin_widgets_form_optionssiteorigin_widgets_form_options_&lt;id_base&gt;

因此,我修改表单字段的机会变成了zero 这种方法。

以下示例可能对您有所帮助:(或者更确切地说,它对我很有效)

// Extends the fields for the Button widget.
// @see SiteOrigin_Widget_Button_Widget::get_widget_form()
// @see SiteOrigin_Widget::form_options()
add_filter( 'siteorigin_widgets_form_options_sow-button', function( $form_options, $widget ){
    if ( isset( $form_options['button_icon'] ) ) {
        // `icon_color` is an existing/built-in field for the Button widget. So
        // in this example, we change the `label` from 'Icon color' to 'Icon
        // default color'.
        $form_options['button_icon']['fields']['icon_color']['label'] = 'Icon default color';

        // Or you could completely override the field:
        /*
        $form_options['button_icon']['fields']['icon_color'] = [
            'type'  => 'custom_type_here',
            'label' => 'Icon color',
        ];
        */

        // And here, we add a new field: A color for the button's `hover` state.
        $form_options['button_icon']['fields']['icon_hover_color'] = [
            'type'  => 'color',
            'label' => 'Icon hover color',
        ];
    }

    return $form_options;
}, 10, 2 );

// Callback to handle the `icon_hover_color`.
add_action( 'siteorigin_widgets_after_widget_sow-button', function( $instance, $widget ){
    if ( isset( $instance['button_icon'], $instance['button_icon']['icon_hover_color'] ) ) {
        $selector = $widget->is_preview( $instance ) ?
            '.so-widget-sow-button' : '#' . $widget->id;
        ?>
            <style>
                <?= $selector ?> a:hover .sow-icon-fontawesome {
                    color: <?= $instance['button_icon']['icon_hover_color'] ?> !important;
                }
            </style>
        <?php
    }
}, 10, 2 );

但是,即使您将color 字段设置为其他type(例如adv_color),您仍然需要创建适当的PHP class,然后添加class 名称前缀通过siteorigin_widgets_field_class_prefixes钩子。

【讨论】:

  • 是的,我明白你的意思。让我试试这个。谢谢你的回答。
  • 看起来这是一个很好的解决方法。现在我想知道,为什么即使是 Siteorigin Widgets Bundle 的开发人员也曾经制作过这些过滤器 'siteorigin_widgets_form_options''siteorigin_widgets_form_options_' . $this-&gt;id_base。甚至他们在上面评论道:“给其他插件一个修改这个表单的方法。”。从字面上看,它们不起作用。这是荒唐的。无论如何,您的回答确实帮助了我。谢谢。
  • 实际上,过滤器确实有效。请参阅更新答案中的示例。
【解决方案2】:

(注意:此答案适用于question as originally asked。在发布此答案后,问题已被修改,因此下面的答案可能看起来不是当前状态下问题的正确答案。) em>

SiteOrigin Widget Bundle 带有各种各样的小部件。

每个小部件都使用LESS 变量编译它自己的css。

由于您可以为每个小部件显式更改颜色,因此这些变量存储在数据库中,并为每个单独的小部件单独检索,然后编译成特定于小部件的 CSS 文件。这发生在小部件的“保存”时,CSS 被缓存 7 天。

为了覆盖这些小部件的变量,您有几个不同的过滤器可供选择(请参阅siteorigin-widget.class.php 插件文件,get_instance_css 方法,从第 816 行开始查看执行此操作的代码) .仅供参考,你会想要在这个级别上做,因为这是所有单个小部件的“基础”类。

过滤器 1:

$vars = apply_filters( 'siteorigin_widgets_less_variables_' . $this->id_base, $this->get_less_variables( $instance ), $instance, $this );

这将是一个理想的地方,因为$vars 是一个包含所有已定义颜色的数组,您可以轻松地覆盖任何您喜欢的颜色。 然而,问题是这个过滤器很难利用,因为它会在小部件的id_base 中烘焙,这会产生像siteorigin_widgets_less_variables_sow-accordion 这样的过滤器标签 - 但是,理论上你可以设置列出一长串过滤器,每个小部件一个过滤器,它们都通过相同的功能运行。

过滤器 2:
紧随其后有一个过滤器,但是 LESS 变量已经“写入”到 LESS 中:

$less = apply_filters( 'siteorigin_widgets_styles', $less, $this->widget_class, $instance );

这是需要使用的过滤器,但您需要知道要替换的 LESS 变量名称。该列表(至少其中一些)是:

$vars = ‌array (
  'heading_background_color'       => '',
  'heading_background_hover_color' => '',
  'title_color'                    => '',
  'title_hover_color'              => '',
  'heading_border_color'           => '',
  'heading_border_hover_color'     => '',
  'heading_border_width'           => '',
  'has_heading_border_width'       => '',
  'panels_background_color'        => '',
  'panels_font_color'              => '',
  'panels_border_color'            => '',
  'panels_border_width'            => '',
  'has_panels_border_width'        => '',
  'panels_margin_bottom'           => '',
}

构建解决方案:
有了这些信息,我们可以像这样应用过滤器:

function my_siteorigin_override_less( $less ) {
    // you'll need to load your override colors here.  that is outside the scope of this question / answer
    $my_colors = array(
      'heading_background_color'       => '#fff',
      'heading_background_hover_color' => '#ff0',
      'title_color'                    => '#000'
      // any other colors you want to include / override....
    );

    foreach( $my_colors as $name => $value ) {
        // Ignore empty string, false and null values (but keep '0')
        if( ! empty( $value ) ) {
            $less = preg_replace('/\@'.preg_quote($name).' *\:.*?;/', '@'.$name.': '.$value.';', $less);
        }
    }

    return $less;
}

add_filter( 'siteorigin_widgets_styles', 'my_siteorigin_override_less' );

上面的代码已经过测试,证明可以工作。

注意事项:
SiteOrigin “缓存”它构建的 CSS 7 天。这意味着如果您已经设置了小部件,并且您更改了默认颜色,那么在以某种方式清除缓存之前,这些更改将不会反映。

SiteOrigin 代码中有一个实用方法,您可以在需要时使用它来“清除”缓存。我建议您随时执行以下操作,“默认”颜色被保存/更新:

if ( is_callable( 'SiteOrigin_Widget', 'clear_file_cache' ) ) {
    // pass TRUE to force delete
    SiteOrigin_Widget::clear_file_cache( TRUE );
}

【讨论】:

  • 感谢您的回复,这个问题可能会让您感到困惑,实际上我的问题是通过我的自定义字段覆盖现有字段,而不仅仅是样式及其变量。我已经更新了问题以便更好地理解。希望这可以更好地澄清我的问题。
  • 我在这个答案中投入了 的工作,它完全准确地回答了your question as asked when I answered。您的编辑完全改变了问题的性质。
  • 是的,我必须同意。我认为@SukantaPaul 需要重新阅读How to Ask。提出不好的问题不仅会降低你得到答案的可能性,还会浪费其他人的时间。
  • 如果我的问题引起了误解,我深表歉意。我想“为颜色字段类型创建我自己的 UI 和后端逻辑”和“操作或过滤器,以便我可以使用相同类型的颜色注销和重新注册”明确要求我想用完全是我自己的字段类型。
  • @ThallerThanYall 这是否意味着我不会再得到任何人的帮助?但我试图指定我要覆盖“字段类型”,请查看我的最后评论。
猜你喜欢
  • 2021-03-25
  • 1970-01-01
  • 2011-10-17
  • 1970-01-01
  • 1970-01-01
  • 2015-11-23
  • 2021-10-19
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多