Add new post using a page inside the website

I have been searching for several hours to find a way to embed the "Add New Post" inside a page in the front end. I read this post but sadly no answer to it.

I have embedded the login form in another page called (example.com/user-login) and What I want is to have a page (example.com/add-post) which allows the person who logged in to publish a post in a page that is within the WordPress theme.

The same way as default method of publishing a post (example.com/wp-admin/post-new.php) but without going to the wordpress dashboard.

I have found several plugins that allow guest posts, but I want to person who logged in, be able to post.

Topic custom-field publish posts plugins Wordpress

Category Web


This is pretty simple. So simple you need to make sure your guests don't insert bad code into you DB. So read up on Data Validation and Validating Sanitizing and Escaping User Data before you add anything to your site from a front-end form.

  1. Create a new page at /new-post
  2. Create a page template to target that page
  3. Setup AJAX actions
  4. Render your form inside the custom page template.
  5. Use jQuery to submit the form details to AJAX
  6. AJAX action will validate the data
  7. If good, the new post will be created
  8. AJAX will output a success or fail response
  9. jQuery on the front-end form will inform the user of success or failure.

First, create a page called new-post that will hold your form. Then create a page template to target that page using the file structure page-{slug}.php.

page-new-post.php

On that page you can check to see if is_user_logged_in and if they have the ability to create posts using current_user_can. If not, you can always wp_redirect elsewhere or just wp_die.

You'll need to do all this with AJAX so create a front-end form that when clicked; submits data to WP, validates, and creates a new post.

Take note of _nopriv which you don't want to use in your case because someone will SPAM your site to a crawl.

// AJAX for logged in users

add_action( 'wp_ajax_create_new_post', 'ajax_create_new_post_action' );

// AJAX for non-logged in users

add_action( 'wp_ajax_nopriv_create_new_post', 'ajax_nopriv_create_new_post_action' );

Once you've collected the data and sanitized it in your ajax_create_new_post_action then you'll need to create a new post with wp_insert_post.


Since there are quite a few steps involved I recommend generating most of this automatically using WP Secure Forms and filling in the gaps after. Here is an example of an AJAX email submission form to give you a pretty good overview of the AJAX parts -- including sanitization.

Template for WP Secure Forms

Title {30 characters limit}
> * 30
| Your Title
! Field specific error message


Textarea{150 characters limit}
> 150
| Content
|
|
! Field specific error message


This label is invisible
> H

Form

This script goes into the PHP file of your theme.

<p id="wpse_form_message_wrap" class="secureforms-message-wrap"></p>

<form id="wpse_form" method="post">

  <div id="wpse_form_10000-wrapper">
    <label for="wpse_form_10000">* Title <span>30 characters limit</span></label>
    <input type="text" name="wpse_form_10000" id="wpse_form_10000" value="" placeholder="Your Title" required="required" maxlength="30"  />
    <p class="secureforms-error-msg">Field specific error message</p>
  </div>

  <div id="wpse_form_20000-wrapper">
    <label for="wpse_form_20000">Textarea{150 characters limit}</label>
    <textarea rows="3" name="wpse_form_20000" id="wpse_form_20000" value=""  maxlength="150" ></textarea>
    <p class="secureforms-error-msg">Field specific error message</p>
  </div>

  <div id="wpse_form_30000-wrapper" class="secureforms-hidden-wrapper">
    <input id="wpse_form_30000" name="wpse_form_30000"  type="hidden">
  </div>

  <div id="wpse_form_footer">
    <input type="hidden" id="check_wpse_form" name="check_wpse_form" value="" />
    <input type="hidden" name="action" value="wpse_form" />
    <?php echo wp_nonce_field('wpse_form', '_nonce_eklwu', true, false); ?>
    <input type="submit" name="wpse_form_submit_btn" id="wpse_form_submit_btn" value="Submit" />
  </div>

</form>

Functions.php

This one goes into your functions.php

// WP SECURE FORMS - EMAIL VALIDATION & SENDING 

require_once( 'ajax/wpse_form.php' );

// WP SECURE FORMS - ENQUEUE EMAIL JS 

function enqueue_ajax_wpse_form() {

  if (!is_admin()) {
    wp_enqueue_script( 'ajax_wpse_form', get_template_directory_uri().'/ajax/wpse_form.js', array('jquery'), '', true );
    wp_localize_script( 'ajax_wpse_form', 'ajax_wpse_form', array( 'ajax_url' => admin_url( 'admin-ajax.php' ) ) );
  }
}

add_action( 'wp_enqueue_scripts', 'enqueue_ajax_wpse_form', 999 );

Validation

In your theme folder create an "ajax" folder with the file named wpse_form.php. Paste into it the code below.

<?php 

function ajax_wpse_form_action() { 

if ($_SERVER["REQUEST_METHOD"] == "POST"){ 

  $return_message = '';
  $status = 'success';
  $fields_with_errors = array(); 

  // validate nonce
  if(!wp_verify_nonce($_POST['_nonce_eklwu'], $_POST['action'])){
    $status = 'error';
  }

  // validate hidden field
  if(!empty(trim($_POST['check_wpse_form']))){
    $status = 'error';
  }

  if ($status == 'error') {
    $return_message = 'Data verification error. Check marked fields.';
  } else {

    $wpse_form_10000 = strip_tags(trim(stripslashes($_POST['wpse_form_10000'])));

    if(!empty($wpse_form_10000)){
      if(strlen($wpse_form_10000) > 30){
        $status = 'error';
        $fields_with_errors[] = 'wpse_form_10000';
      }
    } else {
      $status = 'error';
      $fields_with_errors[] = 'wpse_form_10000';
    }

    $wpse_form_20000 = strip_tags(trim(stripslashes($_POST['wpse_form_20000'])));

    if(!empty($wpse_form_20000)){
      if(strlen($wpse_form_20000) > 150){
        $status = 'error';
        $fields_with_errors[] = 'wpse_form_20000';
      }
    }

    $wpse_form_30000 = strip_tags(trim(stripslashes($_POST['wpse_form_30000'])));
    if ($status == 'error') {
      $return_message = 'Data verification error. Check marked fields.';
    } else {

      // message
      $to = '[email protected]';
      $header = 'From: '. get_bloginfo('name') . ' <[email protected]>'.PHP_EOL;
      $subject = 'Test Email Subject';
      $formMessage = '';

      $formMessage .= 'Title {30 characters limit}' . "\n";
      $formMessage .= $wpse_form_10000 . "\n\n";
      $formMessage .= 'Textarea{150 characters limit}' . "\n";
      $formMessage .= $wpse_form_20000 . "\n\n";
      $formMessage .= 'This label is invisible' . "\n";
      $formMessage .= $wpse_form_30000 . "\n\n";
      if ( wp_mail($to, $subject, $formMessage, $header) ) {
        $return_message = 'Thank you for contacting us. We will get in touch as soon as possible.';
      } else {
        $status = 'error';
        $return_message = 'There was an error sending the message. Please try again.';
      }
    }
  }

  $resp = array(
    'status' => $status,
    'return_message' => $return_message,
    'fields_with_errors' => $fields_with_errors,
  );

  header( "Content-Type: application/json" );
  echo json_encode($resp);
  die();

} else {
  http_response_code(403);
}
}

add_action( 'wp_ajax_wpse_form', 'ajax_wpse_form_action' );
add_action( 'wp_ajax_nopriv_wpse_form', 'ajax_wpse_form_action' );

AJAX

In your theme folder create an "ajax" folder with the file named wpse_form.js. Paste into it this code.

jQuery(document).ready(function($) {

  var wpse_form_btn = $('#wpse_form_submit_btn');

  function init_wpse_form(){

    /* VARS */

    var form = $('#wpse_form'),
      type = form.attr('method'),
      requiredFields = ['wpse_form_10000 | textline'];

    /* FUNCTIONS */

    function showErrors(fieldsWithErrors){

      form.find('.hasError').removeClass('hasError').end().find('.secureforms-error-msg.active').removeClass('active');

      for(var i=0; i< fieldsWithErrors.length; i++){
        if(fieldsWithErrors[i].length > 0){
          $('#' + fieldsWithErrors[i]).addClass('hasError').next().addClass('active');
        }
      }
    }

    /* TRIGGER */

    wpse_form_btn.on('click', function(e){

      e.preventDefault();
      e.stopPropagation();

      if($('#check_wpse_form').val()){
        return false;
      } else {

        var emptyErrors = [];

        for(var i = 0; i<requiredFields.length; i++){

          var fieldData = requiredFields[i].split(' | '),
            field = $('#' + fieldData[0]),
            fieldType = fieldData[1];

          if(fieldType == 'select'){
            var selected = field.find(':selected');
            if(selected.length > 0){
              if(selected.val() == 'wpse_form_select_null'){
                emptyErrors.push(fieldData[0]);
              }
            } else {
              emptyErrors.push(fieldData[0]);
            }
          } else if(fieldType == 'radio' || fieldType == 'checkbox'){
            if(field.find('input:checked').length <= 0){
              emptyErrors.push(fieldData[0]);
            }
          } else {
            if(!field.val()){
              emptyErrors.push(fieldData[0]);
            }
          }
        }

        if(emptyErrors.length > 0){
          showErrors(emptyErrors);
          $('#wpse_form_message_wrap').removeClass('success').addClass('error').text('Please fill all the required fields');
          return false;
        } else {

          var data = form.serialize();
          $.ajax({
            type: type,
            url: ajax_wpse_form.ajax_url,
            data: data,
            dataType: 'json',
            success: function(response) {

              if (response.status == 'success') {
                $('#wpse_form_message_wrap')
                  .removeClass('error')
                  .addClass('success')
                  .text(response.return_message);

                showErrors([]);

              } else {
                $('#wpse_form_message_wrap')
                  .removeClass('success')
                  .addClass('error')
                  .text(response.return_message);

                showErrors(response.fields_with_errors);
              }
            },
            error: function(xhr,err){
              console.log("readyState: "+xhr.readyState+"\
status: "+xhr.status);
              console.log("responseText: "+xhr.responseText);
            }
          })
        }
      }
    });
  };

  if(wpse_form_btn.length > 0){
    init_wpse_form();
  }

});

JS

Paste this code into your theme's main js file.

$('body').on('click', 'input[type=radio]', function(){

  var wrapper = $(this).parent(),
    triggers = wrapper.find('.isTrigger');

  if(triggers.length > 0){
    triggers.each(function(){
      if($(this).is(':checked')){
        $('.' + $(this).attr('data-toggle')).slideDown(200);
      } else {
        $('.' + $(this).attr('data-toggle')).slideUp(200);
      }
    })
  }

})

$('body').on('click', 'input[type=checkbox]', function(){

  var that = $(this),
    wrapper = that.parent(),
    limit = wrapper.attr('data-limit'),
    chosen = wrapper.find('input:checked').length;

  // disabling / enabling choices
  if(that.is(':checked')){
    if(chosen + 1 > limit){
      wrapper.find('input').not(':checked').prop('disabled', true);
    }
  } else {
    wrapper.find('input').prop('disabled', false);
  }

  // conditional showing / hiding fields
  if(that.hasClass('isTrigger')){

    var targetClass = that.attr('data-toggle');

    if(that.is(':checked')){
      $('.' + targetClass).slideDown(200);
    } else {
      $('.' + targetClass).slideUp(200);
    }
  }
})

$('body').on('change', 'select', function(){

  var  that = $(this),
    wrapper = that.parent(),
    triggers = wrapper.find('.isTrigger'),
    options = wrapper.find('option');

  if(triggers.length > 0){
    options.each(function(){
      if($(this).is(':selected')){
        if($(this).hasClass('isTrigger')){
          $('.' + $(this).attr('data-toggle')).slideDown(200);
        }
      } else {
        if($(this).hasClass('isTrigger')){
          $('.' + $(this).attr('data-toggle')).slideUp(200);
        }
      }
    })
  }
})

CSS

Paste the code below into your theme's main css file.

form>div, form>p{
  margin-top: 0;
  margin-bottom: 1em;
}
form fieldset {
  margin: 0;
  border: none;
  padding: 0;
}
form label, form legend{
  display: block;
  margin-bottom: .25em;
}
form label span, form legend span{
  font-size: .8em;
  font-style: italic;
}
form label span::before, form legend span::before{
  content: '';
  display: block;
}
input[type="checkbox"]+label, input[type="radio"]+label, input[type="number"]+label{
  display: inline-block;
}
form .showOnTrigger{
  display: none;
}
.secureforms-error-msg{
  display: none;
  color: red;
}
.secureforms-error-msg.active{
  display: block;
}
.secureforms-hidden-wrapper{
  display: none;
}
.secureforms-message-wrap.error{
  border: 2px solid red;
}
.secureforms-message-wrap.success{
  border: 2px solid green;
}

You have never read the WP documentation?

Create any template and form and when submitting the form it could be

Example:

$args = array('post_type'=>'post', 'post_title'=>'your title', 'post_status'=>'publish', 'post_content'=>'post content');

wp_insert_post ($args);

This will allow any post page or custom post type to insert the post

About

Geeks Mental is a community that publishes articles and tutorials about Web, Android, Data Science, new techniques and Linux security.