Custom page for editing custom post type on frontend based on url

I have created a custom post type nammed job. The users will have the posibility to create/read/update/delete their posts from frontend. I created a shortcode with a form for post creating, which is working fine, the jobs are adding and they can be accesed on the generic url site_domain/jobs/job_title.

Now I want to implement the job edit page which will be available on the previous url with /edit/ concatenated, like site_domain/jobs/job_title/edit/.

How can i create another page template/shortcode which will be used only if the user is accessing this endpoint ?

Topic post-editor page-template custom-post-types Wordpress

Category Web


You can add custom url structures with add_rewrite_rule for example the proposed structure in your question can be achieved with something like...

add_action( 'init', function() {
    add_rewrite_rule( '^jobs/([^/]+)/edit/?$', 'index.php?post_type=jobs&name=$matches[1]', 'top' );
} );

So now if you visited https://example.com/jobs/job-title-example/edit/ you should see exactly the same as if you were to visit https://example.com/jobs/job-title-example/ this is because we're telling WordPress to handle the request in a similar way by passing the post_type and name as query parameters. Essentially the same as visiting https://example.com/?post_type=jobs&name=job-title-example.

However, it might be a good idea to build the rewrite rule dynamically based off of the post type properties, something like...

add_action( 'init', function() {
    
    if ( $post_type = get_post_type_object( 'job' ) ) {
        $rewrite = !empty( $post_type->rewrite ) && is_array( $post_type->rewrite ) ? $post_type->rewrite : [];
        $with_front = !empty( $rewrite[ 'with_front' ] ) ? $rewrite[ 'with_front' ] : false;
        $slug = !empty( $rewrite[ 'slug' ] ) ? $rewrite[ 'slug' ] : null;
        $slug = $slug ?: $post_type->name;

        $front = '';

        if ( $with_front ) {
            $permalink_structure = get_option( 'permalink_structure' );
            $front = substr( $permalink_structure, 0, strpos( $permalink_structure, '%' ) );
        }

        $slug = $front ? '/' . $slug : $slug;

        add_rewrite_rule( '^' . $front . $slug . '/([^/]+)/edit/?$', 'index.php?post_type=' . $post_type->name . '&name=$matches[1]', 'top' );
    }

}, PHP_INT_MAX );

So now if you change your jobs post type rewrite properties the rewrite rule above will adapt automatically.

Always remember to flush your rewrite rules if making any changes.

I would also concider adding a custom query var to use in templates, like so...

add_filter( 'query_vars', function( $vars ) {
    $vars[] = 'frontend_editor';
    return $vars;
} );

And add to your rewrite rule with &frontend_editor=1 like so...

add_action( 'init', function() {
    
    if ( $post_type = get_post_type_object( 'job' ) ) {
        $rewrite = !empty( $post_type->rewrite ) && is_array( $post_type->rewrite ) ? $post_type->rewrite : [];
        $with_front = !empty( $rewrite[ 'with_front' ] ) ? $rewrite[ 'with_front' ] : false;
        $slug = !empty( $rewrite[ 'slug' ] ) ? $rewrite[ 'slug' ] : null;
        $slug = $slug ?: $post_type->name;

        $front = '';

        if ( $with_front ) {
            $permalink_structure = get_option( 'permalink_structure' );
            $front = substr( $permalink_structure, 0, strpos( $permalink_structure, '%' ) );
        }

        $slug = $front ? '/' . $slug : $slug;

        // We added `frontend_editor` parameter here.
        add_rewrite_rule( '^' . $front . $slug . '/([^/]+)/edit/?$', 'index.php?post_type=' . $post_type->name . '&name=$matches[1]&frontend_editor=1', 'top' );
    }

}, PHP_INT_MAX );

This is essentially the same as visiting:

https://example.com/jobs/job-title-example/?frontend_editor=1

Or

https://example.com/?post_type=jobs&name=job-title-example&frontend_editor=1

In theory you should now be able to update your template to show the editor, for example...

single-jobs.php

<?php get_header(); ?>

<!-- Check if user is authorised to edit current job -->
<?php if ( is_user_logged_in() && (int)get_post_field( 'post_author', get_the_ID() ) === get_current_user_id() ): ?>

    <!-- Check for our edit parameter -->
    <?php if ( get_query_var( 'frontend_editor', false ) ): ?>

        <form action="">
            ...
        </form>

    <?php endif ?>
<?php endif ?>

<?php get_footer(); ?>

I think that should be enough to point you in the right direction. Please note that none of the above code has been tested!

About

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