Come aggiungere un campo personalizzato alla modifica rapida in WordPress

27 apr 2020, 03:06:45
Visualizzazioni: 16.9K
Voti: 4

Come posso aggiungere una nuova colonna alla modifica rapida e inserire un campo personalizzato al suo interno? Ho letto questa domanda ma uno dei link porta a un errore 404. Ho bisogno di una nuova colonna per la mia chiave meta personalizzata "summary" e per i tipi di post "post" e "episode".

0
Tutte le risposte alla domanda 3
12
14

Ci sono alcuni passaggi per creare la casella di modifica rapida personalizzata e la colonna personalizzata

  1. creare una meta key personalizzata (si assume che ne abbiate già una)
  2. aggiungere titolo e dati per la colonna personalizzata nell'amministrazione (si assume che vogliate mostrare la meta key personalizzata nella colonna, altrimenti potete modificare leggermente la logica per ottenere lo stesso risultato poiché il principio è lo stesso)
  3. aggiungere la casella di modifica rapida personalizzata
  4. aggiungere la logica di salvataggio
  5. caricare lo script per modificare la funzione originale inline-edit-post per supportare il valore meta personalizzato
  6. preparare il file dello script

Questo esempio aggiungerà una casella di input per la modifica rapida nel post type Page. Il seguente codice è stato testato e funziona inserendolo in functions.php.

1. creare una meta key personalizzata (si assume che ne abbiate già una)

Ho preparato una meta key personalizzata remark per il post type page

2. aggiungere titolo e dati per la colonna personalizzata nell'amministrazione

per i custom post type, potete usare

Aggiungere il titolo della colonna

Aggiungere il contenuto della colonna

Di seguito un esempio per il post type Page così come per un custom post type + il Post predefinito come esempio per una configurazione con più post type.

// aggiungi titolo colonna personalizzata per il meta value personalizzato
add_filter('manage_edit-page_columns', 'ws365150_add_custom_columns_title' );
function ws365150_add_custom_columns_title( $columns ) {
    $columns['page_remark'] = 'Nota'; // potete usare __() in seguito per il supporto alla traduzione
    
    return $columns;
}
    
// aggiungi dati colonna personalizzata con meta value personalizzato
add_action('manage_pages_custom_column', 'ws365150_add_custom_column_data', 10, 2 );
function ws365150_add_custom_column_data( $column_name, $post_id ) {
    switch ( $column_name ) {
        case 'page_remark':
            echo get_post_meta( $post_id, 'remark', true );
            break;
        
        default:
            break;
    }
}

Di seguito un esempio per il custom post type episode + il Post predefinito con meta key summary

// aggiungi titolo colonna personalizzata per il meta value personalizzato
// 'manage_pages_columns' o 'manage_edit-post_columns' funzionano entrambi
add_filter('manage_posts_columns', 'ws365150_add_custom_columns_title_pt', 10, 2 );
function ws365150_add_custom_columns_title_pt( $columns, $post_type ) {
    switch ( $post_type ) {
        case 'post':
        case 'episode':
            $columns['ws365150_summary'] = 'Riassunto'; // potete usare __() in seguito per il supporto alla traduzione
            break;
        
        default:
            
            break;
    }
    
    return $columns;
}
    
// aggiungi dati colonna personalizzata con meta value personalizzato per custom post types
add_action('manage_posts_custom_column', 'ws365150_add_custom_column_data_pt', 10, 2 );
function ws365150_add_custom_column_data_pt( $column_name, $post_id ) {
    switch ( $column_name ) {
        case 'ws365150_summary': // specificato per questa colonna assegnata nel titolo della colonna
            echo get_post_meta( $post_id, 'summary', true );
            break;
        
        default:
            break;
    }
}

3. aggiungere la casella di modifica rapida personalizzata

// per page
add_action( 'quick_edit_custom_box', 'ws365150_custom_edit_box', 10, 3 );
function ws365150_custom_edit_box( $column_name, $post_type, $taxonomy ) {
    global $post;

    switch ( $post_type ) {
        case 'page':

        if( $column_name === 'page_remark' ): // stesso titolo colonna definito nel passo precedente
        ?>
                <?php // echo get_post_meta( $post->ID, 'remark', true ); ?>
            <fieldset class="inline-edit-col-right" id="#edit-">
                <div class="inline-edit-col">
                    <label>
                        <span class="title">Nota</span>
                        <span class="input-text-wrap"><input type="text" name="remark" class="inline-edit-menu-order-input" value=""></span>
                    </label>
                </div>
            </fieldset>
            <?php
        endif;
            // echo 'custom page field';
            break;
        
        default:
            break;
    }
}

// per Post + custom post type
add_action( 'quick_edit_custom_box', 'ws365150_custom_edit_box_pt', 10, 3 );
function ws365150_custom_edit_box_pt( $column_name, $post_type, $taxonomy ) {
    global $post;

    switch ( $post_type ) {
        case 'post':
        case 'episode':

        if( $column_name === 'ws365150_summary' ): // stesso titolo colonna definito nel passo precedente
        ?>
                <?php // echo get_post_meta( $post->ID, 'remark', true ); ?>
            <fieldset class="inline-edit-col-right" id="#edit-">
                <div class="inline-edit-col">
                    <label>
                        <span class="title">Riassunto</span>
                        <span class="input-text-wrap"><input type="text" name="summary" class="inline-edit-menu-order-input" value=""></span>
                    </label>
                </div>
            </fieldset>
            <?php
        endif;
            // echo 'custom page field';
            break;
        
        default:
            break;
    }
}

4. aggiungere la logica di salvataggio

add_action( 'save_post', 'ws365150_update_custom_quickedit_box' );
function ws365150_update_custom_quickedit_box() {
    // qualsiasi logica di controllo qui, saltata e mantenuta semplice per scopi illustrativi (nonce, esistenza di $_POST['remark'], salvataggio ajax e così via
    
    // remark in Page
    if( isset( $_POST ) && isset( $_POST['remark'] ) ) { // dove remark è definito in <input name="remark">
        update_post_meta($_POST['post_ID'], 'remark', $_POST['remark']);
    }

    // summary in Post, custom post type
    if( isset( $_POST ) && isset( $_POST['summary'] ) ) { // dove summary è definito in <input name="summary">
        update_post_meta($_POST['post_ID'], 'summary', $_POST['summary']);
    }
    
    // per debug nell'inspector, non necessario, abilitare questo interromperà il salvataggio ma permetterà di vedere il return ajax
    // wp_send_json_success( array(
    //  'message' => 'Save test!',
    //  'post_data' => $_POST,
    // ) );
    return; // termina la chiamata della funzione
}

5. caricare lo script per modificare la funzione originale inline-edit-post

add_action( 'admin_enqueue_scripts', function( $page ) {

    // aggiungi logica di controllo della pagina, questa è semplice, potete testare il post type e così via...
    if ( 'edit.php' != $page ) {
        return;
    }
    
    wp_enqueue_script( 'custom-quickedit-box', get_stylesheet_directory_uri() . '/ws365150_custom_quickedit_box.js', array( 'jquery', 'inline-edit-post' ) );
});

6. preparare il file dello script (ws365150_custom_quickedit_box.js, quando testate il codice sopra, mettetelo nella cartella del tema)

( function( $, wp ) {
    // clona dalla funzione originale in inline-post-edit.js per l'override
    // in realtà non è necessario creare un alias, tuttavia creare un alias può essere una nota e un segno di override senza dimenticare per la manutenzione futura
    window.customInlineEditPost = window.inlineEditPost;

    // override funzione: aggiungi custom meta value, la base è copiata dal sorgente
    customInlineEditPost.edit = function(id) {
            // console.log( 'custom edit' );
            var t = this, fields, editRow, rowData, status, pageOpt, pageLevel, nextPage, pageLoop = true, nextLevel, f, val, pw;
            t.revert();

            if ( typeof(id) === 'object' ) {
                id = t.getId(id);
            }

            fields = ['post_title', 'post_name', 'post_author', '_status', 'jj', 'mm', 'aa', 'hh', 'mn', 'ss', 'post_password', 'post_format', 'menu_order', 'page_template'];
            if ( t.type === 'page' ) {
                fields.push('post_parent');
            }

            // Aggiungi la nuova riga di edit con una riga vuota extra sotto per mantenere lo striping zebrato.
            editRow = $('#inline-edit').clone(true);
            $( 'td', editRow ).attr( 'colspan', $( 'th:visible, td:visible', '.widefat:first thead' ).length );

            $(t.what+id).removeClass('is-expanded').hide().after(editRow).after('<tr class="hidden"></tr>');

            // Popola i campi nella finestra di modifica rapida.
            rowData = $('#inline_'+id);
            if ( !$(':input[name="post_author"] option[value="' + $('.post_author', rowData).text() + '"]', editRow).val() ) {

                // L'autore del post non ha più capacità di modifica, quindi dobbiamo aggiungerlo alla lista degli autori.
                $(':input[name="post_author"]', editRow).prepend('<option value="' + $('.post_author', rowData).text() + '">' + $('#' + t.type + '-' + id + ' .author').text() + '</option>');
            }
            if ( $( ':input[name="post_author"] option', editRow ).length === 1 ) {
                $('label.inline-edit-author', editRow).hide();
            }

            // popola custom meta value
            if ( $( ':input[name="remark"]', editRow ).length === 1 ) {
                $( ':input[name="remark"]', editRow ).val( $('#post-' + id + ' .page_remark').text() );
            }

            if ( $( ':input[name="summary"]', editRow ).length === 1 ) {
                $( ':input[name="summary"]', editRow ).val( $('#post-' + id + ' .ws365150_summary').text() );
            }

            for ( f = 0; f < fields.length; f++ ) {
                val = $('.'+fields[f], rowData);

                /**
                 * Sostituisce l'immagine per un Twemoji (emoji di Twitter) con il suo testo alternativo.
                 *
                 * @returns Testo alternativo dall'immagine.
                 */
                val.find( 'img' ).replaceWith( function() { return this.alt; } );
                val = val.text();
                $(':input[name="' + fields[f] + '"]', editRow).val( val );
            }

            if ( $( '.comment_status', rowData ).text() === 'open' ) {
                $( 'input[name="comment_status"]', editRow ).prop( 'checked', true );
            }
            if ( $( '.ping_status', rowData ).text() === 'open' ) {
                $( 'input[name="ping_status"]', editRow ).prop( 'checked', true );
            }
            if ( $( '.sticky', rowData ).text() === 'sticky' ) {
                $( 'input[name="sticky"]', editRow ).prop( 'checked', true );
            }

            /**
             * Crea le select box per le categorie.
             */
            $('.post_category', rowData).each(function(){
                var taxname,
                    term_ids = $(this).text();

                if ( term_ids ) {
                    taxname = $(this).attr('id').replace('_'+id, '');
                    $('ul.'+taxname+'-checklist :checkbox', editRow).val(term_ids.split(','));
                }
            });

            /**
             * Ottiene tutte le tassonomie per i suggerimenti di auto-completamento quando si digita il nome
             * di un tag.
             */
            $('.tags_input', rowData).each(function(){
                var terms = $(this),
                    taxname = $(this).attr('id').replace('_' + id, ''),
                    textarea = $('textarea.tax_input_' + taxname, editRow),
                    comma = inlineEditL10n.comma;

                terms.find( 'img' ).replaceWith( function() { return this.alt; } );
                terms = terms.text();

                if ( terms ) {
                    if ( ',' !== comma ) {
                        terms = terms.replace(/,/g, comma);
                    }
                    textarea.val(terms);
                }

                textarea.wpTagsSuggest();
            });

            // Gestisce lo status del post.
            status = $('._status', rowData).text();
            if ( 'future' !== status ) {
                $('select[name="_status"] option[value="future"]', editRow).remove();
            }

            pw = $( '.inline-edit-password-input' ).prop( 'disabled', false );
            if ( 'private' === status ) {
                $('input[name="keep_private"]', editRow).prop('checked', true);
                pw.val( '' ).prop( 'disabled', true );
            }

            // Rimuove la pagina corrente e i figli dal dropdown del parent.
            pageOpt = $('select[name="post_parent"] option[value="' + id + '"]', editRow);
            if ( pageOpt.length > 0 ) {
                pageLevel = pageOpt[0].className.split('-')[1];
                nextPage = pageOpt;
                while ( pageLoop ) {
                    nextPage = nextPage.next('option');
                    if ( nextPage.length === 0 ) {
                        break;
                    }

                    nextLevel = nextPage[0].className.split('-')[1];

                    if ( nextLevel <= pageLevel ) {
                        pageLoop = false;
                    } else {
                        nextPage.remove();
                        nextPage = pageOpt;
                    }
                }
                pageOpt.remove();
            }

            $(editRow).attr('id', 'edit-'+id).addClass('inline-editor').show();
            $('.ptitle', editRow).focus();

            return false;
    };
})( jQuery, window.wp );

Quanto sopra è per la modifica rapida usando l'hook quick_edit_custom_box, e potreste aver bisogno di gestire anche la modifica in blocco. Potete esplorare di più leggendo e usando bulk_edit_custom_box.

27 apr 2020 10:10:30
Commenti

Fantastico! Potresti modificare l'esempio per i post type post e episode e il meta key personalizzato summary? Scusa, non mi piace pasticciare con il file functions.php, potrei accidentalmente danneggiare WordPress. Devo essere sicuro al 100% che il codice funzionerà.

Gusto Gusto
5 mag 2020 01:12:17

Ho aggiunto del codice d'esempio aggiuntivo per post, episode con il campo meta summary con note aggiuntive sul titolo della colonna e un esempio di controllo durante il salvataggio. Puoi modificarlo e aggiungere ulteriori controlli in base al contenuto di cui hai bisogno.

西門 正 Code Guy - JingCodeGuy 西門 正 Code Guy - JingCodeGuy
10 mag 2020 13:06:50

Aspetta un attimo, questo codice non funziona e sta semplicemente rendendo bianca la mia pagina di modifica "Tutte le Pagine".

Gusto Gusto
12 mag 2020 23:47:14

Il codice è stato aggiornato, per favore cambia add_filter('manage_posts_columns', 'ws365150_add_custom_columns_title_pt' ); in add_filter('manage_posts_columns', 'ws365150_add_custom_columns_title_pt', 10, 2 ); Non preoccuparti di segnare la risposta prima di averlo testato.

西門 正 Code Guy - JingCodeGuy 西門 正 Code Guy - JingCodeGuy
13 mag 2020 02:15:54

Uhm, testando il codice sopra, il nuovo campo di input per il riassunto viene aggiunto al menu di modifica rapida dei post type post e episode,

ma dopo aver cliccato "aggiorna", il parametro summary risulta vuoto.

Anche se il parametro summary era già presente (senza usare la modifica rapida), l'input della modifica rapida rende comunque vuoto il parametro.

Gusto Gusto
14 mag 2020 00:17:21

Ho creato un caso di test per simulare la tua situazione e ho eseguito un test. Ho aggiornato il javascript e il filtro save_post. Assicurati anche che il javascript venga caricato correttamente. Perché il percorso presuppone che il javascript sia nella cartella del tema. Ora dovrebbe funzionare correttamente secondo la simulazione.

西門 正 Code Guy - JingCodeGuy 西門 正 Code Guy - JingCodeGuy
15 mag 2020 16:48:54

L'ho testato con entrambi i tipi di post. Funziona. Grazie.

Gusto Gusto
15 mag 2020 18:22:17

ottima risposta, anche se... è davvero terribile che debba essere così complicato

Toskan Toskan
8 gen 2021 00:34:46

@Toskan, potrebbe essere semplificato. È solo che questa risposta è specifica per il richiedente con meta key dalla domanda. Personalmente preferisco risposte generiche nella maggior parte dei casi poiché persone diverse hanno esigenze diverse. Se rimuoviamo gli esempi, ci sono pochi passaggi. In sintesi, ci sono 3 parti: (1)creazione di una meta key personalizzata (può essere fatta manualmente o usando plugin), (2)aggiunta di colonne personalizzate per la visualizzazione e (3)creazione della logica di modifica/salvataggio per la modifica rapida. Dato che la modifica rapida si basa su Javascript ajax per fornire una UX "istantanea", questa parte sembra un po' eccessiva.

西門 正 Code Guy - JingCodeGuy 西門 正 Code Guy - JingCodeGuy
9 gen 2021 11:45:07

ah sì, no non ho usato la tua parte javascript. C'è una soluzione molto più semplice per la parte js da qualche parte...

Toskan Toskan
11 gen 2021 21:39:15

guarda questa: https://pastebin.com/FDQPsau4

Toskan Toskan
12 gen 2021 04:11:09

@Toskan Grazie per la condivisione. Ma un punto da notare, il javascript che uso qui copia/si basa sul javascript originale del WordPress Core con controlli come il tipo e così via. Senza i giusti controlli, anche se potrebbe essere più semplice e funzionante, potrebbe risultare in errori in alcuni casi.

西門 正 Code Guy - JingCodeGuy 西門 正 Code Guy - JingCodeGuy
12 gen 2021 06:50:14
Mostra i restanti 7 commenti
0

non ho riscritto tutto il js al passo 6 ho aggiunto solo

(function($){
    lesson_orders={};
    if($('.post_type_page').length && $('.post_type_page').val()=='resource'){
        $('#the-list tr').each(function(){
            id=$(this).find('.check-column input').val();
            val=$(this).find('.lesson_order').text();
            lesson_orders['edit-'+id]=val;
        });
    }
    $(document).on('focus','.ptitle',function(){
        id =$(this).closest('.inline-edit-row').attr('id');
        $('#'+id+' input[name="lesson_order"]').val(lesson_orders[''+id]);
    }); 
})(jQuery);
28 gen 2021 21:15:48
2

Ecco cosa ho fatto nel 2024 per aggiungere il campo meta summary ai tipi di post post e episode come colonne e modificabile tramite modifica rapida.

Aggiungere una colonna nell'amministrazione

Per prima cosa, definisci le colonne con il filtro manage_posts_columns.

/**
 * Aggiunge la colonna Riepilogo a Post e Episodi
 *
 * @param array $columns Un array associativo di intestazioni di colonna.
 * @param string $post_type Lo slug del tipo di post.
 *
 * @return array Un array potenzialmente modificato di colonne.
 */
function prefix_add_summary_column($columns, $post_type)
{
    if (in_array($post_type, array('post','episode')) {
        return array_merge($columns, array(
            'summary' => __('Riepilogo')
        ));
    }
    return $columns;
}
add_filter('manage_posts_columns', 'prefix_add_summary_column', 10, 2);

In alternativa, puoi usare add_filter('manage_post_posts_columns', 'prefix_add_summary_column'); e add_filter('manage_episode_posts_columns', 'prefix_add_summary_column'); per targettizzare tipi di post specifici e rimuovere l'istruzione if che verifica il tipo di post all'interno della funzione.

Successivamente, definisci cosa viene visualizzato nel contenuto per la tua colonna summary usando l'azione manage_posts_custom_column. Per questo esempio, viene semplicemente mostrato il valore del campo meta summary.

/**
 * Mostra il contenuto della colonna Riepilogo per Post e Episodi
 *
 * @param string $column_name Il nome della colonna da visualizzare.
 * @param int $post_id L'ID del post corrente in visualizzazione.
 *
 * @return void
 */
function prefix_display_summary_column($column_name, $post_id)
{
    if ($column_name === 'summary') {
        echo esc_html(get_post_meta($post_id,'summary',true));
    }
}
add_action('manage_posts_custom_column', 'prefix_display_summary_column', 10, 2);

Ancora una volta, puoi invece usare add_action('manage_post_posts_custom_column', 'prefix_display_summary_column', 10, 2); e add_action('manage_episode_posts_custom_column', 'prefix_display_summary_column', 10, 2); per applicare l'azione a tipi di post specifici. Il motivo per cui non c'è un'istruzione if che verifica i tipi di post è perché questa colonna non verrà trovata in altri tipi di post grazie al passaggio precedente.

Aggiungere il campo per la modifica rapida

Ora questo è sufficiente per renderizzare la colonna personalizzata summary e i suoi dati. Il prossimo passo è aggiungere la funzionalità per la modifica rapida. Il primo passaggio qui è aggiungerlo ai dati inline nascosti per memorizzarli sul frontend per il recupero successivo usando l'azione add_inline_data in questo modo:

/**
 * Aggiunge Riepilogo ai Dati dell'Editor Inline
 *
 * @param WP_Post $post L'oggetto post corrente.
 *
 * @return void
 */
function prefix_add_summary_inline($post)
{
    if (in_array($post->post_type, array('post','episode')) {
        printf(
            '<div class="summary">%s</div>',
            esc_html(get_post_meta($post->ID,'summary',true))
        );
    }
}
add_action('add_inline_data', 'prefix_add_summary_inline');

Al momento della scrittura, non esiste un'azione specifica per tipo di post, quindi è necessario l'istruzione if che lo verifica. Sto usando esc_html() qui ma usa qualsiasi funzione di escape appropriata per i tuoi dati.

Ora per visualizzare il campo di testo nella casella dell'editor di modifica rapida usando l'azione quick_edit_custom_box in questo modo:

/**
 * Visualizza il Campo di Input per l'Editor del Riepilogo
 *
 * @param string $column_name Nome della colonna da modificare.
 * @param string $post_type Lo slug del tipo di post
 *
 * @return void
 */
function prefix_display_summary_field($column_name, $post_type)
{
    if ($column_name == 'summary' && in_array($post_type, array('post', 'episode'))) {
        printf(
            '<fieldset class="inline-edit-col-right">
                <div class="inline-edit-col">
                    <div class="inline-edit-group wp-clearfix">
                        <label class="inline-edit-au-websites alignleft">
                            <span class="title">%s</span>
                            <span class="input-text-wrap">
                                <input type="text" name="%s" autocomplete="off">
                            </span>
                        </label>
                    </div>
                </div>
            </fieldset>',
            esc_html__('Riepilogo'),
            esc_attr($column_name)
        );
    }
}
add_action('quick_edit_custom_box', 'prefix_display_summary_field', 10, 2);

Qui stiamo verificando il nome della nostra colonna personalizzata e il tipo di post e generando l'HTML che utilizza un markup simile agli altri campi di modifica rapida. Sentiti libero di minificare l'HTML.

E finalmente, l'ultimo pezzo è precompilare il campo di input con i dati nascosti! Invece di clonare lo script dell'editor, qui semplicemente ascoltiamo il trigger di focus che emette quando si apre, poi prendiamo il nostro valore dal campo nascosto e lo impostiamo (ma solo se il nostro valore nascosto ha dei dati e il valore corrente del campo dell'editor è vuoto)!

Per questo, aggancio l'azione admin_enqueue_scripts e utilizzo la funzione wp_add_inline_script per allegare il nostro JS personalizzato allo script dell'editor inline (inline-edit-post) che è già caricato nella pagina. In questo modo, il nostro script apparirà sempre dopo che inline-edit-post.min.js è caricato, ma solo sui nostri tipi di post specifici post e episode.

/**
 * Precompila il Campo di Modifica Riepilogo con il Valore del Post
 *
 * @param string $hook Suffisso dell'hook per la pagina admin corrente
 *
 * @return void
 */
function prefix_prefill_summary_field($hook) {
    if ($hook == 'edit.php' && in_array(get_post_type(), array('post', 'episode'))) {
        wp_add_inline_script(
            'inline-edit-post', // Handle
            '(function($) {
                $(".ptitle").on("focus",function(e){
                    let id = parseInt($(e.target).closest(".quick-edit-row").attr("id").replace("edit-","")),
                        value = $("#inline_"+id+" .summary").text(),
                        $input = $("#edit-"+id+".quick-edit-row input[name=summary]");
                    if(value && !$input.val()) {
                        $input.val(value);
                    }
                });
            })(jQuery);'
        );
    }
}
add_action('admin_enqueue_scripts', 'prefix_prefill_summary_field');

Questo funziona perché estende ciò che WordPress fa nativamente, come salva i meta dati e i dati del post. Ecco perché non devo scrivere nulla di personalizzato per un'azione save_post.

17 gen 2024 01:20:19
Commenti

Cosa rende il salvataggio funzionante? Come fa WP a conoscere il nome del campo meta in cui salvare?

Bence Szalai Bence Szalai
14 ott 2024 16:02:03

@bence-szalai WordPress conosce il nome della meta key attraverso l'attributo name dell'elemento di controllo del form nella modalità di modifica rapida del post. Nell'esempio sopra, è il valore di $column_name nella funzione prefix_display_summary_field(), ad esempio summary. Personalmente, consiglio di prefissare tutti i tuoi meta field per prevenire sovrascritture accidentali. Sa che deve salvare perché esisterà nell'array $_POST al momento dell'invio del form, che WP leggerà dinamicamente e salverà nei post meta.

AuRise AuRise
17 ott 2024 17:39:17