我想在我的Wordpress网站中添加前端后期编辑功能。我找到了一些这样做的插件,但它们不能满足我的所有需要,所以我决定进行调整an existing solution 开发一个我自己的插件,该插件将返回一个前端编辑表单的短代码。我的插件可以工作,我可以编辑和保存帖子,但是I can\'t solve a warning 和I don\'t have (yet) sufficient knowledge to make this plugin more secure. 有什么建议吗?
警告:
警告:无法修改标题信息-标题已由(输出开始于…/wp-content/plugins/front-post-edit.php:139)在/wp包括/可插拔。php在线1228
P、 139行是我插件中的最后一行(一行没有代码)
我的插件代码:
<?php
/*
* Plugin Name: Front Post Editor
*
*/
add_shortcode( \'front_post_edit\', \'post_shortcode\' );
function post_shortcode() {
return getForm();
}
function getForm() {
if ( !is_user_logged_in()) {
echo \'<p class="alert-box notice">You must be <a href="\' . esc_url( wp_login_url( get_permalink() ) ) . \'" title="Login">logged in</a>!\';
} else {
if( \'POST\' == $_SERVER[\'REQUEST_METHOD\'] && !empty( $_POST[\'action\'] ) && $_POST[\'action\'] == "edit_post" && isset($_POST[\'postid\'])) {
$post_to_edit = array();
$post_to_edit = get_post($_POST[\'postid\']);
/* these are the fields that we are editing in the form below */
$title = $_POST[\'item_title\'];
$description = $_POST[\'item_description\'];
$category = $_POST[\'item_category\'];
$location = $_POST[\'item_location\'];
$location2 = $_POST[\'item_location2\'];
/* this code will save the title and description into the post_to_edit array */
$post_to_edit->post_title = $title;
$post_to_edit->post_content = $description;
/* this code is a must */
$pid = wp_update_post($post_to_edit);
/* save taxonomies: post ID, form field name, taxonomy name, if it appends(true) or rewrite(false) */
wp_set_post_terms($pid, array($_POST[\'item_category\']),\'category\',false);
wp_set_post_terms($pid, array($_POST[\'item_location\']),\'location\',false);
/* update custom fields with the new info */
update_post_meta($pid, \'item_location2\', $location2);
/* redirect user after done editing */
wp_redirect( home_url( \'/myposts\' ) );
}
/* get post to edit */
$post_to_edit = get_post($_POST[\'postid\']);
/* get this post\'s category taxonomy term id */
$term_name = strip_tags( get_the_term_list( $post_to_edit->ID, \'category\', \'\', \', \', \'\' ) );
$term_obj = get_term_by(\'name\', $term_name, \'category\');
$term_id = $term_obj->term_id;
/* array for wp_dropdown_category to display with the current post category selected by default */
$args_cat = array(
\'selected\' => $term_id,
\'name\' => \'item_category\',
\'class\' => \'postform\',
\'tab_index\' => 10,
\'depth\' => 2,
\'hierarchical\' => 1,
\'taxonomy\' => \'category\',
\'hide_empty\' => false );
/* get this post\'s location taxonomy term id */
$term_name2 = strip_tags( get_the_term_list( $post_to_edit->ID, \'location\', \'\', \', \', \'\' ) );
$term_obj2 = get_term_by(\'name\', $term_name2, \'location\');
$term_id2 = $term_obj2->term_id;
$args_loc = array(
\'selected\' => $term_id2,
\'name\' => \'item_location\',
\'class\' => \'postform\',
\'tab_index\' => 10,
\'depth\' => 2,
\'hierarchical\' => 1,
\'taxonomy\' => \'location\',
\'hide_empty\' => false );
?>
<!-- EDIT FORM -->
<form id="edit_post" name="edit_post" method="post" action="" enctype="multipart/form-data">
<!-- post name -->
<fieldset name="item_title">
<label for="item_title">Item title:</label><br />
<input type="text" id="item_title" value="<?php echo $post_to_edit->post_title; ?>" tabindex="5" name="item_title" />
</fieldset>
<!-- post Content -->
<fieldset class="item_description">
<label for="item_description">Item description:</label><br />
<textarea id="item_description" tabindex="15" name="item_description"><?php echo $post_to_edit->post_content; ?></textarea>
</fieldset>
<!-- post Category -->
<fieldset id="item_category">
<label for="item_category">Item category:</label>
<?php wp_dropdown_categories( $args_cat ); ?>
</fieldset>
<!-- post Location -->
<fieldset id="item_location">
<label for="item_location">Item location:</label>
<?php wp_dropdown_categories( $args_loc ); ?>
</fieldset>
<!-- custom fields -->
<fieldset class="item_location2">
<label for="item_location2">Location 2:</label><br />
<input type="text" value="<?php echo get_post_meta($post_to_edit->ID,\'item_location2\', true); ?>" id="item_location2" tabindex="20" name="item_location2" />
</fieldset>
<!-- submit button -->
<fieldset class="submit">
<input type="submit" value="Save Post" tabindex="40" id="submit" name="submit" />
</fieldset>
<input type="hidden" name="postid" value="<?php echo $post_to_edit->ID; ?>" /> <!-- DONT REMOVE OR CHANGE -->
<input type="hidden" name="action" value="edit_post" /> <!-- DONT REMOVE OR CHANGE -->
<input type="hidden" name="change_cat" value="" /> <!-- DONT REMOVE OR CHANGE -->
<?php // wp_nonce_field( \'new-post\' ); ?>
</form>
<!-- END OF FORM -->
<?php } ?><!-- user is logged in -->
<?php } ?><!-- getForm -->
使用以下表单循环生成的每个条目的页脚都添加了一个编辑按钮:
<form class="edit-post" action="<?php echo home_url( \'/edit\'); ?>" method="post">
<input type="hidden" name="postid" value="<?php the_ID(); ?>" />
<input type="submit" value="Edit" />
</form>
SO网友:Iurie
经过一些学习和研究,我放弃了问题中描述的方法,事实上,我找到了如何使用@TheDeadMedic添加前端编辑功能的方法solution. 现在I have only two little questions:
1) 有没有更好的方法来使用/设置帖子ID和发布日期?我使用了两个隐藏输入:foo_id
和foo_date
.
2) 表单之间的通信有多安全?
这是将帖子ID获取到“postid”变量并将其传递到“post form”页面的表单:
<form action="<?php echo home_url( \'/post-form\'); ?>" method="post">
<input type="hidden" name="postid" value="<?php the_ID(); ?>" />
<input type="submit" value="Edit" />
</form>
<?php
这是用于发布编辑帖子的前端表单(我添加的代码标记为
// MY CODE
):
class WPSE_Submit_From_Front {
const NONCE_VALUE = \'front_end_new_post\';
const NONCE_FIELD = \'fenp_nonce\';
protected $pluginPath;
protected $pluginUrl;
protected $errors = array();
protected $data = array();
function __construct() {
$this->pluginPath = plugin_dir_path( __file__ );
$this->pluginUrl = plugins_url( \'\', __file__ );
add_action( \'wp_enqueue_scripts\', array( $this, \'addStyles\' ) );
add_shortcode( \'post_from_front\', array( $this, \'shortcode\' ) );
// Listen for the form submit & process before headers output
add_action( \'template_redirect\', array( $this, \'handleForm\' ) );
}
function addStyles() {
wp_enqueue_style( \'submitform-style\', "$this->pluginUrl/submitfromfront.css" );
}
/**
* Shortcodes should return data, NOT echo it.
*
* @return string
*/
function shortcode() {
if ( ! current_user_can( \'publish_posts\' ) )
return sprintf( \'<p>Please <a href="%s">login</a> to post links.</p>\', esc_url( wp_login_url( get_permalink() ) ) );
elseif ( $this->isFormSuccess() )
return \'<p class="success">Nice one, post created.</p>\';
else
return $this->getForm();
}
/**
* Process the form and redirect if sucessful.
*/
function handleForm() {
if ( ! $this->isFormSubmitted() )
return false;
// http://php.net/manual/en/function.filter-input-array.php
$data = filter_input_array( INPUT_POST, array(
// MY CODE
\'foo_id\' => FILTER_DEFAULT,
\'foo_date\' => FILTER_DEFAULT,
// END MY CODE
\'postTitle\' => FILTER_DEFAULT,
\'postContent\' => FILTER_DEFAULT,
\'location2\' => FILTER_DEFAULT,
));
$data = wp_unslash( $data );
$data = array_map( \'trim\', $data );
// You might also want to more aggressively sanitize these fields
// By default WordPress will handle it pretty well, based on the current user\'s "unfiltered_html" capability
$data[\'postTitle\'] = sanitize_text_field( $data[\'postTitle\'] );
$data[\'postContent\'] = wp_check_invalid_utf8( $data[\'postContent\'] );
$data[\'location2\'] = sanitize_text_field( $data[\'location2\'] );
$this->data = $data;
if ( ! $this->isNonceValid() )
$this->errors[] = \'Security check failed, please try again.\';
if ( ! $data[\'postTitle\'] )
$this->errors[] = \'Please enter a title.\';
if ( ! $data[\'postContent\'] )
$this->errors[] = \'Please enter the content.\';
if ( ! $this->errors ) {
$post_id = wp_insert_post( array(
// MY CODE
\'ID\' => $data[\'foo_id\'],
\'post_date\' => $data[\'foo_date\'],
// END MY CODE
\'post_title\' => $data[\'postTitle\'],
\'post_content\' => $data[\'postContent\'],
\'post_status\' => \'publish\',
));
if ( $post_id ) {
add_post_meta( $post_id, \'location2\', $data[\'location2\'] );
// Redirect to avoid duplicate form submissions
wp_redirect( add_query_arg( \'success\', \'true\' ) );
exit;
} else {
$this->errors[] = \'Whoops, please try again.\';
}
}
}
/**
* Use output buffering to *return* the form HTML, not echo it.
*
* @return string
*/
function getForm() {
// MY CODE
if( \'POST\' == $_SERVER[\'REQUEST_METHOD\'] && isset( $_POST[\'postid\'] ) ) {
$post_to_edit = array();
$post_to_edit = get_post( $_POST[\'postid\'] );
$this->data[\'foo_id\'] = $post_to_edit->ID;
$this->data[\'foo_date\'] = $post_to_edit->post_date;
$this->data[\'item_name\'] = $post_to_edit->post_title;
$this->data[\'item_description\'] = $post_to_edit->post_content;
}
// END MY CODE
ob_start();
?>
<div id ="frontpostform">
<?php foreach ( $this->errors as $error ) : ?>
<p class="error"><?php echo $error ?></p>
<?php endforeach ?>
<form id="formpost" method="post">
<fieldset>
<label for="postTitle">Post Title</label>
<input type="text" name="postTitle" id="postTitle" value="<?php
// "Sticky" field, will keep value from last POST if there were errors
if ( isset( $this->data[\'postTitle\'] ) )
echo esc_attr( $this->data[\'postTitle\'] );
?>" />
</fieldset>
<fieldset>
<label for="postContent">Content</label>
<textarea name="postContent" id="postContent" rows="10" cols="35" ><?php
if ( isset( $this->data[\'postContent\'] ) )
echo esc_textarea( $this->data[\'postContent\'] );
?></textarea>
</fieldset>
<fieldset>
<label for="location2">Location 2</label>
<input type="text" name="location2" id="location2" title="Location 2 (opțional)" value="<?php
// "Sticky" field, will keep value from last POST if there were errors
if ( isset( $this->data[\'location2\'] ) )
echo esc_attr( $this->data[\'location2\'] );
?>" />
</fieldset>
<fieldset>
// MY CODE
<input type="hidden" name="foo_id" id="foo_id" value="<?php
// "Sticky" field, will keep value from last POST if there were errors
if ( isset( $this->data[\'foo_id\'] ) )
echo esc_attr( $this->data[\'foo_id\'] );
?>" />
<input type="hidden" name="foo_date" id="foo_date" value="<?php
// "Sticky" field, will keep value from last POST if there were errors
if ( isset( $this->data[\'foo_date\'] ) )
echo esc_attr( $this->data[\'foo_date\'] );
?>" />
// END MY CODE
<button type="submit" name="submitForm" >Create Post</button>
</fieldset>
<?php wp_nonce_field( self::NONCE_VALUE , self::NONCE_FIELD ) ?>
</form>
</div>
<?php
return ob_get_clean();
}
/**
* Has the form been submitted?
*
* @return bool
*/
function isFormSubmitted() {
return isset( $_POST[\'submitForm\'] );
}
/**
* Has the form been successfully processed?
*
* @return bool
*/
function isFormSuccess() {
return filter_input( INPUT_GET, \'success\' ) === \'true\';
}
/**
* Is the nonce field valid?
*
* @return bool
*/
function isNonceValid() {
return isset( $_POST[ self::NONCE_FIELD ] ) && wp_verify_nonce( $_POST[ self::NONCE_FIELD ], self::NONCE_VALUE );
}
}
new WPSE_Submit_From_Front;