web-dev-qa-db-ja.com

Wp-admin内のウィジェットに表示される情報に影響を与える方法

最初に、私は明確にしたい - これはCSSの質問ではない。

ウィジェットがwp-admin内、サイドバーまたはページビルダー内でクローズ/オープンモードのときに表示されるデータを変更したい。これはよりよく説明するための画像です。

enter image description here 

私は何かを動的に追加したり、ウィジェットのタイトルから削除したりするためにwidget $ instanceを使用したいと思います。

望ましい結果:
mobile/desktop/bothを示す小さな情報ラベルを追加します。これは、その特定のウィジェット内で選択されたオプションです。

誰か考え?

UPDATE
私はこの質問の解決策にいくらか興味があるので:
@ cjbjソリューションは美しく機能しますが、サイドバーと部分的にのみ機能します。

add_filter ('dynamic_sidebar_params','wpse261042_change_widget_title');
function wpse261042_change_widget_title ($params) {

    $widget_id          = $params[0]['widget_id'];
    $widget_instance    = strrchr ($widget_id, '-');
    $wlen               = strlen ($widget_id);
    $ilen               = strlen ($widget_instance);
    $widget_name        = substr ($widget_id,0,$wlen-$ilen);
    $widget_instance    = substr ($widget_instance,1);

    // get the data
    $widget_instances   = get_option('widget_' . $widget_name);
    $data               = $widget_instances[$widget_instance];
    $use_mobile         = $data['use_mobile'];  // option inside my widget

    if($use_mobile == 'yes') {$string = 'desktop / mobile';} else {$string = 'desktop only';}

    $params[0]['widget_name'] .= $string;
    return $params;
}

ただし、その文字列にHTMLを挿入することはできません(または少なくとも私はできませんでした)。

私は実用的な解決策を見つけた場合は更新されるでしょう。

6
Sagive SEO

バックグラウンド:

dynamic_sidebar_paramsでのフィルタリングがHTMLで機能しない理由は、WordPressが wp_widget_control() 関数のウィジェットの見出しからHTMLを削除するためです。

$widget_title = esc_html( strip_tags( $sidebar_args['widget_name'] ) );

WordPressは wp-admin/js/widgets.js のデフォルトJavaScriptでHTMLも削除します

そのため、カスタマイズされたソリューションがなければ、PHPまたはJavaScriptを使用して目的を達成するためのデフォルトのフィルターまたはオプションはありません。

カスタムPHPソリューション:

wp-admin -> Appearance -> Widgetsでのみ機能し、Customizer -> Widgetsでは機能しないカスタムPHPソリューションが可能です。

WordPressはdynamic_sidebar_paramsフックで wp_widget_control() function (ウィジェット制御UIを生成する)を追加するため、このフィルターフックを使用してオーバーライドできます。ただし、カスタマイザーでは、WordPressは wp_widget_control() function を直接呼び出すため、このソリューションはカスタマイザーに対して機能しません。

ソリューションは次のように機能します(このコードをカスタムプラグインに追加します)。

add_filter( 'dynamic_sidebar_params', 'wpse261042_list_widget_controls_dynamic_sidebar', 20 );
function wpse261042_list_widget_controls_dynamic_sidebar( $params ) {
    global $wp_registered_widgets;
    // we only want this in wp-admin (may need different check to enable page builder)
    if( is_admin() ) {
        if ( is_array( $params ) && is_array( $params[0] ) && $params[0]['id'] !== 'wp_inactive_widgets' ) {
            $widget_id = $params[0]['widget_id'];
            if ( $wp_registered_widgets[$widget_id]['callback'] ===  'wp_widget_control' ) {
                // here we are replacing wp_widget_control() function 
                // with our custom wpse261042_widget_control() function
                $wp_registered_widgets[$widget_id]['callback'] = 'wpse261042_widget_control';
            }
        }
    }
    return $params;
}

function wpse261042_widget_control( $sidebar_args ) {
    // here copy everything from the core wp_widget_control() function
    // and change only the part related to heading as you need 
} 

前にも言ったように、このソリューションはカスタマイザーでは機能せず、コア機能をオーバーライドするため、今後の更新が必要になる可能性が高くなります。

カスタムJavaScriptソリューション(推奨):

幸いなことに、JavaScriptを使用してこの動作をカスタマイズできます。 WordPressは、とにかくJavaScriptでウィジェットコントロールの見出しを更新します。そのためにWordPressはプレースホルダーin-widget-title CSSクラスを保持し、JavaScript CODEのウィジェットtitleフィールド値で更新します。これを操作して目標を達成できます。

関連するコアJSファイル:

まず、WordPressがwp-admin/js/customize-widgets.js(カスタマイザー)で customize-widgets ファイル(wp-admin -> Customize -> Widgetsハンドル付き)をロードし、wp-admin/js/widgets.jsadmin-widgets ファイル(wp-admin -> Appearance -> Widgetsハンドル付き)をロードすることを知っておく必要がありますウィジェットコントロールUI。これらの2つのファイルは、ウィジェットUIマークアップとウィジェット見出しUI操作に対して同様の操作を行いますが、多くの異なることも行います。そのため、JavaScriptベースのソリューションではそれを考慮する必要があります。

カスタマイザーに関する考慮事項:

カスタマイザーは、ページのロード直後にウィジェットUIマークアップをロードせず、代わりに、対応するWidgets -> Sidebarパネルが開いているときにJavaScriptでロードします。そのため、WordPressが読み込まれた後にウィジェットUIを操作する必要があります。たとえば、カスタマイザーCODEはイベントベースであるため、次のCODE行を使用して、適切なタイミングでイベントハンドラーを設定しました。

section.expanded.bind( onExpanded );

また、カスタマイザーはAJAXを使用して変更をすぐにロードしたため、次の行を使用してデータの変更を利用しました。

control.setting.bind( updateTitle );

また、次のコード行でwidget-addedイベントを利用する必要がありました。

$( document ).on( 'widget-added', add_widget );

カスタマイザーとwp-admin -> Appearance -> Widgetsに共通:

上記の両方のJavaScriptファイルは、ウィジェットが更新されるとwidget-updatedイベントをトリガーします。カスタマイザーはAJAXですぐにそれを行いますが、従来のWidget adminは、 Save ボタン。これには次のコード行を使用しました。

$( document ).on( 'widget-updated', modify_widget );

wp-admin -> Appearance -> Widgetsに関する考慮事項:

カスタマイザーとは異なり、従来のWidgets adminはWidget Control UIをPHPでロードするため、UI HTMLを走査して次のような初期変更を行いました。

$( '#widgets-right div.widgets-sortables div.widget' ).each( function() { // code } ); 

カスタムプラグインコード:

以下は、wp-admin -> Appearance -> WidgetsCustomizer -> Widgetsの両方で機能するJavaScriptベースのソリューションを備えた完全なプラグインです。

wpse-widget-control.phpプラグインPHPファイル:

<?php
/**
 *  Plugin Name: Widget Control
 *  Plugin URI: https://wordpress.stackexchange.com/questions/261042/how-to-influence-the-information-displayed-on-widget-inside-wp-admin
 *  Description: Display additional info on Widget Heading in wp-admin & customizer using JS
 *  Author: Fayaz
 *  Version: 1.0
 *  Author URI: http://fmy.me/
 */

    if( is_admin() ) {
        add_action( 'current_screen', 'wpse261042_widget_screen' );
    }

    function wpse261042_widget_screen() {
        $currentScreen = get_current_screen();
        if( $currentScreen->id === 'customize' ) {
            add_action( 'customize_controls_enqueue_scripts', 'wpse261042_customizer_widgets', 99 );
        }
        else if( $currentScreen->id === 'widgets' ) {
            add_action( 'admin_enqueue_scripts', 'wpse261042_admin_widgets', 99 );
        }
    }

    function wpse261042_customizer_widgets() {
        wp_enqueue_script( 'custom-widget-heading', plugin_dir_url( __FILE__ ) . 'custom-widget-heading.js', array( 'jquery', 'customize-widgets' ) );
    }

    function wpse261042_admin_widgets() {
        wp_enqueue_script( 'custom-widget-heading', plugin_dir_url( __FILE__ ) . 'custom-widget-heading.js', array( 'jquery', 'admin-widgets' ) );
    }

custom-widget-heading.js JavaScriptファイル:

(function( wp, $ ) {
    var compare = {
        // field to compare
        field: 'title',
        // value to be compared with
        value: 'yes',
        // heading if compare.value matches with compare.field value
        heading: ' <i>(mobile/desktop)</i> ',
        // alternate heading
        alt_heading: ' <i>(desktop only)</i> ',
        // WP adds <span class="in-widget-title"></span> in each widget heading by default
        heading_selector: '.in-widget-title'
    };

    var widgetIdSelector = '> .widget-inside > form > .widget-id';
    // heading is added as prefix of already existing heading, modify this as needed
    function modify_heading( $Elm, isMain ) {
        var html = $Elm.html();
        if ( html.indexOf( compare.heading ) == -1 && html.indexOf( compare.alt_heading ) == -1 ) {
            if( isMain ) {
                $Elm.html( compare.heading + html );
            }
            else {
                $Elm.html( compare.alt_heading + html );
            }
        }
    };
    function parseFieldSelector( widgetId ) {
        return 'input[name="' + widgetIdToFieldPrefix( widgetId ) + '[' + compare.field + ']"]';
    };

    // @note: change this function if you don't want custom Heading change to appear for all the widgets.
    // If field variable is empty, then that means that field doesn't exist for that widget.
    // So use this logic if you don't want the custom heading manipulation if the field doesn't exist for a widget
    function modify_widget( evt, $widget, content ) {
        var field = null;
        var field_value = '';
        if( content ) {
            field = $( content ).find( parseFieldSelector( $widget.find( widgetIdSelector ).val() ) );
        }
        else {
            field = $widget.find( parseFieldSelector( $widget.find( widgetIdSelector ).val() ) );
        }
        if( field ) {
            field_value = ( ( field.attr( 'type' ) != 'radio' && field.attr( 'type' ) != 'checkbox' )
                          || field.is( ':checked' ) ) ? field.val() : '';
        }
        modify_heading( $widget.find( compare.heading_selector ), field_value == compare.value );
    }

    function parseWidgetId( widgetId ) {
        var matches, parsed = {
            number: null,
            id_base: null
        };
        matches = widgetId.match( /^(.+)-(\d+)$/ );
        if ( matches ) {
            parsed.id_base = matches[1];
            parsed.number = parseInt( matches[2], 10 );
        } else {
            parsed.id_base = widgetId;
        }
        return parsed;
    }
    function widgetIdToSettingId( widgetId ) {
        var parsed = parseWidgetId( widgetId ), settingId;
        settingId = 'widget_' + parsed.id_base;
        if ( parsed.number ) {
            settingId += '[' + parsed.number + ']';
        }
        return settingId;
    }
    function widgetIdToFieldPrefix( widgetId ) {
        var parsed = parseWidgetId( widgetId ), settingId;
        settingId = 'widget-' + parsed.id_base;
        if ( parsed.number ) {
            settingId += '[' + parsed.number + ']';
        }
        return settingId;
    }
    var api = wp.customize;
    if( api ) {
        // We ate in the customizer
        widgetIdSelector = '> .widget-inside > .form > .widget-id';
        api.bind( 'ready', function() {
            function add_widget( evt, $widget ) {
                var control;
                control = api.control( widgetIdToSettingId( $widget.find( widgetIdSelector ).val() ) );

                function updateTitle( evt ) {
                    modify_widget( null, $widget );
                };
                if ( control ) {
                    control.setting.bind( updateTitle );
                }
                updateTitle();
            };
            api.control.each( function ( control ) {
                if( control.id &&  0 === control.id.indexOf( 'widget_' ) ) {
                    api.section( control.section.get(), function( section ) {
                        function onExpanded( isExpanded ) {
                            if ( isExpanded ) {
                                section.expanded.unbind( onExpanded );
                                modify_widget( null, control.container.find( '.widget' ), control.params.widget_content );
                            }
                        };
                        if ( section.expanded() ) {
                            onExpanded( true );
                        } else {
                            section.expanded.bind( onExpanded );
                        }
                    } );
                }
            } );
            $( document ).on( 'widget-added', add_widget );
        } );
    }
    else {
        // We are in wp-admin -> Appearance -> Widgets
        // Use proper condition and CODE if you want to target any page builder
        // that doesn't use WP Core Widget Markup or Core JavaScript
        $( window ).on( 'load', function() {
            $( '#widgets-right div.widgets-sortables div.widget' ).each( function() {
                modify_widget( 'non-customizer', $( this ) );
            } );
            $( document ).on( 'widget-added', modify_widget );
        } );
    }
    $( document ).on( 'widget-updated', modify_widget );
})( window.wp, jQuery );

プラグインの使用法:

注:ウィジェットのtitleを設定した場合、上記のサンプルプラグインコードをそのまま使用yesにすると、ウィジェットコントロールUI見出し内に(mobile/desktop)が表示され、他のすべてのウィジェットには(desktopのみ)見出し。カスタマイザでは、変更はすぐに反映され、wp-admin -> widgetsでは、変更をsave後に表示します。もちろん、(JavaScriptで)CODEを変更して別のfield_nameの見出しを変更するか、特定の見出しをすべてのウィジェットではなく一部のウィジェットにのみ表示することで、この動作を変更できます。

たとえば、use_mobileという名前のフィールドがあり、yesに設定されているときに見出しを(mobile/desktop)に設定するとします。次に、compare変数を次のように設定します。

var compare = {
    field: 'use_mobile',
    value: 'yes',
    heading: ' <i>(mobile/desktop)</i> ',
    alt_heading: ' <i>(desktop only)</i> ',
    heading_selector: '.in-widget-title'
};

また、(.in-widget-titleだけでなく)見出し全体を変更する場合は、headingおよびheading_selectorの正しいマークアップとともにalt_heading設定を変更することもできます。可能性は無限にありますが、結果のマークアップで創造的になりたい場合は、WordPressコアCODEでエラーが発生しないようにしてください。

ページビルダーの統合:

これらのソリューションのいずれかがページビルダーで機能するかどうかは、そのページビルダーの実装に依存します。 WordPressが提供するメソッドを使用してウィジェットコントロールUIをロードする場合、変更せずに動作します。そうしないと、同様の(ただし変更された)意味がページビルダーでも可能になります。

4
Fayaz

まずadminのウィジェットタイトルに表示される情報を変更できるかどうかを見てみましょう。このリストは wp_list_widget_controls によって生成され、 dynamic_sidebar を呼び出します。これには、タイトルを含むコントロール内のパラメータを変更するためのフィルタ dynamic_sidebar_params が含まれます。それを試してみましょう:

add_filter ('dynamic_sidebar_params','wpse261042_change_widget_title');
function wpse261042_change_widget_title ($params) {
  $string = ' Added info';
  $params[0]['widget_name'] .= $string;
  return $params;
  }

$stringは正確にあなたが指し示す場所にはありません、しかし私はそれが十分に良いと言いたいです。

さて、$stringを現在のウィジェットの中からの情報で置き換える必要があります。幸いなことに、$paramsにはwidget_idも含まれているので、自分がどのウィジェットにいるのかがわかります。ウィジェットデータを取得するためにwidget_idをどのように使用するかについての説明は、私は この回答を参照してください 。さあ:

 // we need to separate the widget name and instance from the id
 $widget_id = $params[0]['widget_id'];
 $widget_instance = strrchr ($widget_id, '-');
 $wlen = strlen ($widget_id);
 $ilen = strlen ($widget_instance);
 $widget_name = substr ($widget_id,0,$wlen-$ilen);
 $widget_instance = substr ($widget_instance,1);
 // get the data
 $widget_instances = get_option('widget_' . $widget_name);
 $data = $widget_instances[$widget_instance];

これで、配列$dataにウィジェットのインスタンスが含まれ、関数内でどのインスタンスを$stringに渡すかを選択できます。

3
cjbj

WordPressにはすでにウィジェットのUIに組み込まれた同様の機能があります。たとえば、ユーザーが入力した「タイトル」の値がこの検索ウィジェットのタイトルにどのように追加されるかを参照してください。

Search widget with title appended 

これを行うコードは wp-admin/js/widgets.js にあります。

appendTitle : function(widget) {
    var title = $('input[id*="-title"]', widget).val() || '';

    if ( title ) {
        title = ': ' + title.replace(/<[^<>]+>/g, '').replace(/</g, '&lt;').replace(/>/g, '&gt;');
    }

    $(widget).children('.widget-top').children('.widget-title').children()
            .children('.in-widget-title').html(title);

},

ウィジェット内で-titleで終わるinput属性を持つid要素を見つけ、その入力に入力された値をウィジェットのタイトルバーのテキストに追加します。

あなたが念頭に置いている設定がinputフィールドに基づいている場合(typetextであるかradioであるかにかかわらず)、あなたはそれに-titleで終わるidを与える必要があるだけです、そしてWordPressは残り。

これにより、ユーザーが設定を変更したときにタイトルバーの文字列が自動的に更新されます。

1
J.D.