How to make Guest post on Wordpress Frontend - wordpress

Here is the code that I find to create a Form on the frontend page in WordPress to allow guests (visitors) to publish posts on the Blog section without logging in.
it has actually 3 steps and I applied it on WordPress Theme twenty twenty-two default theme.
but unfortunately, the Form shortcode does not apply to my mentioned section and it applies after my Body
tag (no matter where I callback the shortcode in Gutenberg).
So I have no idea about the Solution :(
Note: I don't want to do this by using any type of plugin... I know it sounds crazy but no plugin, please...
Step 1:
add bellow code to end line of my functions.php in 2022 WordPress Theme
//Add Shortcode-Form
require get_template_directory() . '/shortcode-form.php';
Step 2: Create shortcode-form.php file in theme's main folder
Step 3: add bellow lines to it:
add_shortcode( 'themedomain_frontend_post', 'themedomain_frontend_post' );
function themedomain_frontend_post() {
themedomain_post_if_submitted(); ?>
<form id="new_post" name="new_post" method="post" enctype="multipart/form-data">
<p><label for="title"><?php echo esc_html__( 'Title', 'theme-domain' ); ?></label><br />
<input type="text" id="title" value="" tabindex="1" size="20" name="title" />
</p>
<?php wp_editor( '', 'content' ); ?>
<p><?php wp_dropdown_categories( 'show_option_none=Category&tab_index=4&taxonomy=category' ); ?></p>
<p><label for="post_tags"><?php echo esc_html__( 'Tags', 'theme-domain' ); ?></label>
<input type="text" value="" tabindex="5" size="16" name="post_tags" id="post_tags" />
</p>
<input type="file" name="post_image" id="post_image" aria-required="true">
<p><input type="submit" value="Publish" tabindex="6" id="submit" name="submit" /></p>
</form>
<?php
}
and:
function themedomain_post_if_submitted() {
// Stop running function if the form wasn't submitted
if ( ! isset( $_POST['title'] ) ) {
return;
}
// Add the content of the form to $post as an array
$post = array(
'post_title' => $_POST['title'],
'post_content' => $_POST['content'],
'post_category' => array( $_POST['cat'] ),
'tags_input' => $_POST['post_tags'],
'post_status' => 'draft', // Could be: publish
'post_type' => 'post', // Could be: 'page' or your CPT
);
$post_id = wp_insert_post( $post );
// For Featured Image
if ( ! function_exists( 'wp_generate_attachment_metadata' ) ) {
require_once ABSPATH . 'wp-admin' . '/includes/image.php';
require_once ABSPATH . 'wp-admin' . '/includes/file.php';
require_once ABSPATH . 'wp-admin' . '/includes/media.php';
}
if ( $_FILES ) {
foreach ( $_FILES as $file => $array ) {
if ( $_FILES[ $file ]['error'] !== UPLOAD_ERR_OK ) {
return 'upload error : ' . $_FILES[ $file ]['error'];
}
$attach_id = media_handle_upload( $file, $post_id );
}
}
if ( $attach_id > 0 ) {
update_post_meta( $post_id, '_thumbnail_id', $attach_id );
}
echo 'Saved your post successfully! :)';
}
Here is the shortcode that I use in my gotenburg theme editor:
[themedomain_frontend_post]

Actually WordPress shortcode should run its own callback function, so it except a return variable. In this case you have echo inside callback function, that's why all the output comes at top of the page
Please try the code like bellow
add_shortcode( 'themedomain_frontend_post', 'themedomain_frontend_post' );
function themedomain_frontend_post() {
ob_start();
themedomain_post_if_submitted();
$return = "<form id='new_post' name='new_post' method='post' enctype='multipart/form-data'>
<p><label for='title'>" . esc_html__('Title','theme-domain') . "</label><br />
<input type='text' id='title' value='' tabindex='1' size='20' name='title' />
</p>". wp_editor( '', 'content' ) ."
<p>" . wp_dropdown_categories( 'show_option_none=Category&tab_index=4&taxonomy=category' ) ."</p>
<p><label for='post_tags'>" . esc_html__('Tags','theme-domain') . "</label>
<input type='text' value='' tabindex='5' size='16' name='post_tags' id='post_tags' /></p>
<input type='file' name='post_image' id='post_image' aria-required='true'>
<p><input type='submit' value='Publish' tabindex='6' id='submit' name='submit' /></p>
</form>";
$return .= ob_get_clean();
return $return;
}
it will solve the issue.

Related

How to properly sanitize user input in WordPress search form: get_search_query()

I am attempting to sanitize user input for a search form that I am building in WordPress (in searchform.php file).
I used a built-in WordPress function, sanitize_text_field():
function wpdocs_my_search_form( $form ) {
$search_query = sanitize_text_field( get_search_query() );
$form = '<form role="search" method="get" id="searchform" class="searchform" action="' . home_url( '/' ) . '" >
<div><label class="screen-reader-text" for="s">' . __( 'Search for:' ) . '</label>
<input type="text" value="' . $search_query . '" name="s" id="s" />
<input type="submit" id="searchsubmit" value="'. esc_attr__( 'Search' ) .'" />
</div>
</form>';
return $form;
}
add_filter( 'get_search_form', 'wpdocs_my_search_form' );
This however, is still not properly sanitizing input such as <script></script>
I also attempted to add additional code to detect if it has been submitted however, that is also not working. I would appreciate any direction/pointers.

Use existing tags on Wordpress front-end posting

I have a front end posting to allow users to update their posts. Currently I'm using this to allow entering new tags:
This is my HTML form:
<form id="featured_upload" method="post" action="#" enctype="multipart/form-data">
<input type="file" name="new_image_upload" id="new_image_upload" multiple="false" />
<input type="text" name="newtags" id="newtags" value="" />
<input type="hidden" name="post_id" id="post_id" value="" />
<?php wp_nonce_field( 'new_image_upload', 'new_image_upload_nonce' ); ?>
<input id="submit_new_image_upload" name="submit_new_image_upload" type="submit" value="Upload" />
</form>
This is part of the code:
// If the form has been submitted with new tags
if ( isset( $_POST['newtags'] ) ) {
// get existing tags
$post_tags = get_the_tags();
// concatenates both existing and new tags
$concatenated_tags = array($post_tags, sanitize_text_field($_POST['newtags']));
// Add all the tags to the post
wp_set_post_tags(get_the_ID(), $concatenated_tags , true );
}
The problem with this is that is creating many unecessary tags on my database and I need my users to see the sugestion of tags already present in my database.
So, I need that <input type="text" name="newtags" id="newtags" value="" /> make them existing tags sugestions, just like wordpress does on the post editing backend. See the image bellow to check the desired result on my front-end form:
I would recommend using Select2 javascript library for the frontend, specifically the automatic tokenization tagging functionality. See here: https://select2.org/tagging#automatic-tokenization-into-tags
Once you have enqued the Select2 file into your frontend you could do something like...
Your frontend form:
Note that I have added the $has_tag variable which will automatically select all saved tags for the current post. See selected()
<?php $post_id = get_the_ID(); ?>
<form id="featured_upload" method="post" action="#" enctype="multipart/form-data">
...
<input type="hidden" name="post_id" value="<?= $post_id; ?>">
<select name="tags" multiple id="frontend-tagger">
<?php if ( $tags = get_terms( [ 'taxonomy' => 'post_tag', 'hide_empty' => false ] ) ): ?>
<?php foreach ( $tags as $tag ): ?>
<?php $has_tag = selected( has_tag( $tag->term_id, $post_id ), true, false ); ?>
<option value="<?= $tag->name; ?>"<?= $has_tag; ?>><?= $tag->name; ?></option>
<?php endforeach ?>
<?php endif ?>
</select>
...
</form>
JS to initiate the select2 field:
$( '#frontend-tagger' ).select2( {
tags: true,
tokenSeparators: [ ',' ]
} );
Saving process: Note because we are now including already saved tags in the pay load, we do not need to concat existing tags. We can now change the third paramater for wp_set_post_tags to false as we do not need to append tags.
$post_id = !empty( $_POST[ 'post_id' ] ) : (int)$_POST[ 'post_id' ] : null;
if ( isset( $_POST[ 'tags' ] ) ) {
// Sanitize array values
$tags = array_map( 'sanitize_text_field', $_POST[ 'tags' ] );
wp_set_post_tags( $post_id, $tags , false );
}
The above code hasn't been test, just a starting point for you to work from.
Hope this helps!

Custom WordPress search with multiple text fields

I need to create a custom WordPress search form, with multiple text input fields. Each text field should search its corresponding meta key. Frontend would look like this:
Search form:
<form role="search" action="/" method="get" id="searchform">
<input type="text" name="s" placeholder="Name"/>
<input type="text" name="hometown" placeholder="Hometown"/>
<input type="text" name="branch" placeholder="Branch of Service"/>
<input type="text" name="birth" placeholder="Birth Year"/>
<input type="text" name="casualty" placeholder="Casualty Year"/>
<input type="text" name="location" placeholder="Casualty Location">
<input type="hidden" name="post_type" value="veterans" />
<input type="submit" alt="Search" value="Search" />
</form>
The "Name" field should search the post title only. The rest of the input fields would search a specific custom meta key. It would use an "AND" relationship when multiple fields are used.
Is this possible? Here is what I have tried, but it doesn't search if the name ("s") is empty, and it doesn't seem to be affected at all by what I enter into the custom fields for Hometown or Branch.
// register query vars
function sm_register_query_vars( $vars ) {
$vars[] = 'hometown';
$vars[] = 'branch';
return $vars;
}
add_filter( 'query_vars', 'sm_register_query_vars' );
// pre get posts
function sm_pre_get_posts( $query ) {
if ( is_admin() || ! $query->is_main_query() ){
return;
}
if ( !is_post_type_archive( 'veterans' ) ){
return;
}
$meta_query = array();
// add meta_query elements
if( !empty( get_query_var( 'hometown' ) ) ){
$meta_query[] = array( 'key' => 'hometown', 'value' => get_query_var( 'hometown' ), 'compare' => 'LIKE' );
}
if( !empty( get_query_var( 'branch' ) ) ){
$meta_query[] = array( 'key' => 'branch', 'value' => get_query_var( 'branch' ), 'compare' => 'LIKE' );
}
if( count( $meta_query ) > 1 ){
$meta_query['relation'] = 'AND';
}
if( count( $meta_query ) > 0 ){
$query->set( 'meta_query', $meta_query );
}
}
add_action( 'pre_get_posts', 'sm_pre_get_posts', 1 );
// the search form (display via shortcode)
function sm_search_form( $args ){
$output = '<form id="smform" action="' . esc_url( home_url() ) . '" method="GET" role="search">';
$output .= '<div class="smtextfield"><input type="text" name="s" placeholder="Name" value="' . get_search_query() . '" /></div>';
$output .= '<div class="smtextfield"><input type="text" name="hometown" placeholder="Hometown" value="' . get_search_query() . '" /></div>';
$output .= '<div class="smtextfield"><input type="text" name="branch" placeholder="Branch" value="' . get_search_query() . '" /></div>';
$output .= '<input type="hidden" name="post_type" value="veterans" />';
$output .= '<p><input type="submit" value="Search" class="button" /></p></form>';
return $output;
}
The above query looks like this when attempting to search:
site.com/?s=john+doe&branch=army&hometown=new+york&post_type=veterans
After checking if there are any terms in your search by something like
if($_GET['myfield'])...
try storing each type of your search in a var and then build a custom query with all the items that are in your search. ie :
<?php
$title=$_GET['name']; // Get the name
$params=[]; // Create an array with all the parameters you've got except the name
function populate_array($term) // Create a function to populate your array
{
if ($_GET[$term]) {
$params[$term] = $_GET[$term];
}
}
populate_array('hometown');
populate_array('branch');
//(...)
$args=array( // Initialize your query
'post_type' => 'my_post_type', // Just set your post type if needed
);
if($title){ // If there is a title add it to the query
$args['title']=$title;
}
if(count($params)>0){. // If there are any params
$meta=array('relation'=>'AND'); // Because you asked for it
foreach($params as $param => $value){
$meta[]=array( // Adding each meta tou your query
'key' => $param, // considering you name your meta as your parameter
'value' => $value,
'compare' => '='
);
}
$args['meta_query']=$meta; // Adding your meta to your main query
}
$query = new WP_Query( $args ); // And now you can request your query with all your parameters
I have not tested this but it should work... Maybe some improvements are needed. Test it and come back to me :)

Create a New User via Form in Wordpress

I am trying to create a page-template on wordpress that allows me to create a new user through a form on the front end of the website. Basically I want it to be laid out like how it currently is on the wordpress admin page but I need to make it work on the frontend.
(Layout would look like this)wordpress admin create new user page
The part that I'm stuck now is, when the user presses submit how can I handle the data and add it into the wordpress db? (Using this https://codex.wordpress.org/Function_Reference/wp_create_user)
(Code so far...) -
<?php
/**
* Template Name: Create User
*/
get_header('user');
?>
<?php // Start the Loop.
while ( have_posts() ) : the_post(); ?>
<div id="left-content">
<?php //GET THEME HEADER CONTENT
theme_title(get_the_title()); ?>
<!-- START CONTENT -->
<div id="content">
<?php if (woffice_is_user_allowed()) { ?>
<!-- PHP Create User -->
<?php
function add_user_from_form() {
$user_login = $_POST['email'];
$first_name = $_POST['fName'];
$last_name = $_POST['lName'];
$user_email = $_POST['email'];
$user_pass = $_POST['pass'];
$display_name = "{$first_name} {$last_name}";
$role = $_POST['role'];
$info = array(
'user_login' => $user_login,
'user_pass' => $user_pass,
'user_email' => $user_email,
'display_name' => $display_name,
'first_name' => $first_name,
'last_name' => $last_name,
'role' => $role
);
$result = wp_insert_user( $info )
if ( is_wp_error( $result ) ) {
echo $result->get_error_message();
} else {
echo "Added user {$result}";
}
}
?>
<div class="box">
<form id="create-user-form" method="POST" action="<?php echo $_SERVER['PHP_SELF']?>">
<div class="row">
<div class="col-md-12">
<input value="" name="fName" id="fName" placeholder="First Name" required="" type="text">
<input value="" name="lName" id="lName" placeholder="Last Name" required="" type="text">
<input value="" name="email" id="email" placeholder="Email" required="" type="text">
<input value="" name="pass" id="password" placeholder="Password" required="" type="Password">
<select name="role">
<option value="author">Author</option>
<option value="contributor">Contributor</option>
</select>
<input name="submit" type="submit" class="btn-ser" value="Create New User" style="width:160px !important; padding-left:18px;">
</div>
</div>
</form>
</div>
<?php } else {
get_template_part( 'content', 'private' );
}
?>
</div>
</div><!-- END #content-container -->
<?php theme_scroll_top(); ?>
</div><!-- END #left-content -->
<?php // END THE LOOP
endwhile; ?>
If you want to insert the data in the WP db, you can use the WP database API.
You can include the global wpdb object in your code to post the form data in your database.
global $wpdb;
Then use the insert function to post the data in db.
<?php $wpdb->insert( $table, $data, $format ); ?>
Check this link for more details : https://codex.wordpress.org/Class_Reference/wpdb#INSERT_rowenter link description here
Create a function in your functions.php like below to handle your post data:
function my_theme_send_email() {
if ( isset( $_POST['email-submission'] ) && '1' == $_POST['email-submission'] ) {
// Send the email...
} // end if
} // end my_theme_send_email
add_action( 'init', 'my_theme_send_email' );
Refer this link as well they have explained very nicely : https://tommcfarlin.com/sending-data-post/
Users need a login name for database. Login can be anything. Users do not need to know it, because users can login with email address.
I would use wp_insert_user().
Example:
function add_user_from_form() {
$now = time(); // unique number
$c = chr( ($now % 26) + 65 ); // random letter
$user_login = $c . strval( $now ); // unique user name
$first_name = $_POST['fName'];
$last_name = $_POST['lName'];
$user_email = $_POST['email'];
$user_pass = $_POST['pass'];
$display_name = "{$first_name} {$last_name}";
/*
VALIDATE USER DATA BEFORE ADDING TO DATABASE
*/
$info = array('user_login' => $user_login,
'user_pass' => $user_pass,
'user_email' => $user_email,
'display_name' => $display_name,
'first_name' => $first_name,
'last_name' => $last_name);
$result = wp_insert_user( $info )
if ( is_wp_error( $result ) ) {
echo $result->get_error_message();
} else {
echo "Added user {$result}";
}
}
Simplest way use this on a page is to create a template with a different header and process form on the same page.
E.g. Copy page.php to create-user.php and add the template header.
Copy header.php to header-user.php. Replace get_header() with
get_header('user').
Edit action on form:
<form id="my-registration-form" method="post" action="<?php echo $_SERVER['PHP_SELF']">
Add my function to the top of header with:
if ( 'POST` == $_SERVER['REQUEST_METHOD'] ) {
add_user_from_form();
}
You do not need an action. You just need to process form.
This does not conform to best practice of using MVC pattern, but it is easy and it will work.
Hope this clarifies earlier answer.

WordPress Creating Front end posting plugin

I try to create a plugin allow users to add new post, edit post, and delete post from the front end.
Now when the user try to edit the post instead of updating the the same post the plugin create new page ! in pending status.
Can anyone help me please?
This is the code of edit post class:
<?php
/**
* Edit Post form class
*
* #author Engr.MTH
* #package MOSTASHAROON Frontend Form
*/
class MOSFF_Edit_Post {
function __construct() {
add_shortcode( 'mosff_editpost', array($this, 'shortcode') );
}
/**
* Handles the edit post shortcode
*
*
*/
function shortcode() {
$query = new WP_Query(array('post_type' => 'post', 'posts_per_page' =>'-1', 'post_status' => array('publish', 'pending', 'draft', 'private', 'trash') ) );
if ($query->have_posts()) : while ($query->have_posts()) : $query->the_post();global $post;
if(isset($_GET['post'])) {
if($_GET['post'] == $post->ID)
{
$current_post = $post->ID;
$title = get_the_title();
$content = get_the_content();
$custom_one = get_post_meta($current_post, 'vsip_custom_one', true);
$custom_two = get_post_meta($current_post, 'vsip_custom_two', true);
}
}
endwhile; endif;
wp_reset_query();
global $current_post;
$postTitleError = '';
if(isset($_POST['submitted']) && isset($_POST['post_nonce_field']) && wp_verify_nonce($_POST['post_nonce_field'], 'post_nonce')) {
if(trim($_POST['postTitle']) === '') {
$postTitleError = 'Please enter a title.';
$hasError = true;
} else {
$postTitle = trim($_POST['postTitle']);
}
$post_information = array(
'ID' => $current_post,
'post_title' => esc_attr(strip_tags($_POST['postTitle'])),
'post_content' => esc_attr(strip_tags($_POST['postContent'])),
'post-type' => 'post',
'post_status' => 'pending'
);
$post_id = wp_update_post($post_information);
if($post_id)
{
// Update Custom Meta
update_post_meta($post_id, 'vsip_custom_one', esc_attr(strip_tags($_POST['customMetaOne'])));
update_post_meta($post_id, 'vsip_custom_two', esc_attr(strip_tags($_POST['customMetaTwo'])));
wp_redirect( home_url() ); exit;
}
}
?>
<!-- #primary BEGIN -->
<div id="primary">
<form action="" id="primaryPostForm" method="POST">
<fieldset>
<label for="postTitle"><?php _e('Post\'s Title:', 'framework') ?></label>
<input type="text" name="postTitle" id="postTitle" value="<?php echo $title; ?>" class="required" />
</fieldset>
<?php if($postTitleError != '') { ?>
<span class="error"><?php echo $postTitleError; ?></span>
<div class="clearfix"></div>
<?php } ?>
<fieldset>
<label for="postContent"><?php _e('Post\'s Content:', 'framework') ?></label>
<textarea name="postContent" id="postContent" rows="8" cols="30"><?php echo $content; ?></textarea>
</fieldset>
<fieldset>
<label for="customMetaOne"><?php _e('Custom Meta One:', 'framework') ?></label>
<input type="text" name="customMetaOne" id="customMetaOne" value="<?php echo $custom_one; ?>" />
</fieldset>
<fieldset>
<label for="customMetaTwo"><?php _e('Custom Meta Two:', 'framework') ?></label>
<input type="text" name="customMetaTwo" id="customMetaTwo" value="<?php echo $custom_two; ?>" />
</fieldset>
<fieldset>
<?php wp_nonce_field('post_nonce', 'post_nonce_field'); ?>
<input type="hidden" name="submitted" id="submitted" value="true" />
<button type="submit"><?php _e('Update Post', 'framework') ?></button>
</fieldset>
</form>
</div><!-- #primary END -->
<?php }}
$mosff_editpostform = new MOSFF_Edit_Post();
I found the answer, just I remove this line:
global $current_post;
I think you can do this by getting the post id and query it to get all the fields of the particular and edit it through a form and post it again.
get more detailed article herekvcodes.

Resources