1

In my plugin, I want to be able to catch a slug - say 'testpath', as in www.mysite.com/testpath and output whatever I want from my plugin into the page.

I in WP Admin I could create a page called 'testpath', and put a shortcode in it (say, [testpath]), which is then implemented by the plugin, but I don't want the user of the plugin to have to create that page and enter the shortcode - it should all be handled by the plugin.

I can also create a post programmatically on plugin activation, then intercept it in the plugin, like

function create_custom_page($page_name) {
  $pages = get_pages();     
  foreach ($pages as $page) { 
    if ($page->post_name == $page_name) return;
  }
  wp_insert_post ([
  'post_type' =>'page',        
  'post_name' => $page_name,
  'post_status' => 'publish',
  ]);
}

And then:

add_filter( 'page_template', 'add_test_template' );
function add_test_template( $page_template ) {
  if ( is_page( 'testpath' ) ) {
    $page_template = __DIR__.'/testpath.html';
  }
  return $page_template;
}

This works as I want - but it seems very kludgy. I'm thinking something with the Rewrite API or appropriate actions might be a better way to go. Are there any standard (or clever) approaches to this?

5
<?php
/*
Plugin Name: Custom output
Description: A module to test the custom output. To test: http://your_wordpress_site.com/customop_uri_path
Version: 1.0
Author: Danilo Silva
Author URI: http://danilocgsilva.me
*/

// Write a new permalink entry on code activation
register_activation_hook( __FILE__, 'customop_activation' );
function customop_activation() {
        customop_custom_output();
        flush_rewrite_rules(); // Update the permalink entries in the database, so the permalink structure needn't be redone every page load
}

// If the plugin is deactivated, clean the permalink structure
register_deactivation_hook( __FILE__, 'customop_deactivation' );
function customop_deactivation() {
        flush_rewrite_rules();
}


// And now, the code that do the magic!!!
// This code create a new permalink entry
add_action( 'init', 'customop_custom_output' );
function customop_custom_output() {
        add_rewrite_tag( '%customop_uri_path%', '([^/]+)' );
        add_permastruct( 'customop_uri_path', '/%customop_uri_path%' );
}

// The following controls the output content
add_action( 'template_redirect', 'customop_display' );
function customop_display() {
        if ($query_var = get_query_var('customop_uri_path')) {
                header("Content-Type: text/plain");
                echo 'This is my custom content!!!!';
                exit; // Don't forget the exit. If so, WordPress will continue executing the template rendering and will not fing anything, throwing the 'not found page' 
        }
}

Create a plugin with this exact code. Activate the plugin and test typing in the browser http://your_wordpress_site.com/customop_uri_path.

The registers functions deals with permalink structure, and are executed just in the plugin activation or plugin deactivation (to clean the permalinks entries, in case of not using anymore the plugin).

The real magic is done by the following code. There are two functions: one used in the plugin activation to create a new rewrite rule and add a permalink entry, and the other constrols the output display. The get_query_var function scans for uri arguments if there are your custom uri path created previously. If so, then, it executes the code to write your custom output. DON'T FORGET THE FINAL EXIT, or it will fall in the not found content page.

Scans for any ocurrence of 'customop_uri_path' in the code to customize your own uri address of your custom output. Honestly talking, I still did not understood whats going on in the add_rewrite_tag and add_permastruct arguments. So, just replace with your own uri path.

Also, assure that your apache rewrite module are working properly and your WordPress installation are setted to use the permalinks, or you will not see the module works.

  • if you're not going to use the main query, there's no reason to wait until template_redirect, you could hook parse_request instead and save some time and memory. – Milo Jun 20 '16 at 3:22
  • @danilocgsilva Could your example be used and cause the active theme's default page template to be used while still having control of the_content within the plugin? – rwkiii Sep 18 '16 at 20:56

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.