Как редактировать метаданные поста по ID поста в Гутенберге

Вопрос или проблема

Какова лучшая практика для этого в Gutenberg/JavaScript:

update_post_meta( $page_id, '_custom_post_meta', 'Некоторые данные для сохранения' );
  • Мне нужно сделать это из боковой панели
  • Пользовательский мета-поле зарегистрировано, и я могу обновить его для редактируемого поста
  • Мне нужно сделать это для другого поста, а не для редактируемого в данный момент

Вот пример использования:

const UpdateMeta = () => {

    const { editPost } = useDispatch( 'core/editor' );
    const onChange = ( value ) => {
        editPost( { // Я обновляю здесь редактируемый пост, и это нормально
            meta: { _custom_meta : JSON.stringify( value ) },
        } );

        // Но я хотел бы изменить некоторые метаданные другого поста, выбранного по его ID
    };

    return (
        <FormTokenField
            value={ selectedContinents }
            suggestions={ suggestionsList }
            __experimentalShowHowTo={false}
            onChange={ onChange }
            displayTransform={ prepare }
        />
    );
}

const Component = () => (
    <PluginDocumentSettingPanel
        title={ 'Моя боковая панель' }>
        <UpdateMeta/>
    </PluginDocumentSettingPanel>
);

registerPlugin( 'my-plugin-name', {
    icon: '',
    render: Component,
} );

Я исключил не относящиеся к делу части кода.

Обновление:
Я делюсь полным кодом здесь (код в разработке, пожалуйста, игнорируйте возможные ошибки и недостатки):

const { registerPlugin } = wp.plugins;
const { FormTokenField } = wp.components;
const { PluginDocumentSettingPanel } = wp.editPost;
const { useSelect, useDispatch } = wp.data;
const { useState } = wp.element;
let targetType="";

const RelatedDifferentTypePosts = () => {

    const postType = wp.data.select( 'core/editor' ).getCurrentPostType();

    switch ( postType ) {
            case 'display':
                targetType="event";
                break;
            case 'event':
                targetType="display";
                break;
    }

    const postMetaField = `_assigned_${  targetType  }s`;

    const isLoading = useSelect( ( select ) => {
        return select( 'core/data' ).isResolving( 'core', 'getEntityRecords',  [
            'postType', targetType
        ] );
    } );

    const assignedPosts = useSelect(
        ( select ) => select( 'core/editor' ).getEditedPostAttribute( 'meta' )[postMetaField], []
    );

    const targetPostsRaw = useSelect(
        ( select ) => select( 'core' ).getEntityRecords( 'postType', targetType ), []
    );

    let valueTitlePair = [];
    if ( targetPostsRaw ) {
        valueTitlePair = targetPostsRaw.map( ( postItem ) => {
            const tempObj = {};
            tempObj.id = postItem.id;
            tempObj.slug = postItem.slug;
            return tempObj;
        } );
    }

    const slugs = assignedPosts ? Array.from( JSON.parse( assignedPosts ), ( item ) => { return item.slug; } ) : [];
    const [ selectedPosts, setSelectedPosts ] = useState( slugs );

    let suggestionsList;
    if ( targetPostsRaw ) {
        suggestionsList = Array.from( targetPostsRaw, ( postItem ) => {
            return postItem.slug;
        } );
    }

    const { editPost } = useDispatch( 'core/editor' );
    const onChange = ( value ) => {

        /* Предотвратить ввод несуществующих событий */
        value = value.filter( ( entry ) => suggestionsList.includes( entry ) );

        setSelectedPosts( value );
        value = valueTitlePair.filter( pair => value.includes( pair.slug ) );

        editPost( {
            meta: { [ postMetaField ] : JSON.stringify( value ) },
        } );
    };

    const prepare = ( token ) => {
        return token.replaceAll( '-', ' ' ).replace( /(^\w|\s\w)/g, m => m.toUpperCase() );
    };

    if ( isLoading ) {
        return <h3>Загрузка...</h3>;
    }

    return (
        <FormTokenField
            value={ selectedPosts }
            suggestions={ suggestionsList }
            __experimentalShowHowTo={false}
            onChange={ onChange }
            displayTransform={ prepare }
        />
    );
};

/**
 * Компонент
 */
const Component = () => (
    <PluginDocumentSettingPanel
        title={ `Связанные ${ targetType.charAt( 0 ).toUpperCase() + targetType.slice( 1 ) }` }>
        <RelatedDifferentTypePosts/>
    </PluginDocumentSettingPanel>
);

registerPlugin( 'related-posts-of-different-type', {
    icon: '',
    render: Component,
} );

Я смог сделать это, используя Backbone JavaScript Client, предоставленный в составе основных скриптов wp-api.

Вы можете получить пост, обновить его мета-данные и сохранить его. Убедитесь, что вы wp_enqueue_script( 'wp-api' ) или добавили его в зависимости своего скрипта, чтобы API был доступен в JavaScript по адресу wp.api.

Пример:

const post = new wp.api.models.Post( { id: 123 } );
post.fetch().done( () => {
    post.setMeta( 'your_meta_field', 'your_meta_string_content' );
    post.save().done( () => {
        // Любые действия, которые нужно выполнить после сохранения мета-данных.
    } );
} );

Методы Backbone Client не имеют хорошей документации на данный момент, но вы можете просмотреть их в исходном коде. Например, setMeta() можно найти здесь: https://github.com/WordPress/WordPress/blob/master/wp-includes/js/wp-api.js#L543-L553

Будьте осторожны, поскольку API возвращает промисы для большинства методов; легко допустить ошибку (например, попытаться установить мета-данные поста до того, как пост был загружен, что не даст никаких результатов).

Также имейте в виду, что REST API имеет конечные точки для каждого типа поста, поэтому вам нужно будет использовать разные модели для каждого. Например, wp.api.models.Post, wp.api.models.Page, wp.api.models.YourCustomPostTypes и т.д. Возможно, вам придется сохранить эту информацию вместе с ID, чтобы знать, какую конечную точку использовать.

Ответ или решение

Чтобы редактировать метаданные поста по его ID в редакторе Gutenberg, необходимо прибегнуть к REST API WordPress и использовать объекты, предоставляемые Backbone.js. Основная идея заключается в том, чтобы сначала запросить нужный пост, обновить его метаданные и затем сохранить изменения. Ниже представлена пошаговая инструкция и пример кода для решения вашей задачи.

Шаги для редактирования метаданных поста по ID

  1. Подготовка окружения:
    Убедитесь, что у вас подключён скрипт wp-api, иначе вы не сможете работать с REST API. Если вы создаёте свой скрипт, добавьте его зависимости в функции wp_enqueue_script.

    function my_enqueue_scripts() {
       wp_enqueue_script( 'wp-api' );
    }
    add_action( 'admin_enqueue_scripts', 'my_enqueue_scripts' );
  2. Создание функционала для обновления метаданных:
    Используйте метод fetch() для получения объекта поста и setMeta() для установки нужных метаданных. Как только метаданные установлены, их нужно сохранить с помощью метода save().

Пример кода

Ниже приведён пример компонента, который позволяет редактировать метаданные другого поста:

const { registerPlugin } = wp.plugins;
const { PluginDocumentSettingPanel } = wp.editPost;
const { FormTokenField } = wp.components;
const { useDispatch } = wp.data;
const { useState, useEffect } = wp.element;

const UpdatePostMeta = ({ targetPostId }) => {
    const [metaValue, setMetaValue] = useState('');

    const updateMeta = (value) => {
        const post = new wp.api.models.Post({ id: targetPostId });
        post.fetch().done(() => {
            post.setMeta('_custom_post_meta', value);
            post.save().done(() => {
                console.log('Метаданные успешно обновлены!');
            }).fail((error) => {
                console.error('Ошибка при сохранении метаданных:', error);
            });
        }).fail((error) => {
            console.error('Ошибка при получении поста:', error);
        });
    };

    return (
        <FormTokenField
            value={metaValue}
            suggestions={[]}
            onChange={(value) => {
                setMetaValue(value);
                updateMeta(value);
            }}
        />
    );
};

const MySidebarComponent = () => {
    // Здесь определите ID целевого поста, метаданные которого вы хотите обновить
    const targetPostId = 123; // Замените на нужный ID поста

    return (
        <PluginDocumentSettingPanel
            title="Обновить метаданные"
            initialOpen={true}
        >
            <UpdatePostMeta targetPostId={targetPostId} />
        </PluginDocumentSettingPanel>
    );
};

registerPlugin('my-post-meta-plugin', {
    render: MySidebarComponent,
});

Пояснение:

  • Компонент UpdatePostMeta:

    • Мы создаём состояние metaValue для хранения значения, которое мы хотим сохранить в метаданные.
    • В функции updateMeta происходит запрос поста с помощью fetch(), установка метаданных с помощью setMeta() и сохранение с помощью save().
  • Компонент MySidebarComponent:

    • Содержит панель PluginDocumentSettingPanel, где и будет отображаться поле для ввода метаданных.
    • Убедитесь, что вы передаёте правильный ID поста, который нужно обновить.

Заключение

Пользуясь описанными шагами, вы сможете редактировать метаданные любого поста в WordPress через интерфейс Gutenberg, используя JavaScript и REST API. Убедитесь, что у вас есть все необходимые разрешения для работы с постами через API, и тестируйте ваш код на локальном окружении перед тем, как применять его на живом сайте.

Оцените материал
Добавить комментарий

Капча загружается...