如何覆盖 Siteorigin 中的现有字段?
How to override existing field in Siteorigin?
我想为现有字段类型 color
创建一个自定义字段,这是 Siteorigin 小部件包的默认设置。基本上,我需要为 color
字段类型创建自己的 UI 和后端逻辑。
由于这个字段在很多地方都用到,如果我能直接覆盖字段类型,就会自动在每个地方都起作用。
我搜索了很多次,还深入研究了 widgets bundle 和 SO 本身的源代码,但找不到我需要的东西,甚至我尝试以 0
优先级(最高)加载我的 fields 文件夹) 但没有用。它仍然显示默认颜色字段类型。
任何人都可以指出一些操作或过滤器,以便我可以注销并重新注册相同类型 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 );
这两个过滤器在 class 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_options
和 siteorigin_widgets_form_options_<id_base>
因此,通过这种方法,我修改表单字段的机会变成 zero
。
我基本上需要的是例如。有一个现有字段 color
,我有另一个自定义字段 adv-color
。现在,挑战是将 color
字段的所有实例覆盖为 adv-color
,因此该字段的每个实例都被覆盖。但是,还是有希望的。
如果我的方法有误或者有其他方法可以解决这个问题,请告诉我。示例 is/are 非常期待。
(注意:这个答案是针对 question as originally asked 的。问题是在这个答案发布后修改的,所以下面的答案可能看起来不像是问题的正确答案当前状态。)
SiteOrigin Widget Bundle 带有各种各样的小部件。
每个小部件编译它自己的 css,利用 LESS 个变量。
由于您可以显式更改每个小部件的颜色,因此这些变量存储在数据库中并针对每个单独的小部件单独检索,然后编译到特定于小部件的 CSS 文件中。这发生在小部件的 "Save" 上,CSS 缓存了 7 天。
为了覆盖这些小部件的变量,您有几个不同的过滤器可供选择(参考 siteorigin-widget.class.php
插件文件,get_instance_css
方法,从第 816 行开始查看执行此操作的代码)。仅供参考,你会想在这个级别上这样做,因为这是对所有单个小部件的 "base" class。
过滤器 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 变量已经 "written" 进入 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 "caches" CSS 它构建了 7 天。这意味着如果您已经设置了小部件,并且更改了默认颜色,则在以某种方式清除缓存之前,更改不会反映出来。
SiteOrigin 代码中有一个实用方法,您可以在需要时使用它 "purge" 缓存。我建议您随时执行以下操作 "default" 颜色被保存/更新:
if ( is_callable( 'SiteOrigin_Widget', 'clear_file_cache' ) ) {
// pass TRUE to force delete
SiteOrigin_Widget::clear_file_cache( TRUE );
}
Can anybody point me to some actions or filters, so that, I can
de-register and re-register with the same type color
? Or if any other
workaround possible?
我没有找到注销和重新注册 color
字段 type(或生成器)的方法。
但是,如果您想自定义字段的 UI(甚至完全改变它的外观),您可以创建一个 PHP class
扩展了这些 class
之一:SiteOrigin_Widget_Field_Base
、SiteOrigin_Widget_Field_Text_Input_Base
或 SiteOrigin_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 中加载 class
in/during init
挂钩。 示例:
add_action( 'init', function(){
require_once __DIR__ . '/includes/class-my-siteorigin-widget-field-color.php';
} );
然后,要强制 color
字段使用自定义 class
(如上),将 class
名称 prefix 添加到$prefixes
array
下面:
add_filter( 'siteorigin_widgets_field_class_prefixes', function( $prefixes ){
return array_merge( [ 'My_SiteOrigin_Widget_Field_' ], $prefixes );
} );
很遗憾,您无法从 class
列表中 unset
或删除 SiteOrigin_Widget_Field_Color
,因为以上过滤器只允许您过滤 class
名称 前缀.
但在上面的示例回调中,自定义 My_SiteOrigin_Widget_Field_Color
将首先由 SiteOrigin Widgets Bundle 插件 "seen";因此,color
字段将使用自定义 class
代替默认字段——即 SiteOrigin_Widget_Field_Color
.
有关详细信息,请参阅 SiteOrigin_Widget_Field_Factory::get_class_prefixes()
and the entire SiteOrigin_Widget_Field_Factory
source code. And SiteOrigin_Widget::form()
。
另请参阅:
更新
But it looks like $this->form_options
is never empty and so, method
$this->form_options()
is never called which in turn never applies the
filters siteorigin_widgets_form_options
and
siteorigin_widgets_form_options_<id_base>
And thus, my chance of modifying the form fields becomes zero
with
this approach.
以下示例可能对您有所帮助:(或者更确切地说,它对我来说效果很好)
// 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
然后通过 siteorigin_widgets_field_class_prefixes
挂钩添加 class
名称 prefix。
我想为现有字段类型 color
创建一个自定义字段,这是 Siteorigin 小部件包的默认设置。基本上,我需要为 color
字段类型创建自己的 UI 和后端逻辑。
由于这个字段在很多地方都用到,如果我能直接覆盖字段类型,就会自动在每个地方都起作用。
我搜索了很多次,还深入研究了 widgets bundle 和 SO 本身的源代码,但找不到我需要的东西,甚至我尝试以 0
优先级(最高)加载我的 fields 文件夹) 但没有用。它仍然显示默认颜色字段类型。
任何人都可以指出一些操作或过滤器,以便我可以注销并重新注册相同类型 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 );
这两个过滤器在 class 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_options
和 siteorigin_widgets_form_options_<id_base>
因此,通过这种方法,我修改表单字段的机会变成 zero
。
我基本上需要的是例如。有一个现有字段 color
,我有另一个自定义字段 adv-color
。现在,挑战是将 color
字段的所有实例覆盖为 adv-color
,因此该字段的每个实例都被覆盖。但是,还是有希望的。
如果我的方法有误或者有其他方法可以解决这个问题,请告诉我。示例 is/are 非常期待。
(注意:这个答案是针对 question as originally asked 的。问题是在这个答案发布后修改的,所以下面的答案可能看起来不像是问题的正确答案当前状态。)
SiteOrigin Widget Bundle 带有各种各样的小部件。
每个小部件编译它自己的 css,利用 LESS 个变量。
由于您可以显式更改每个小部件的颜色,因此这些变量存储在数据库中并针对每个单独的小部件单独检索,然后编译到特定于小部件的 CSS 文件中。这发生在小部件的 "Save" 上,CSS 缓存了 7 天。
为了覆盖这些小部件的变量,您有几个不同的过滤器可供选择(参考 siteorigin-widget.class.php
插件文件,get_instance_css
方法,从第 816 行开始查看执行此操作的代码)。仅供参考,你会想在这个级别上这样做,因为这是对所有单个小部件的 "base" class。
过滤器 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 变量已经 "written" 进入 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 "caches" CSS 它构建了 7 天。这意味着如果您已经设置了小部件,并且更改了默认颜色,则在以某种方式清除缓存之前,更改不会反映出来。
SiteOrigin 代码中有一个实用方法,您可以在需要时使用它 "purge" 缓存。我建议您随时执行以下操作 "default" 颜色被保存/更新:
if ( is_callable( 'SiteOrigin_Widget', 'clear_file_cache' ) ) {
// pass TRUE to force delete
SiteOrigin_Widget::clear_file_cache( TRUE );
}
Can anybody point me to some actions or filters, so that, I can de-register and re-register with the same type
color
? Or if any other workaround possible?
我没有找到注销和重新注册 color
字段 type(或生成器)的方法。
但是,如果您想自定义字段的 UI(甚至完全改变它的外观),您可以创建一个 PHP class
扩展了这些 class
之一:SiteOrigin_Widget_Field_Base
、SiteOrigin_Widget_Field_Text_Input_Base
或 SiteOrigin_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 中加载 class
in/during init
挂钩。 示例:
add_action( 'init', function(){
require_once __DIR__ . '/includes/class-my-siteorigin-widget-field-color.php';
} );
然后,要强制 color
字段使用自定义 class
(如上),将 class
名称 prefix 添加到$prefixes
array
下面:
add_filter( 'siteorigin_widgets_field_class_prefixes', function( $prefixes ){
return array_merge( [ 'My_SiteOrigin_Widget_Field_' ], $prefixes );
} );
很遗憾,您无法从 class
列表中 unset
或删除 SiteOrigin_Widget_Field_Color
,因为以上过滤器只允许您过滤 class
名称 前缀.
但在上面的示例回调中,自定义 My_SiteOrigin_Widget_Field_Color
将首先由 SiteOrigin Widgets Bundle 插件 "seen";因此,color
字段将使用自定义 class
代替默认字段——即 SiteOrigin_Widget_Field_Color
.
有关详细信息,请参阅 SiteOrigin_Widget_Field_Factory::get_class_prefixes()
and the entire SiteOrigin_Widget_Field_Factory
source code. And SiteOrigin_Widget::form()
。
另请参阅:
更新
But it looks like
$this->form_options
is never empty and so, method$this->form_options()
is never called which in turn never applies the filterssiteorigin_widgets_form_options
andsiteorigin_widgets_form_options_<id_base>
And thus, my chance of modifying the form fields becomes
zero
with this approach.
以下示例可能对您有所帮助:(或者更确切地说,它对我来说效果很好)
// 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
然后通过 siteorigin_widgets_field_class_prefixes
挂钩添加 class
名称 prefix。