函数文档

wp_autosave()

💡 云策文档标注

概述

wp_autosave() 函数用于通过 XHR 提交保存文章,主要与 heartbeat 和 autosave.js 配合使用。它处理文章数据的验证、权限检查和自动保存逻辑,根据文章状态和用户权限决定是直接更新草稿还是创建自动保存修订。

关键要点

  • 函数用途:通过 XHR 提交保存文章,支持自动保存功能,适用于 WordPress 的 heartbeat 机制。
  • 参数要求:接受一个关联数组 $post_data,必须包含 post_id 等文章数据。
  • 返回值:成功时返回保存的文章 ID(可能是草稿 ID 或自动保存修订 ID),失败时返回 0 或 WP_Error。
  • 核心逻辑:验证 nonce 和用户编辑权限,根据文章状态(如 auto-draft 或 draft)和文章锁状态决定调用 edit_post() 直接更新或 wp_create_post_autosave() 创建修订。
  • 相关函数:涉及 wp_verify_nonce()、current_user_can()、wp_check_post_lock() 等,用于安全性和权限控制。

代码示例

function wp_autosave( $post_data ) {
    // Back-compat.
    if ( ! defined( 'DOING_AUTOSAVE' ) ) {
        define( 'DOING_AUTOSAVE', true );
    }

    $post_id              = (int) $post_data['post_id'];
    $post_data['ID']      = $post_id;
    $post_data['post_ID'] = $post_id;

    if ( false === wp_verify_nonce( $post_data['_wpnonce'], 'update-post_' . $post_id ) ) {
        return new WP_Error( 'invalid_nonce', __( 'Error while saving.' ) );
    }

    $post = get_post( $post_id );

    if ( ! current_user_can( 'edit_post', $post->ID ) ) {
        return new WP_Error( 'edit_posts', __( 'Sorry, you are not allowed to edit this item.' ) );
    }

    if ( 'auto-draft' === $post->post_status ) {
        $post_data['post_status'] = 'draft';
    }

    if ( 'page' !== $post_data['post_type'] && ! empty( $post_data['catslist'] ) ) {
        $post_data['post_category'] = explode( ',', $post_data['catslist'] );
    }

    if ( ! wp_check_post_lock( $post->ID ) && get_current_user_id() === (int) $post->post_author
        && ( 'auto-draft' === $post->post_status || 'draft' === $post->post_status )
    ) {
        // Drafts and auto-drafts are just overwritten by autosave for the same user if the post is not locked.
        return edit_post( wp_slash( $post_data ) );
    } else {
        /*
         * Non-drafts or other users' drafts are not overwritten.
         * The autosave is stored in a special post revision for each user.
         */
        return wp_create_post_autosave( wp_slash( $post_data ) );
    }
}

注意事项

  • 函数内部定义了 DOING_AUTOSAVE 常量以保持向后兼容性,开发者需注意避免冲突。
  • 自动保存逻辑区分草稿和非草稿:对于未锁定且由同一作者编辑的草稿,直接覆盖;否则创建用户特定的自动保存修订。
  • 参数 $post_data 需包含有效的 _wpnonce 和 post_id,否则可能返回 WP_Error。
  • 函数依赖于多个 WordPress 核心函数(如 wp_verify_nonce、current_user_can),确保环境正确配置。

📄 原文内容

Saves a post submitted with XHR.

Description

Intended for use with heartbeat and autosave.js

Parameters

$post_dataarrayrequired
Associative array of the submitted post data.

Return

mixed The value 0 or WP_Error on failure. The saved post ID on success.
The ID can be the draft post_id or the autosave revision post_id.

Source

function wp_autosave( $post_data ) {
	// Back-compat.
	if ( ! defined( 'DOING_AUTOSAVE' ) ) {
		define( 'DOING_AUTOSAVE', true );
	}

	$post_id              = (int) $post_data['post_id'];
	$post_data['ID']      = $post_id;
	$post_data['post_ID'] = $post_id;

	if ( false === wp_verify_nonce( $post_data['_wpnonce'], 'update-post_' . $post_id ) ) {
		return new WP_Error( 'invalid_nonce', __( 'Error while saving.' ) );
	}

	$post = get_post( $post_id );

	if ( ! current_user_can( 'edit_post', $post->ID ) ) {
		return new WP_Error( 'edit_posts', __( 'Sorry, you are not allowed to edit this item.' ) );
	}

	if ( 'auto-draft' === $post->post_status ) {
		$post_data['post_status'] = 'draft';
	}

	if ( 'page' !== $post_data['post_type'] && ! empty( $post_data['catslist'] ) ) {
		$post_data['post_category'] = explode( ',', $post_data['catslist'] );
	}

	if ( ! wp_check_post_lock( $post->ID ) && get_current_user_id() === (int) $post->post_author
		&& ( 'auto-draft' === $post->post_status || 'draft' === $post->post_status )
	) {
		// Drafts and auto-drafts are just overwritten by autosave for the same user if the post is not locked.
		return edit_post( wp_slash( $post_data ) );
	} else {
		/*
		 * Non-drafts or other users' drafts are not overwritten.
		 * The autosave is stored in a special post revision for each user.
		 */
		return wp_create_post_autosave( wp_slash( $post_data ) );
	}
}

Changelog

Version Description
3.9.0 Introduced.