Routing to callback functions in WordPress – 06
June 5, 2014
I've sorted the options available to add an admin interface possibility of routes added using WP Router and decided to go with the easier option of using a page
post-type metabox.
That would allow plugins and enhancements that work on pages and their meta information to keep working and allow an easy addition of pages to navigation menus.
The master plan
The idea is to persist routes and some meta information about them in the database to be able to later fetch that information and generate ad-hoc permalinks while allowing a user to choose which content a page should display: either the page content itself or the result of a route endpoint.
Can I generate permalinks?
The end point of the struggle is to be able to generate the correct permalink to the route when adding a page and choosing it to be a route placeholder; sure WordPress comes with the possibility to edit the permalink [caption id="attachment_1061" align="aligncenter" width="1024"][](http://theaveragedev.local/wordpress/wp-content/uploads/2014/06/2014-06-05-at-18.46.png) Generated permalink[/caption] [caption id="attachment_1062" align="aligncenter" width="1024"][
](http://theaveragedev.local/wordpress/wp-content/uploads/2014/06/2014-06-05-at-18.47.png) Cusotm made permalink[/caption] but while I'd like to leave the user that possibility I'd also like to be able control the permalink generation altogether for a smoothest experience.
Digging for hooks
How does WordPress generates the page permalink? After some code digging I've found out it does in two distinct points relying but on the same functions; when the page is first rendered PHP will take care of populating the "Permalink" field using code defined in the /wp-admin/edit-form-advanced.php
file at about line 449
<?php
$sample_permalink_html = $post_type_object->public ? get_sample_permalink_html($post->ID) : '';
$shortlink = wp_get_shortlink($post->ID, 'post');
$permalink = get_permalink( $post->ID );
if ( !empty( $shortlink ) && $shortlink !== $permalink && $permalink !== home_url('?page_id=' . $post->ID) )
$sample_permalink_html .= '<input id="shortlink" type="hidden" value="' . esc_attr($shortlink) . '" /><a href="#" class="button button-small" onclick="prompt('URL:', jQuery(\'#shortlink\').val()); return false;">' . __('Get Shortlink') . '</a>';
if ( $post_type_object->public && ! ( 'pending' == get_post_status( $post ) && !current_user_can( $post_type_object->cap->publish_posts ) ) ) {
$has_sample_permalink = $sample_permalink_html && 'auto-draft' != $post->post_status;
?>
<div id="edit-slug-box" class="hide-if-no-js">
<?php
if ( $has_sample_permalink )
echo $sample_permalink_html;
?>
</div>
<?php
}
?>
</div>
<?php
wp_nonce_field( 'samplepermalink', 'samplepermalinknonce', false );
?>
after some code reading I get that the get_permalink
function will be used to generate the permalink to the page or post if the page or post is not a newly created one; in that case WordPress will trigger an AJAX call to generate a temporary permalink taking the page title into account. Again in code that is defined in the /wp-admin/js/post.js
file at line 316
}).on( 'after-autosave.update-post-slug', function() {
// Create slug area only if not already there
// and the title field was not focused (user was not typing a title) when autosave ran
if ( ! $('#edit-slug-box > *').length && ! titleHasFocus ) {
$.post( ajaxurl, {
action: 'sample-permalink',
post_id: $('#post_ID').val(),
new_title: $('#title').val(),
samplepermalinknonce: $('#samplepermalinknonce').val()
},
function( data ) {
if ( data != '-1' ) {
$('#edit-slug-box').html(data);
}
}
);
}
});
and the callback function answering to that AJAX call is defined in the /wp-admin/includes/ajax-actions.php
file
function wp_ajax_get_permalink() {
check_ajax_referer( 'getpermalink', 'getpermalinknonce' );
$post_id = isset($_POST['post_id'])? intval($_POST['post_id']) : 0;
wp_die( add_query_arg( array( 'preview' => 'true' ), get_permalink( $post_id ) ) );
}
and it's, once again, get_permalink
.
Next
I will probably tap into the pre_post_link
and post_link
filters defined into the get_permalink
function to be able to work some magic on the permalink generation to suit my needs.